| name | platform-project-structure |
| description | Complete project structure and file organization guide for the `apps/platform` Next.js workspace. Use when creating new files, adding features, placing API routes, defining database schemas, or deciding where any new code belongs. Triggers on questions about where to put files, how to name things, or how the platform codebase is organized. |
Platform Workspace โ Project Structure
apps/platform is a Next.js 14+ App Router application. Every new file must be placed according to the conventions below. Deviating from these conventions is an architecture violation.
Top-Level Directory Map
apps/platform/
โ
โโโ app/ # Next.js App Router โ routes and API handlers
โ โโโ (auth)/ # Public auth pages (login, signup)
โ โโโ (backend)/ # Server-only: API routes, tRPC handlers, GitHub webhooks
โ โ โโโ api/
โ โ โ โโโ trpc/ # tRPC HTTP handler
โ โ โ โโโ upload/ # File upload API routes
โ โ โโโ auth/ # Auth callbacks (GitHub OAuth)
โ โ โโโ github/ # GitHub App webhook handlers
โ โโโ (platform)/ # Authenticated platform UI pages
โ โโโ analytics/
โ โโโ architecture/
โ โโโ dashboard/
โ โโโ installation-success/
โ โโโ learn/
โ โโโ skills-library/
โ โโโ production-grade-projects/
โ โโโ repositories/
โ โโโ subscription/
โ
โโโ components/ # Shared UI components used across the entire platform
โ
โโโ const/ # App-wide constants (auth, config values)
โ
โโโ database/ # Database layer (Drizzle ORM)
โ โโโ core/ # Drizzle client setup
โ โโโ migrations/ # SQL migration files
โ โโโ models/ # Query models (data access per entity)
โ โโโ schemas/ # Drizzle table schema definitions
โ โโโ type.ts # Shared database types
โ
โโโ hooks/ # Shared custom React hooks
โ
โโโ layout/ # Global React providers / layout wrappers
โ โโโ GlobalProvider/
โ
โโโ lib/ # Utility libraries and third-party integrations
โ โโโ logger/
โ โโโ server/
โ โโโ trpc/
โ
โโโ server/ # tRPC router definitions (server-side only)
โ โโโ routers/
โ โ โโโ lambda/ # tRPC lambda routers per entity
โ โโโ service/ # Server-side service logic (called by routers)
โ
โโโ service/ # Client-side service layer (called by stores/components)
โ โโโ chunk/
โ โโโ document/
โ โโโ installation/
โ โโโ organization/
โ
โโโ store/ # Zustand global state stores
โ โโโ document/
โ โโโ file/
โ โโโ middleware/
โ โโโ organization/
โ โโโ index.ts
โ โโโ initialState.ts
โ โโโ selectors.ts
โ โโโ slices/
โ โโโ store.ts
โ
โโโ types/ # Shared TypeScript types
โ
โโโ utils/ # Shared utility functions
โโโ env.ts
โโโ server/
โโโ supabase/
Naming Conventions
| Artifact | Convention | Example |
|---|
| React components | PascalCase | AppSidebar.tsx, LoginForm.tsx |
| Hooks | camelCase with use prefix | useInstallation.ts, useOrganizations.ts |
| Utility functions / libs | camelCase | generateGithubAppJwt.ts, langgraph-client.ts |
| Types / interfaces | PascalCase | InstallationType, GraphTypes |
| Constants | camelCase (config objects), UPPER_SNAKE_CASE (true constants) | auth.ts exports AUTH_COOKIE_NAME |
| Database schemas | camelCase filename per entity | organization.ts, repository.ts |
| Database models | camelCase filename per entity | organization.ts, document.ts |
| tRPC routers | camelCase filename per entity | organization.ts, installation.ts |
| Store slices | directory per entity, nested slices/ | store/organization/slices/organization/ |
Import Path Rules
- Use
@/ for all imports within apps/platform:
import { Button } from '@/components/ui/button'
import { db } from '@/database/core'
import { organizationRouter } from '@/server/routers/lambda/organization'
- Use
@repo/* for shared monorepo packages:
import { Editor } from '@repo/editor'
import { cn } from '@repo/ui'
- Never use relative
../../ paths that escape the workspace root.
Data Flow
React UI (app/(platform)/)
โ Zustand Store (store/)
โ Client Service (service/)
โ tRPC lambda (server/routers/lambda/)
โ Server Service (server/service/)
โ Database Model (database/models/)
โ PostgreSQL (Supabase)
- Components render state from stores and call store actions.
- Stores call client services for data fetching and mutations.
- Client services (
service/) make tRPC calls to the backend.
- tRPC routers (
server/routers/lambda/) receive requests, call server services.
- Server services (
server/service/) contain business logic, call database models.
- Database models (
database/models/) execute Drizzle queries against schemas.
Route Groups
| Group | Purpose |
|---|
app/(auth)/ | Public pages that do not require authentication (login, signup) |
app/(backend)/ | Server-only API routes โ no UI rendered here |
app/(platform)/ | All authenticated platform pages |
- New authenticated pages โ
app/(platform)/<feature>/
- New API routes โ
app/(backend)/api/<resource>/route.ts
- New tRPC handlers โ
app/(backend)/api/trpc/
Database Layer Conventions
database/
โโโ schemas/<entity>.ts # Drizzle table definition โ column names, types, relations
โโโ models/<entity>.ts # Query functions โ CRUD operations for that entity
โโโ migrations/ # Auto-generated migration SQL files (do not edit manually)
โโโ core/ # Drizzle client instantiation
โโโ type.ts # Shared inferred types from schemas
- One file per entity in both
schemas/ and models/.
- Schema files use Drizzle
pgTable definitions only โ no business logic.
- Model files export plain async functions (e.g.
getOrganizationById, createDocument).
- Never import
database/models/ directly from a React component โ always go through server/service/ via tRPC.
Store Conventions (Zustand)
Each store lives in store/<entity>/ and has this structure:
store/<entity>/
โโโ index.ts # Re-exports the store hook
โโโ initialState.ts # State interface + default values
โโโ selectors.ts # Selector functions for derived state
โโโ slices/ # Action slices (one subdirectory per slice)
โโโ store.ts # createStore combining all slices
- Export a single
use<Entity>Store hook from index.ts.
- Keep selectors in
selectors.ts โ never compute derived state inline in components.
- Use plain arrays for list data (
xxxList: XxxItem[]).
- Use Record maps for detail data (
xxxMap: Record<string, Xxx>).
Component Placement
| Type | Location |
|---|
| Shared across multiple pages | components/ |
| Scoped to a single route/feature | app/(platform)/<feature>/components/ (co-located) |
| shadcn/ui primitives | components/ui/ |
| Page-level layout wrappers | layout/ |
| Analytics/metrics UI | components/analytics-ui/ |
Do not create a new top-level directory for components that already have a home above.
Hooks Conventions
- Shared hooks used in 2+ pages โ
hooks/
- Hooks scoped to one page โ co-locate next to the page file
- Always prefix with
use: useInstallation.ts, useOrganizations.ts
API Layer Conventions
See docs/development/api-layer/ for full patterns. Summary:
- All tRPC routers live in
server/routers/lambda/<entity>.ts
- All routers are registered in
server/routers/lambda/index.ts
- The HTTP handler that exposes them lives in
app/(backend)/api/trpc/
- REST-style routes (e.g. file upload, GitHub webhooks) live in
app/(backend)/api/<resource>/route.ts
Types Conventions
types/
โโโ auth.ts # Auth-related types
โโโ asyncTask.ts # Async task types
โโโ graphTypes.ts # Graph / RAG types
โโโ rag.ts # RAG-specific types
โโโ chunk/ # Chunk entity types
โโโ document/ # Document entity types
โโโ files/ # File entity types
- Entity types live in
types/<entity>.ts or types/<entity>/ (directory) when complex.
- Database inferred types (from Drizzle
$inferSelect) are exported from database/type.ts.
- Never use database types directly in components โ define separate view/UI types in
types/.
Utility Libraries (lib/)
lib/ holds integrations with third-party services and app-wide utility modules:
| File/Dir | Purpose |
|---|
lib/trpc/ | tRPC client setup |
lib/logger/ | Structured logging |
lib/server/ | Server-only utilities |
lib/langgraph-client.ts | LangGraph client (browser-safe) |
lib/langgraph-server.ts | LangGraph server helper |
lib/generate-github-app-jwt.ts | GitHub App JWT generation |
lib/pdf.ts | PDF processing |
lib/slack.ts | Slack notifications |
Only add to lib/ when a utility wraps a third-party SDK or is reused across 3+ files.
Configuration Files
| File | Purpose |
|---|
middleware.ts | Auth middleware and route protection |
drizzle.config.ts | Drizzle ORM configuration |
features.json | Feature flags |
next.config.js | Next.js configuration |
utils/env.ts | Validated environment variable exports |
Always import env variables through utils/env.ts โ never use process.env directly in application code.
Checklist โ Adding a New Feature
When adding a new feature (e.g. "widgets"):
Architecture Rules (Enforced)
- No cross-layer imports downward past one step โ components call stores, not services directly.
- No direct database imports in components or stores โ always go through
server/service/ via tRPC.
- No
process.env outside utils/env.ts.
- No barrel re-exports from feature directories โ import files directly to avoid tree-shaking issues.
- Route groups are structural โ
(auth), (backend), (platform) are not URL segments.