Tech Stack
Architecture Overview
Section titled “Architecture Overview”TheTerms is a Turborepo monorepo with a Next.js 14 web application at its core. The internal backend uses tRPC for type-safe API communication, Prisma for database access, and NextAuth for authentication. The public REST API is a separate, already-shipped surface built on Hono with a hand-written OpenAPI 3.1 spec — it doesn’t sit on top of tRPC.
Browser → Next.js App Router → tRPC Router → Prisma ORM → PostgreSQL ↕ NextAuth (JWT) ↕ Redis (cache)Technology Choices
Section titled “Technology Choices”| Layer | Technology | Why |
|---|---|---|
| Monorepo | Turborepo + pnpm workspaces | Shared code between packages without publish cycles |
| Framework | Next.js 14 (App Router) | Server components, streaming, output: "standalone" for Docker |
| Internal API | tRPC v10 + React Query | End-to-end type safety from database to UI, no code generation |
| Public REST API | Hono + @hono/zod-openapi + Scalar | Hand-written OpenAPI 3.1 spec, interactive reference UI, independent of the tRPC layer |
| Auth | NextAuth v5 (beta) | JWT sessions, credential provider |
| ORM | Prisma 6 | Type-safe queries, automatic migrations, PostgreSQL support |
| Database | PostgreSQL 14+ | ACID transactions, JSON support, mature ecosystem |
| Billing | Stripe | Subscription tiers and usage-based billing |
| Redis | Redis 7 | Provisioned via Docker Compose; not currently used by application code — rate limiting today is in-memory per instance, not Redis-backed |
| Resend | Developer-friendly API, React Email templates | |
| UI | Tailwind CSS + shadcn/ui | Utility-first styling, accessible component primitives |
| Rich Text | TipTap v3 | Extensible ProseMirror-based editor, SSR-compatible |
| Drag & Drop | dnd-kit | Accessible drag-and-drop for clause reordering |
| Testing | Vitest + Testing Library | Fast unit/integration tests with live database |
Key Architectural Decisions
Section titled “Key Architectural Decisions”tRPC internally, a separate hand-written REST API for external consumers
Section titled “tRPC internally, a separate hand-written REST API for external consumers”TheTerms uses tRPC instead of REST for the internal API that powers the web app. This provides compile-time type safety between the server and client — when a router procedure changes its input or output type, TypeScript catches mismatches immediately.
The public REST API is a distinct, already-shipped layer built directly on Hono with its own hand-written OpenAPI 3.1 spec (@hono/zod-openapi) — it does not sit on top of tRPC or generate its spec from it. See API Reference for the live endpoint list.
JWT Sessions over Database Sessions
Section titled “JWT Sessions over Database Sessions”NextAuth is configured with JWT strategy. Sessions are stored in signed cookies rather than a database table. This avoids a database lookup on every request and simplifies horizontal scaling. The trade-off is that session revocation requires token expiry rather than immediate invalidation.
Standalone Docker Output
Section titled “Standalone Docker Output”The Next.js output: "standalone" setting produces a self-contained Node.js server with only the required dependencies. This dramatically reduces the Docker image size compared to copying the full node_modules.
Prisma Binary Targets
Section titled “Prisma Binary Targets”The Prisma schema includes binaryTargets: ["native", "linux-musl-openssl-3.0.x"] to support both local development (macOS/Linux) and Alpine-based Docker containers.