---
title: "Project structure"
description: "Where code lives in a generated Taman monorepo, and which packages stay on npm."
canonical_url: "https://vinicunca.dev/taman/getting-started/project-structure"
---
# Project structure

> Where code lives in a generated Taman monorepo, and which packages stay on npm.

Paths below use the default `@taman/` scope. After `create-taman --scope acme`, every `@taman/` name becomes `@acme/`.

## Top level

```text
apps/
  web/                 @taman/web     Vue 3 SPA (Vite)
  api/                 @taman/api     Nitro v3 API (Cloudflare Workers)
packages/
  shell/               browser-only workspace packages
  server/              db-pg, emails
  shared/              api-contract, rbac, constants
docker-compose.yml     Postgres 18 on host port 5437
pnpm-workspace.yaml    catalog + workspace globs
nx.json                nx project graph
template.manifest.ts   only in the source repo — removed on generate
```

Published packages (`@vinicunca/taman-core`, `taman-ui`, `request`, `create-taman`, and `internal/*`) exist in the **source** repository. Generated projects install them from npm.

## Web app (`apps/web`)

| Path | Role |
| --- | --- |
| `src/main.ts` | `initPreferences` then dynamic `bootstrap` |
| `src/bootstrap.ts` | adapters, Pinia, i18n, access directive, router, Vue Query, pohon, AG Grid |
| `src/preferences.ts` | `defineOverridesPreferences` (home path, app name) |
| `src/router/routes/core.ts` | Root, login, 404 |
| `src/router/routes/modules/*.ts` | Feature routes, auto-loaded |
| `src/router/routes/modules/dev/**` | Example gallery (stripped from generated projects) |
| `src/views/` | Page components (`todo/`, `_core/`) |
| `src/api/orpc.ts` | Typed oRPC client + query utils |
| `src/api/http.ts` | Example REST client (dummyjson) |
| `src/auth/` | better-auth Vue client, session store |
| `src/adapter/` | Form + component adapters for taman-ui |
| `src/locales/langs/` | App message JSON (`en-US`, `id-ID`) |

Import alias: `#/*` → `./src/*`.

## API (`apps/api`)

| Path | Role |
| --- | --- |
| `nitro.config.ts` | Worker name, Durable Object, queues, `send_email`, runtimeConfig, port `8788` |
| `server/routes/api/auth/[...all].ts` | better-auth |
| `server/routes/api/rpc/[...path].ts` | oRPC |
| `server/routes/healthz/` | Liveness `{ status: 'ok' }` |
| `server/routes/readyz/` | Readiness (database) |
| `server/rpc/base.ts` | `os` / `authed` procedures |
| `server/rpc/router.ts` | `menu` + `todo` routers |
| `server/domains/<feature>/` | repo + service |
| `server/auth/` | better-auth instance, emails, org resolution |
| `server/email/` | sender, dispatcher, queue consumer |
| `server/realtime/publisher.ts` | Durable Object vs in-memory publisher |
| `scripts/seed-admin.ts` | Dev admin user and its `demo` organization |
| `scripts/seed-todos.ts` | Sample todos |
| `exports.cloudflare.ts` | `TodoPublisherObject` Durable Object class |

Import alias: `#*` → `./server/*`.

## Workspace packages

### `packages/shell`

Browser-only. Stay in the generated project.

| Package | Role |
| --- | --- |
| `@taman/access` | `v-access` directive, `useAccess`, `generateAccessible` |
| `@taman/app-ui` | App wrappers around taman-ui |
| `@taman/composables` | `useAppTamanConfig` and related |
| `@taman/designs` | Theme tokens, UnoCSS, `virtual:pohon-theme` |
| `@taman/layouts` | Core layout chrome (header, sidebar, tabs) |
| `@taman/locales` | vue-i18n setup shared with the app |
| `@taman/stores` | Pinia stores (access, user, tabbar, …) |
| `@taman/types` | App-level types |
| `@taman/utils` | Route helpers, nprogress, loading overlay |

### `packages/server`

| Package | Role |
| --- | --- |
| `@taman/db-pg` | Drizzle client + `src/schemas` |
| `@taman/emails` | Maizzle templates (`invitation`, `reset-password`, `verify-email`) |

### `packages/shared`

Used by **both** apps.

| Package | Role |
| --- | --- |
| `@taman/api-contract` | oRPC contract (`menu`, `todo`) |
| `@taman/rbac` | better-auth access control + `USER_ROLES` / `ORGANIZATION_ROLES` |
| `@taman/constants` | `LOGIN_PATH`, languages; re-exports taman-core constants |

## What generate removes

From `template.manifest.ts`:

- `packages/taman-core/**`, `taman-ui/**`, `request/**`, `create-taman/**`, `internal/**`
- `.github/**`, `.changeset/**`, `scripts/release/**`, `scripts/deploy/**`, `docs/**`, `tasks/**`
- Example gallery: `apps/web/src/views/examples/**`, `routes/modules/dev/examples.ts`, `locales/*/examples.json`
- `CLAUDE.md`, `AGENTS.md`, Graphify output, `.gitpod.yml`, `template.manifest.ts`, `pnpm-lock.yaml`

The **todo** feature stays as the reference implementation.


## Sitemap

See the full [sitemap](https://vinicunca.dev/sitemap.md) for all pages.
