# Project Structure and Organization

> Understand the current monorepo layout, route tree, and key config locations.

*Canonical: https://makerkit.dev/docs/tanstack-drizzle/project-structure/overview*

---

The TanStack Start Drizzle SaaS Kit is organized as a pnpm + Turborepo monorepo.

## Top-Level Layout

```text
apps/                 # runnable apps
packages/             # shared packages
tooling/              # shared tooling and MCP server
turbo/                # code generators
docs/                 # documentation
```

## Apps

```text
apps/
├── web/              # main TanStack Start app
└── e2e/              # Playwright test app
```

### `apps/web`

This is a TanStack Start (Vite + Nitro) application. Source lives under `src/`, not a Next.js `app/` directory.

Key locations:

```text
apps/web/
├── src/
│   ├── routes/           # file-based route tree (TanStack Router)
│   ├── components/       # app components (kebab-case)
│   ├── config/           # typed app config (app, auth, feature flags, ...)
│   ├── lib/              # server functions, loaders, helpers
│   ├── styles/           # global styles
│   ├── router.tsx        # router instance
│   ├── start.ts          # global request middleware (CSRF, security headers)
│   ├── routeTree.gen.ts  # generated route tree (do not edit by hand)
│   └── env.d.ts          # typed import.meta.env
├── content/              # CMS content (posts, changelog, documentation)
├── public/               # static assets
├── vite.config.ts        # Vite + TanStack Start + Nitro config
└── tsr.config.json       # TanStack Router generator config
```

Notes:

- app config files live in `apps/web/src/config/`
- the sidebar/navigation config lives in `apps/web/src/config/navigation.config.tsx`
- inside `apps/web`, the `#/*` import alias maps to `./src/*` (e.g. `#/config/app.config`)
- Drizzle config does **not** live in `apps/web`; it lives in `packages/database/drizzle.config.mjs`

## Routing

Routes are file-based under `apps/web/src/routes/`. TanStack Router generates `routeTree.gen.ts` from these files.

```text
src/routes/
├── __root.tsx            # root route: shell, head, providers, beforeLoad
├── _public/              # marketing/public pages (pathless group)
├── _authenticated/       # signed-in app (dashboard, settings, billing)
├── _invitation/          # invitation acceptance flow
├── auth/                 # sign-in, sign-up, password reset, MFA verify
├── admin/                # admin pages
├── help/                 # documentation/help pages
├── api/                  # server routes (auth catch-all, upload, healthcheck)
├── sitemap[.]xml.ts      # sitemap server route
└── robots[.]txt.ts       # robots server route
```

Route conventions (TanStack Router):

- a pathless layout group is a folder prefixed with `_` (e.g. `_public/`, `_authenticated/`) with a `route.tsx` layout
- a folder/segment route uses `route.tsx`; its default child is `index.tsx`
- dynamic params use `$param` (e.g. `blog/$slug.tsx`); catch-all uses `$.tsx` (e.g. `help/$.tsx`)
- API/server routes are plain `.ts` files under `api/` using `createFileRoute(...).methods(...)` / server handlers

There is **no** `[locale]` path segment. Locale is cookie-based (`LOCALE_COOKIE` / `detectLocale()`); see the [Internationalization](../internationalization/overview) docs.

## Naming Conventions

- routes: `route.tsx`, `index.tsx`, `$param.tsx`, `$.tsx`
- loaders/server functions: colocated in `src/lib/**` (e.g. `*.functions.ts`) or inside the route file
- schemas: `*.schema.ts`
- components: `kebab-case.tsx`

## Package Layout

Most packages expose from `src/index.ts` and define additional exports in `package.json`.

Use `pnpm turbo gen package` if you need a new shared package.

---

**Next:** [Packages →](./package-architecture)
