Use when building end-to-end TypeScript applications — Node backend (Fastify), React/Next frontend, shared types via tRPC or Zod, monorepo with turborepo/nx, Prisma/Drizzle data layer, end-to-end type safety.
Scanned 9/3/2026
Install to Claude Code
npx -y skills add peterbamuhigire/chwezi-dev-engine --skill typescript-full-stack --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Typescript Full Stack?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/peterbamuhigire-typescript-full-stack-chwezi-dev-engine)More formats (shields.io, HTML) on the badges page.
---
name: typescript-full-stack
description: Use when building end-to-end TypeScript applications — Node backend (Fastify), React/Next frontend, shared types via tRPC or Zod, monorepo with turborepo/nx, Prisma/Drizzle data layer, end-to-end type safety.
metadata:
portable: true
compatible_with:
- Codex
- codex
---
# Full-Stack TypeScript
Acknowledgement: Shared by Peter Bamuhigire, techguypeter.com, +256 784 464178.
<!-- dual-compat-start -->
## Use When
- Use when building end-to-end TypeScript applications — Node backend (Fastify), React/Next frontend, shared types via tRPC or Zod, monorepo with turborepo/nx, Prisma/Drizzle data layer, end-to-end type safety.
## Evidence Produced
| Category | Artifact | Format | Example |
|----------|----------|--------|---------|
| Correctness | Full-stack contract test plan | Markdown doc covering Fastify route + tRPC router + Prisma schema contract tests | `docs/ts/full-stack-tests.md` |
## References
- Use the `references/` directory for deep detail after reading the core workflow below.
<!-- dual-compat-end -->
Build and maintain apps where the same types flow from database to backend to frontend to mobile. Zero runtime type drift between layers.
**Prerequisites:** Load `typescript-effective` for production idioms. Load `typescript-mastery` for type-system depth.
## When this skill applies
- Greenfield TypeScript web app (React + Node).
- Unifying a split JS frontend + JS backend under TypeScript.
- Refactoring an Express/JS backend into a typed Fastify/TS backend while keeping the frontend running.
- Setting up a monorepo with shared types across packages.
## Architecture baseline
```text
+----------------------------------+
| apps/web (Next.js) |
| apps/mobile (Expo RN) |
| apps/api (Fastify) |
| packages/schemas (Zod) |---> source of truth for types
| packages/api-client (tRPC / fetch)
| packages/db (Prisma client)
| packages/ui (shadcn-like components)
| packages/config (tsconfig, eslint, prettier)
+----------------------------------+
```
- **Zod schemas** are the single source of truth; TS types are inferred.
- **tRPC** for internal APIs (no OpenAPI needed — types flow).
- **REST + OpenAPI** only when external clients consume the API. Use `ts-rest` or `zod-to-openapi`.
- **Prisma** for SQL-first data layer; **Drizzle** when you want SQL in view and finer control.
- **Auth** via Lucia, better-auth, or Clerk — not rolling your own.
## Monorepo with turborepo
```text
pnpm init -w
pnpm add -D turbo
```
`turbo.json` defines pipeline (`build`, `test`, `lint`, `type-check`) with caching. Remote cache on Vercel or self-hosted.
Rule: every package has its own `tsconfig.json` extending `packages/config/tsconfig.base.json`. Project references enable incremental typecheck.
See `references/monorepo-turborepo.md`.
## Fastify backend (TS-first)
```ts
import Fastify from "fastify";
import { z } from "zod";
const app = Fastify({ logger: true });
const Params = z.object({ id: z.string().uuid() });
app.get("/users/:id", async (req, reply) => {
const { id } = Params.parse(req.params);
const user = await db.user.findUnique({ where: { id } });
if (!user) return reply.code(404).send({ error: "not_found" });
return user;
});
```
Fastify beats Express for TS: first-class hooks, schema validation, plugin system, lifecycle typing. See `references/fastify-backend.md`.
## tRPC — end-to-end types without OpenAPI
```ts
// packages/api/src/router.ts
import { initTRPC } from "@trpc/server";
import { z } from "zod";
const t = initTRPC.create();
export const appRouter = t.router({
user: t.router({
byId: t.procedure
.input(z.object({ id: z.string().uuid() }))
.query(async ({ input }) => db.user.findUnique({ where: { id: input.id } })),
create: t.procedure
.input(UserCreate)
.mutation(async ({ input }) => db.user.create({ data: input })),
}),
});
export type AppRouter = typeof appRouter;
```
Frontend imports `AppRouter` type only. Runtime is fetch; types flow at compile time. Zero duplication. See `references/trpc-end-to-end.md`.
**When tRPC vs REST:**
```text
All clients are your own code, no public API -> tRPC
External partners, third-party integrations, public SDK -> REST + OpenAPI
Mobile on old TS versions / no TS -> REST
GraphQL ecosystem in the org -> GraphQL (not covered here)
```
## REST + OpenAPI (when needed)
Use `ts-rest` or `zod-to-openapi` — define schemas once, generate OpenAPI spec automatically.
```ts
import { initContract } from "@ts-rest/core";
const c = initContract();
export const userContract = c.router({
getUser: {
method: "GET",
path: "/users/:id",
pathParams: z.object({ id: z.string().uuid() }),
responses: { 200: UserSchema, 404: z.object({ error: z.literal("not_found") }) },
},
});
```
See `references/rest-plus-openapi.md`.
## Data layer — Prisma or Drizzle
**Prisma:** schema-first, Prisma Client is fully typed, great DX. Ships with migration tool. Best for teams.
**Drizzle:** SQL-first, TypeScript-first. Queries look like SQL, no hidden abstractions. Best when you love SQL and want explicit control.
Decision rule:
```text
Want schema.prisma as source of truth, good migrations, team of mixed SQL skill -> Prisma
Want SQL-in-code visibility, complex queries, performance-critical -> Drizzle
Postgres-only with advanced features (arrays, ranges, custom types) -> Drizzle
MySQL primary, migrations managed alongside PHP app -> Prisma
```
See `references/prisma-vs-drizzle.md`.
## Zod schemas as the shared layer
```ts
// packages/schemas/src/user.ts
import { z } from "zod";
export const UserCreate = z.object({
email: z.string().email(),
name: z.string().min(1).max(100),
role: z.enum(["admin", "member", "viewer"]),
}).strict();
export const User = UserCreate.extend({
id: z.string().uuid(),
createdAt: z.coerce.date(),
});
export type UserCreate = z.infer<typeof UserCreate>;
export type User = z.infer<typeof User>;
```
Consumed by: API validation, Prisma custom types, React Hook Form, tRPC input, test fixtures. See `references/zod-shared-schemas.md`.
## Auth
- **Lucia** — session-based, database-backed, flexible. Good for first-party apps.
- **better-auth** — newer, feature-rich (MFA, OAuth, magic links).
- **Clerk** — hosted auth; trade cost for speed. Great for MVPs.
- **NextAuth/Auth.js** — incumbent; fine but DX can be rough.
Never roll password hashing, session storage, or OAuth flows yourself. See `references/auth-patterns.md`.
## Testing the full stack
- **Unit:** vitest in each package.
- **Integration:** vitest + test database (Testcontainers or pg-lite).
- **E2E:** Playwright for the web app.
- **Contract tests:** if you expose REST, snapshot the OpenAPI spec — breaking changes fail CI.
- **Type tests:** `expectTypeOf` for API client usage.
See `references/testing-full-stack.md`.
## Deployment — Docker for Node
Multi-stage Dockerfile, node-slim base, non-root user, pnpm deploy for prod-only deps:
```dockerfile
FROM node:22-slim AS base
RUN corepack enable && corepack prepare pnpm@latest --activate
WORKDIR /app
FROM base AS deps
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./
COPY apps/api/package.json ./apps/api/
COPY packages/ ./packages/
RUN pnpm install --frozen-lockfile
FROM deps AS build
COPY . .
RUN pnpm --filter api build
FROM base AS prod
ENV NODE_ENV=production
USER node
WORKDIR /app
COPY --from=build --chown=node:node /app/apps/api/dist ./dist
COPY --from=deps --chown=node:node /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/server.js"]
```
See `references/docker-node-production.md`.
## Anti-patterns
- Duplicating types between frontend and backend ("I'll just type it again here").
- Trusting API responses without Zod validation on the client.
- Running migrations in app startup — run in CI or a separate migrate step.
- Sharing Prisma client across edge + Node runtime without a driver adapter.
- Importing server code into client code (mark server-only with `"use server"` or a runtime guard).
- Monorepo without remote build cache on CI — slow feedback.
- `any` on API boundaries.
## Read next
- `typescript-effective` — idioms.
- `typescript-mastery` — type system depth.
- `react-development` / `nextjs-app-router` — frontend.
- `nodejs-development` — Node runtime patterns.
- `postgresql-fundamentals` / `mysql-best-practices` — data layer specifics.
## References
- `references/monorepo-turborepo.md`
- `references/fastify-backend.md`
- `references/trpc-end-to-end.md`
- `references/rest-plus-openapi.md`
- `references/prisma-vs-drizzle.md`
- `references/zod-shared-schemas.md`
- `references/auth-patterns.md`
- `references/testing-full-stack.md`
- `references/docker-node-production.md`
- `references/large-scale-react-ts.md`
## Decision Rules
| Condition | Action |
|---|---|
| Only first-party TypeScript clients consume API | Consider tRPC with runtime validation |
| External clients or long-lived integrations exist | Publish REST/OpenAPI contracts |
| Shared package creates circular dependencies | Split schemas from implementations |
## Capability Contract
Read and search are required. Editing, database mutation, builds, and tests require authorisation.
## Degraded Mode
Fallback: without execution or services, return unverified integration points and exact end-to-end checks. Validate every network boundary at runtime.
## Inputs
| Artefact | Required? | Purpose |
|---|---|---|
| Frontend/backend boundaries, shared contracts, runtime targets, and deployment context | yes | Coordinate full-stack types and behaviour |
## Outputs
- Produce end-to-end TypeScript implementation or design with shared contracts, tests, and deployment notes.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!