Skip to content

paralect/ship-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

69 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Ship

Full-stack TypeScript starter β€” TanStack Start + Hono + oRPC + Drizzle + PostgreSQL.

Scaffolds in one of two shapes: full-stack (apps/api + apps/web) or web-only (apps/web alone, with backend logic in TanStack Start server functions).

Tech Stack

Layer Technologies
Web Vite + TanStack Start (SPA mode), TanStack Router (file-based), TanStack Query, react-hook-form, zod, shadcn/ui, Tailwind v4
API Hono, oRPC (RPCHandler + OpenAPIHandler), zod validation, filesystem-routed resources auto-generated by codegen-router
Database Drizzle ORM + PostgreSQL. @ship/db DbService<T> wrappers with typed transaction() and mutation event hooks. Flat methods (findFirst/find/findPage/…) surface with/columns relation loading via Drizzle's relational query builder (no .query namespace on the service) and carry a relations generic.
Auth better-auth β€” email/password + verification + reset + Google OAuth
Shared app-constants workspace package, typed API client via import type { AppClient } from 'api'
Infra Docker, Turborepo, Redis, Socket.IO
Deployment Digital Ocean Apps, Kubernetes (DO / AWS EKS)

Prerequisites

  • Node β‰₯22.13.0 (see .nvmrc)
  • pnpm β‰₯9.5.0 (corepack enable)
  • Docker for Postgres + Redis
nvm use && corepack enable

Quick start

pnpm install
pnpm start            # spins up infra (postgres + redis), runs codegen + migrations, then api + web

Web: http://localhost:3002 Β· API: http://localhost:3001 Β· API docs: http://localhost:3001/docs Β· Email preview: http://localhost:4000 Β· DB studio: https://local.drizzle.studio

Common commands

Command What it does
pnpm start Boots infra + everything in dev (alias for infra:postgres + turbo-start).
pnpm infra:postgres Redis + Postgres only.
pnpm turbo-start Turborepo dev (assumes infra is running).
pnpm --filter api dev API only on :3001.
pnpm --filter web dev Web only on :3002.
pnpm --filter api codegen Regenerate src/router.ts, src/contract.ts, src/db.ts.
pnpm --filter api generate New Drizzle migration from schema diff.
pnpm --filter api migrate Apply pending migrations.
pnpm --filter api seed:dev Seed dev data (if present).
pnpm --filter api tsc --noEmit / pnpm --filter web tsc --noEmit Typecheck.
pnpm admin:set <email> Promote a user to admin.
pnpm dashboard Drizzle Studio β€” DB schema/relations viewer + query runner on :4983 (also auto-launched by pnpm start).

Plugins

Extend the template with pre-built features. Plugins live in <repo-root>/plugins/ and merge into the template via pnpm plugin:dev.

# Run in dev mode (watches plugin files, re-merges into plugin-dev-server/)
cd template
pnpm plugin:dev ../plugins/auth-starter ../plugins/admin

# Permanently copy plugin files into the template (like shadcn add)
pnpm plugin:install <git-url>
pnpm plugin:uninstall <name>
pnpm plugin:list

Available plugins: auth-starter, admin, notes, ai-chat, mailer, cloud-storage. See the top-level PLUGINS.md for the catalog and the layout convention.

Project layout

template/
β”œβ”€β”€ apps/
β”‚   β”œβ”€β”€ api/                # Hono + oRPC backend (port 3001)
β”‚   β”‚   β”œβ”€β”€ src/resources/<name>/{*.schema.ts, endpoints/, methods/, handlers/}
β”‚   β”‚   β”œβ”€β”€ src/{db,router,contract}.ts   # auto-generated by scripts/codegen-*.ts
β”‚   β”‚   β”œβ”€β”€ src/{auth,server,endpoint,event-bus}.ts
β”‚   β”‚   β”œβ”€β”€ src/middlewares/               # global/ + gates (is-authorized, is-admin, can-access, can-edit)
β”‚   β”‚   └── drizzle/                       # migration files
β”‚   └── web/                # Vite + TanStack Start SPA (port 3002)
β”‚       β”œβ”€β”€ src/routes/                    # TanStack Router file routes
β”‚       β”œβ”€β”€ src/components/{ui,Table,app-drawer,pill-tab-bar}.tsx
β”‚       β”œβ”€β”€ src/layouts/main-layout/{*, content-layout}.tsx
β”‚       β”œβ”€β”€ src/hooks/use-api.hook.ts      # useApiQuery / useApiMutation / useApiForm
β”‚       └── src/services/api-client.service.ts
β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ db/                 # @ship/db (DbService<T> wrapper + MutationEvent types)
β”‚   β”œβ”€β”€ emails/             # @ship/emails (Resend + React Email templates)
β”‚   β”œβ”€β”€ cloud-storage/      # @ship/cloud-storage (S3-compatible)
β”‚   β”œβ”€β”€ app-constants/      # shared enums / constants
β”‚   └── {eslint,prettier,tsconfig}-config/
β”œβ”€β”€ plugin-dev-server/      # gitignored merge target for pnpm plugin:dev
β”œβ”€β”€ scripts/plugin.ts       # plugin CLI
└── docker-compose*.yml     # postgres, cloud-storage flavors

Agent docs

Inside template/, see agent_docs/ for the canonical workflows:

  • api_resource_and_endpoint_workflow.md β€” resource layout, the endpoint base builder + middlewares (isAuthorized/isAdmin gates, canAccess/canEdit), transactions, event hooks.
  • web_pages_and_data_access.md β€” file routes, oRPC client, hooks, ported widgets.
  • workflows_dev_build_test.md β€” when to run what.
  • common_failure_modes.md β€” debugging.