ZeroStarter

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, exports AppType for type-safe RPC
  • src/routers/: API route handlers
    • index.ts: Barrel re-exporting every router
    • auth.ts: Authentication routes (Better Auth handler)
    • agents.ts: Local-only agent sign-in (/api/agents/sign-in-as)
    • v1.ts: Protected API routes requiring authentication
    • waitlist.ts: Public waitlist signup + approximate count (/api/waitlist)
  • src/middlewares/: Custom middlewares
    • auth.ts: Authentication middleware for protected routes
    • rate-limiter.ts: Rate limiting middleware
  • src/lib/error.ts: Centralized errorHandler (the app.onError switchboard) that shapes every thrown ApiError / HTTPException / ZodError into a consistent { error: { code, message } } envelope; routes throw new ApiError(...) for domain codes from the shared ErrorCode union

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 endpoints
    • waitlist/: Public waitlist landing. A freshly scaffolded fork's home (page.tsx) redirects here until you build your product; remove it by deleting app/waitlist/, routers/waitlist.ts, and schema/waitlist.ts
    • og/: Dynamic Open Graph image routes
    • robots.ts: robots.txt generation
    • sitemap.ts: Sitemap generation
  • src/components/: React components
    • ui/: Shadcn UI components
    • sidebar/: Navigation sidebar components
  • src/lib/: Shared utilities
    • api/client.ts: Type-safe API client using Hono RPC
    • auth/: Authentication client and utilities (including console.ts, the /console access 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 the docs/ helpers
  • content/: MDX content
    • docs/: Documentation pages
    • blog/: Blog posts

packages/auth/

Shared authentication logic using Better Auth.

  • src/index.ts: Auth configuration with database adapter and social providers
  • src/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 admin plugin (gates the entire /console area by role === "admin")
  • Exports session types for type safety

packages/db/

Database schema and configuration using Drizzle ORM.

  • src/schema/: Database table definitions
    • auth.ts: User, session, account, verification, organization, member, team, teamMember, and invitation tables
    • waitlist.ts: Public waitlist signup table
  • drizzle/: Generated migrations
  • drizzle.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, plus VERSION, GIT_SHA, BUILD_VERSION, getBuildVersion, the NODE_ENV enum, and the env checkers isLocal/isDevelopment/isTest/isStaging/isProduction). BUILD_VERSION and getBuildVersion are the ones actually consumed (for example in web/next/src/lib/config.ts).
  • src/api-hono.ts: API server environment variables
  • src/auth.ts: Authentication environment variables
  • src/db.ts: Database environment variables
  • src/web-next.ts: Frontend environment variables (client and server)
  • src/lib/: constants.ts (the NODE_ENV enum, VERSION/GIT_SHA/BUILD_VERSION, getBuildVersion, and the env checkers isLocal/isDevelopment/isTest/isStaging/isProduction) and utils.ts (dotenv loader, redaction)

packages/config/

Shared config for the workspace:

  • tsconfig.json: The TypeScript base, extended by every package.
  • tsdown.ts: The tsdown factory (definePackageConfig) that the backend packages' tsdown.config.ts files call. It lives at the package root (exported as @packages/config/tsdown), not under src/.
  • 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 both api/hono and web/next.

Key Files

FilePurpose
package.jsonRoot package with workspace configuration and scripts
turbo.jsonTurborepo build configuration and global environment variables
lefthook.ymlGit hooks configuration for linting and formatting
.envEnvironment 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.