Project Structure
Understand the monorepo structure and organization of ZeroStarter.
Overview
ZeroStarter uses a monorepo architecture to organize code into logical packages. This structure enables code sharing, type safety, and efficient development workflows.
Project Structure
This project is a monorepo organized as follows:
.
├── api/
│ └── hono/ # Backend API server (Hono)
├── web/
│ └── next/ # Frontend application (Next.js)
│ └── content/ # Documentation and blog content (MDX)
└── packages/
├── auth/ # Shared authentication logic (Better Auth)
├── db/ # Database schema and Drizzle configuration
├── env/ # Type-safe environment variables
└── config/ # Shared config: TS base, tsdown factory, and src/site.ts (brand identity)Directory Details
api/hono/
The backend API server built with Hono.
src/index.ts: Main application entry point, exportsAppTypefor type-safe RPCsrc/routers/: API route handlersindex.ts: Barrel re-exporting every routerauth.ts: Authentication routes (Better Auth handler)agents.ts: Local-only agent sign-in (/api/agents/sign-in-as)v1.ts: Protected API routes requiring authenticationwaitlist.ts: Public waitlist signup + approximate count (/api/waitlist)
src/middlewares/: Custom middlewaresauth.ts: Authentication middleware for protected routesrate-limiter.ts: Rate limiting middleware
src/lib/error.ts: CentralizederrorHandler(theapp.onErrorswitchboard) that shapes every thrownApiError/HTTPException/ZodErrorinto a consistent{ error: { code, message } }envelope; routesthrow new ApiError(...)for domain codes from the sharedErrorCodeunion
web/next/
The frontend application built with Next.js 16.
src/app/: Next.js App Router pages and layouts(content)/: Documentation and blog pages(protected)/: Authenticated user pages (dashboard)(console)/: Access-gated privileged admin console at/console(docs live under/console/docs)(llms.txt)/: Auto-generated AI documentation endpointswaitlist/: Public waitlist landing. A freshly scaffolded fork's home (page.tsx) redirects here until you build your product; remove it by deletingapp/waitlist/,routers/waitlist.ts, andschema/waitlist.tsog/: Dynamic Open Graph image routesrobots.ts:robots.txtgenerationsitemap.ts: Sitemap generation
src/components/: React componentsui/: Shadcn UI componentssidebar/: Navigation sidebar components
src/lib/: Shared utilitiesapi/client.ts: Type-safe API client using Hono RPCauth/: Authentication client and utilities (includingconsole.ts, the/consoleaccess gate)config.ts: Application configuration- Content and SEO helpers:
blog.ts,blog-policy.ts,llms.ts,og-image.tsx,fumadocs.tsx,source.ts,sort-by-meta.ts, and thedocs/helpers
content/: MDX contentdocs/: Documentation pagesblog/: Blog posts
packages/auth/
Shared authentication logic using Better Auth.
src/index.ts: Auth configuration with database adapter and social providerssrc/lib/utils.ts: Cookie domain and prefix helpers (getCookieDomain,getCookiePrefix) for cross-subdomain and environment-specific cookies- Supports optional GitHub and Google OAuth (each enabled only when its credentials are set; the UI shows only configured providers via
GET /api/auth/providers) - Organization and teams plugin for multi-tenant support, the Better Auth OpenAPI plugin, and the
adminplugin (gates the entire/consolearea byrole === "admin") - Exports session types for type safety
packages/db/
Database schema and configuration using Drizzle ORM.
src/schema/: Database table definitionsauth.ts: User, session, account, verification, organization, member, team, teamMember, and invitation tableswaitlist.ts: Public waitlist signup table
drizzle/: Generated migrationsdrizzle.config.ts: Drizzle Kit configuration
packages/env/
Type-safe environment variables using @t3-oss/env-core.
src/index.ts: Barrel exporting shared helpers and version info (getSafeEnv, plusVERSION,GIT_SHA,BUILD_VERSION,getBuildVersion, theNODE_ENVenum, and the env checkersisLocal/isDevelopment/isTest/isStaging/isProduction).BUILD_VERSIONandgetBuildVersionare the ones actually consumed (for example inweb/next/src/lib/config.ts).src/api-hono.ts: API server environment variablessrc/auth.ts: Authentication environment variablessrc/db.ts: Database environment variablessrc/web-next.ts: Frontend environment variables (client and server)src/lib/:constants.ts(theNODE_ENVenum,VERSION/GIT_SHA/BUILD_VERSION,getBuildVersion, and the env checkersisLocal/isDevelopment/isTest/isStaging/isProduction) andutils.ts(dotenv loader, redaction)
packages/config/
Shared config for the workspace:
tsconfig.json: The TypeScript base, extended by every package.tsdown.ts: Thetsdownfactory (definePackageConfig) that the backend packages'tsdown.config.tsfiles call. It lives at the package root (exported as@packages/config/tsdown), not undersrc/.src/site.ts: The brand/site identity (name, description, social links, injectable content), exported as@packages/config/site. This is the single source a fork edits to rebrand, consumed by bothapi/honoandweb/next.
Key Files
| File | Purpose |
|---|---|
package.json | Root package with workspace configuration and scripts |
turbo.json | Turborepo build configuration and global environment variables |
lefthook.yml | Git hooks configuration for linting and formatting |
.env | Environment variables (create from .env.example) |
Bun catalog convention
The root package.json defines a catalog: block listing a single version for each shared dependency. Every workspace then references those deps with catalog: instead of a literal version, so the whole monorepo stays on one version per package. The .github/scripts/deps-manager.ts script normalizes and sorts these entries; it runs on postinstall and via lint-staged whenever a package.json is staged.