Market Intelligence Dashboard for Counter-Strike 2
Track market prices, manage your inventory, and get AI-powered market insights for Counter-Strike 2 items.
Features · Getting Started · Data Synchronization · Scripts · Deployment · License
| Feature | Description |
|---|---|
| Market Overview | Real-time price tracking with CSFloat, Pricempire, and Steam Community Market API. |
| Portfolio Tracker | Manage your CS2 inventory, monitor assets value, purchase history, and margins. |
| Top Movers | Track items experiencing the largest price gains or losses in short/long intervals. |
| Aegis Chat | AI-powered market analysis using Google Gemini, OpenAI GPT, Anthropic Claude, OpenRouter, or 9Router. |
| News Feed | Aggregated Counter-Strike economy and market updates via RSS feeds. |
| Price Analysis | Interactive candlestick price charts using TradingView Lightweight Charts and technical indicators. |
| Responsive UI | Adaptive desktop, tablet, and mobile interface built with CSS Modules. |
- Framework: Next.js 16.1.6 (App Router, React Compiler)
- UI & Styling: React 19.2.3, CSS Modules (Design tokens configured in
src/app/globals.css) - Database & ORM: SQLite (Local development) / Turso (Production libSQL) managed by Prisma 7.4.1 (Generated client in
src/generated/prisma) - Authentication: NextAuth.js (Steam OpenID)
- Charts: TradingView Lightweight Charts &
lightweight-charts-indicators - AI Integrations: Gemini, OpenAI, Anthropic SDKs, plus OpenRouter and 9Router gateway options
- Node.js 20+
- npm, pnpm, or yarn
# Clone the repository
git clone https://github.com/kyokoxdev/CS2Vault.git
cd CS2Vault
# Install dependencies
npm install
# Copy environment variables template and edit values
cp .env.example .env.local
# Generate the Prisma client
npx prisma generate
# Initialize the local SQLite database schema
npx prisma db push
# Seed the default settings and data
npx tsx prisma/seed.ts
# Start the development server
npm run devThe application will run locally at http://localhost:3000.
The application reads variables from .env.local for local development.
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Yes | Path to the local SQLite file (default: file:./dev.db) |
TURSO_DATABASE_URL |
Production | Turso database URL (libsql://...) |
TURSO_AUTH_TOKEN |
Production | Turso authentication token |
CRON_SECRET |
Production | Token to authorize background cron routes |
STEAM_API_KEY |
Yes | Steam Web API Key |
ALLOWED_STEAM_ID |
Yes | Steam64 ID of the user allowed to log in |
CSFLOAT_API_KEY |
Yes | CSFloat API Key |
PRICEMPIRE_API_KEY |
No | Pricempire API Key |
GEMINI_API_KEY |
No | Google AI Studio API Key |
OPENAI_API_KEY |
No | OpenAI API Key |
OPENAI_MODEL |
No | Override default OpenAI model (default: gpt-4o-mini) |
ANTHROPIC_API_KEY |
No | Anthropic Console API Key |
ANTHROPIC_MODEL |
No | Override default Anthropic model (default: claude-opus-4-7) |
OPENROUTER_API_KEY |
No | OpenRouter API Key |
OPENROUTER_BASE_URL |
No | Base URL for OpenRouter (default: https://openrouter.ai/api/v1) |
OPENROUTER_MODEL |
No | Override default OpenRouter model (default: ~openai/gpt-latest) |
NINEROUTER_API_KEY |
No | 9Router gateway key |
NINEROUTER_BASE_URL |
No | Base URL for 9Router (default: http://localhost:20128/v1) |
NINEROUTER_MODEL |
No | Override default 9Router model (default: cc/claude-opus-4-7) |
GOOGLE_CLIENT_ID |
No | Google OAuth client ID (for Gemini OAuth flows) |
GOOGLE_CLIENT_SECRET |
No | Google OAuth client secret |
NEXTAUTH_SECRET |
Yes | App authentication secret (generate with openssl rand -hex 32) |
NEXTAUTH_URL |
Yes | Hostname URL (default: http://localhost:3000) |
TOKEN_ENCRYPTION_KEY |
Yes | Symmetric key for encrypting stored database credentials |
Data refreshes are split between server-side schedulers and client-side triggers:
- Vercel Cron Jobs (configured in
vercel.json):GET /api/syncruns daily (0 4 * * *) to fetch general price updates.GET /api/market/market-cap-syncruns daily (0 8 * * *) to compute weighted market caps.
- External Schedulers (e.g., cron-job.org):
GET /api/intelligence/runmust be configured in an external cron service to run every 5 minutes with theCRON_SECRETauthorization header. This handles candidate scanning via CSFloat and validation via Steam Community Market (SCM). To prevent SCM bans, it executes at most 3 validations per run, respecting SCM limits of 19 requests/minute and 950 requests/day.GET /api/market/price-sync/boundedcan be configured in cron-job.org to run every 10 minutes for lightweight price snapshot refreshes. Use eitherAuthorization: Bearer <CRON_SECRET>orx-cron-secret: <CRON_SECRET>. Defaults arelimit=25,minAgeMinutes=60, andbudgetMs=25000; the route clamps work to stay below cron-job.org's 30-second timeout, skips candle aggregation, and shares the sync lock with the full/api/syncroute.
- Browser Refreshes:
- The application automatically refreshes watchlist and portfolio metrics while a dashboard tab is active using the interval specified by the
priceRefreshIntervalMindatabase setting. - Users can manually trigger a market-cap update in the Settings dashboard.
- The application automatically refreshes watchlist and portfolio metrics while a dashboard tab is active using the interval specified by the
Use cron-job.org for short, frequent pings that stay inside its 30-second timeout. Keep secrets in request headers, not in the URL.
- Create and deploy
CRON_SECRET:- Generate a long random value, for example
openssl rand -hex 32. - Set the same value in Vercel project environment variables as
CRON_SECRET. - Keep
.env.localaligned if testing the cron route locally.
- Generate a long random value, for example
- Create the bounded price refresh job:
- URL:
https://<your-domain>/api/market/price-sync/bounded?limit=25&minAgeMinutes=60&budgetMs=25000 - Method:
GET - Schedule: every 10 minutes
- Headers:
x-cron-secret: <CRON_SECRET>orAuthorization: Bearer <CRON_SECRET> - Expected result: HTTP
200withdata.statusofsuccess,partial,skipped, ortime_budget_exhausted.partialis normal when more stale items remain for the next ping.
- URL:
- Create the intelligence queue job:
- URL:
https://<your-domain>/api/intelligence/run - Method:
GET - Schedule: every 5 minutes
- Headers:
x-cron-secret: <CRON_SECRET>orAuthorization: Bearer <CRON_SECRET> - Expected result: HTTP
200when the queue is processed, paused, or budget-limited; HTTP401means the secret header is missing or wrong.
- URL:
- Enable failure notifications:
- In cron-job.org, enable notifications for failed executions.
- Treat repeated
401responses as a secret mismatch. - Treat repeated timeouts as a signal to lower
limitorbudgetMson the bounded price refresh job.
- Avoid external full sync pings on the free tier:
- Do not point cron-job.org's 30-second jobs at
/api/sync; that route is the legacy full sync path and can run for several minutes. - Keep
/api/syncon Vercel Cron for compatibility, or run it manually only when a full refresh is needed.
- Do not point cron-job.org's 30-second jobs at
Manage the lifecycle using these npm commands:
| Script | Description |
|---|---|
npm run dev |
Start the local hot-reloading Next.js development server. |
npm run build |
Generate Prisma models, run schema migrations/seeding, and compile the Next.js production build. |
npm run start |
Start the Next.js production server. |
npm run lint |
Run ESLint syntax checking. |
npm run test |
Execute Vitest unit and integration tests. |
npm run test:watch |
Run Vitest unit tests in interactive watch mode. |
npm run db:push:turso |
Push local schema changes and run database seeding against production Turso database. |
npm run db:migrate |
Create and apply a new migration locally using SQLite. |
npm run db:studio |
Run the Prisma Studio GUI database manager. |
This project relies on Turso to provide SQLite databases over HTTP for serverless deployments.
- Set up Turso database:
# Install CLI curl -sSfL https://get.tur.so/install.sh | bash # Create database instance turso db create cs2vault # Obtain URL and authentication tokens turso db show cs2vault --url turso db tokens create cs2vault
- Push Schema to Turso:
Configure
TURSO_DATABASE_URLandTURSO_AUTH_TOKENin.env.local, then push:npm run db:push:turso
- Configure Vercel Deployment:
- Connect the repository at Vercel.
- Configure all environment variables in Vercel project settings.
- Set the Next.js Build Command override:
prisma generate && npx tsx prisma/push-schema.ts && next build
- Deploy.
Note: If compilation fails due to memory limits, prepend the build command with: NODE_OPTIONS=--max-old-space-size=4096
GPL v3