Instruction file imported from FindMalek/sonaraem (
.cursor/rules/00-project-overview.mdc). Copyright stays with the author.
Project Overview
What is Sonaraem
Sonaraem is an AI-powered music organization app. It syncs a user's Spotify library, classifies tracks with LLMs, clusters them by embedding similarity, and auto-generates playlists. It is a pnpm + Turborepo monorepo with four Next.js (App Router) apps and shared packages.
Monorepo Structure
Applications
apps/api(api): Next.js API server (port 3002) — oRPC, Better Auth (dashboard + admin), Trigger.dev webhookapps/dashboard(dashboard): Next.js user dashboard (port 3003) — Spotify OAuth, waitlist-gatedapps/web(web): Next.js web app (port 3001) — public waitlist signupapps/admin(admin): Internal admin dashboard (port 3004) — email/password, waitlist approval
Packages
packages/auth: Better Auth factories — separate dashboard (Spotify) and admin (email/password) instancespackages/common: Shared schemas, types, services, Trigger.dev task definitionspackages/config: Sharedtsconfig.base.jsonpackages/core: Initialises DB +dashboardAuth/adminAuth; re-exportsauthas dashboard aliaspackages/db: Drizzle ORM schema + migrations + DB clientpackages/env: Zod-validated env presets (never useprocess.envdirectly)packages/logger: Pino structured loggerpackages/orpc: oRPC routers, procedures, context, and clientpackages/tracing: OpenTelemetry instrumentationpackages/ui: shadcn/ui component library + shared Tailwind configpackages/email: React Email templates + Resend send layer (@sonaraem/email)
Hard Rules
- Never
process.envdirectly. Useimport { env } from "@sonaraem/env/server". - Never construct an LLM provider client directly outside
@sonaraem/ai-provider. Consumers usegetAIModel(task)from@sonaraem/ai-provider— it resolves the model for that task's fixed assigned provider (TASK_PROVIDERinpackages/ai-provider/src/models.ts; each task is pinned to one ofgroq|concentrate, not a global runtime switch).@sonaraem/ai-provideritself is the one place that's allowed to callcreateGroq/createOpenAI. - Never
inngest. Background jobs use@trigger.dev/sdkonly. - All env vars prefixed
SONARAEM_orNEXT_PUBLIC_SONARAEM_. - JSONB progress writes: use
updateStageProgress(runId, stage, val). Never overwrite the full column in concurrent code. - DB driver is conditional.
.neon.techURL →@neondatabase/serverless, otherwise →pg. Do not change this logic.
Git commits
Use conventional prefixes: feat: fix: chore: perf: refactor: (scope optional).
Do not name AI assistants, IDEs, or vendor coding tools in commit messages, PR titles, or PR bodies (e.g. Claude, Cursor, Copilot, ChatGPT, Windsurf). Write commits as a human contributor would. Do not add Co-authored-by: lines for tools.