Skip to content

An API with it all in place, ready to build on.

An Express 5 API in TypeScript with one complete example resource that shows every pattern: protected routes, validation, responses and errors.

Open on GitHubMIT licence · free to use

Use it when

You need a standalone API for a web or mobile app, with signed-in users, a Postgres database and Redis.

Need the web app and jobs in the same repo? template-monorepo instead →

What's included

Done from the start.

  • Sign-in

    Clerk middleware, and protected routes with requireAuth() and getAuth().

  • Database

    Drizzle on Postgres with example tables and scripts to generate and run migrations.

  • Redis

    Sliding-window rate limiting with X-RateLimit headers, plus simple cache helpers.

  • Validation

    Zod schemas with a validate() middleware, and sanitizing of text and filenames.

  • Responses and errors

    asyncHandler, sendSuccess and sendError, so every route answers the same way.

  • Example resource

    A protected resource with list, get, create and delete, and a health check.

Get started

pnpm install
cp .env.example .env
pnpm db:generate
pnpm db:migrate
pnpm dev          # http://localhost:3001

Structure

src/
├── index.ts        entry point: middleware, routes, errors
├── middleware/     rate limiting
├── routes/         health.ts, example.ts
├── services/       database, schema, Redis
├── types/          shared types
└── utils/          responses, validation, sanitizing

Environment variables

  • DATABASE_URL
  • REDIS_URL
  • CLERK_SECRET_KEY
  • CLERK_PUBLISHABLE_KEY
  • CORS_ORIGINS

Postgres and Redis are needed locally. CORS allows localhost:3000 unless told otherwise.

Good to know

  • No ESLint config ships yet, so pnpm lint works once you've added one.

Built with

  • Express 5
  • TypeScript
  • Clerk
  • Drizzle
  • PostgreSQL
  • Redis
  • Zod

Let's build
the next thing.

You talk to me, not a salesperson. The first call is free.

— Kenny

psst, it takes 15 min

Write, and I reply the same working day.