A minimal Bun + GraphQL Yoga + Drizzle ORM starter with Zod, Biome, and a sprinkle of fun.
- β‘οΈ Bun runtime for speed
- π GraphQL Yoga β simple, modern GraphQL server
- ποΈ Drizzle ORM + SQLite for typed database access
- β Zod for runtime schema validation
- π§Ή Biome for linting & formatting (auto on save!)
- π Custom error handling with
GraphQLException
- ποΈ Modular folder structure β
src/graphql/modules/*
keeps resolvers/types organized
src/
βββ db/ # Database (drizzle + migrations)
βββ env.ts # Zod-powered environment validation
βββ graphql/ # GraphQL schema, resolvers, context
β βββ modules/ # Modularized features (task, user, etc.)
β βββ schema.ts # Yoga schema entrypoint
βββ lib/ # Utilities & custom exceptions
βββ index.ts # Server entrypoint
# Install dependencies
bun install
# Start dev server
bun run dev
# Run migrations
bun run db:migrate
INFO Server is running on: π http://localhost:3000/graphql
bun run dev
β Start server in dev modebun run format
β Format code with Biomebun run lint
β Lint & fix with Biomebun run db:migrate
β Run database migrationsbun run db:generate
β Generate Drizzle migration filesbun run db:push
β Push schema directlybun run db:start-studio
β Open Drizzle Studio
PORT=3000
NODE_ENV=development
DB_FILE_NAME=./breeze.sqlite
DEBUG=1
Validated with Zod in src/env.ts
. Invalid configs will π« exit early.
Instead of raw GraphQLError
, Breeze ships with a custom GraphQLException
:
throw new GraphQLException("NOT_FOUND", {
message: "Task not found",
});
This ensures consistent error responses with extensions.code
.
Available codes: BAD_USER_INPUT
, UNAUTHENTICATED
, FORBIDDEN
, NOT_FOUND
, CONFLICT
, INTERNAL_ERROR
, GRAPHQL_PARSE_FAILED
, GRAPHQL_VALIDATION_FAILED
.
PRs and issues are welcome! π Fork it, hack it, and send improvements.
- Subscription example
- Default error handling
- GraphQLException v2