Development
Run Litestore day to day, reset its data and check your work before you commit.
Once Setup is done, you use the commands below every day. The repository's compose.yml runs everything the store needs locally, so development works without any paid services.
Services
Start the local services with this command:
docker compose up -dcompose.yml defines these services, and .env.example already contains the matching connection values.
| Service | Port | What the app uses it for |
|---|---|---|
| PostgreSQL 17 | 5432 | The database. Point DATABASE_URL at localhost:5432/litestore. |
Redis with serverless-redis-http | 8079 | Rate limiting, the checkout payment lock and coupon reservations. serverless-redis-http speaks the same REST protocol as Upstash, so REDIS_REST_URL points at http://localhost:8079. |
| MinIO | 9000, console on 9001 | S3-compatible storage for media uploads. A setup container creates the bucket and makes its objects publicly readable. |
env.ts validates the environment with @t3-oss/env-nextjs when the module loads, so an unset required value throws before any route runs. If you copied .env.example, the Redis and S3 values already point at the Compose services.
Daily tasks
Dev server
This runs next dev -p 3000 --turbopack --disable-source-maps.
bun run devThe storefront serves on http://localhost:3000 and the admin on http://localhost:3000/admin. Both are served by the same Next.js app.
Prisma client
When you change prisma/schema.prisma, regenerate the client and restart the dev server.
bun run db:generatepostinstall runs the same script, so a fresh bun install also regenerates the client.
Browser testing
The seeded catalog is a working store, so most flows work without extra setup. Browse /collections or the feed at /feed, add something to the cart and go through checkout up to the payment step. STRIPE_SECRET_KEY is optional in env.ts, but you need Stripe configured to get past the payment step.
/api/health checks Postgres with SELECT 1 and Redis with ping(), each with a 3-second timeout. The admin Home shows the To do counts and the setup guide, both computed from the local data.
Outside production Litestore never sends email: sign-in emails, like every other email, are printed in the terminal running bun run dev, whether or not RESEND_API_KEY is set.
Database reset
You choose between reseeding and rebuilding depending on whether you need to keep your edits.
| Command | What it does | Your edited rows |
|---|---|---|
bun run db:seed | Runs bun prisma/seed.ts, which writes with upsert. Most of those upserts have an empty update: {} block. | They keep your values and don't revert to the seed values. |
bun run db:reset | Runs prisma migrate reset. It drops the database, applies the committed migrations again, and then runs the seed, which prisma.config.ts registers as bun prisma/seed.ts. | They go back to the seed's values. |
bun run db:studio | Opens Prisma Studio for looking at rows directly. | Unchanged. |
Keeping your values is usually the right choice, but it also means reseeding won't fix a broken local database. Use db:reset only when you need the seed's values back.
Prisma Studio listens on port 5556 instead of Prisma's default 5555, so it doesn't conflict with Studio running for another project.
Checks
Each part of verify is its own script, so you run just the one that matches what you changed.
| Script | What it does | Run it after you |
|---|---|---|
bun run lint | Runs biome check --write ., which lints and formats the code and writes fixes to your files. | Finish a change. |
bun run test | Runs the unit tests once with vitest run. | Change logic. |
bun run typecheck | Runs tsc --noEmit across the app. | Change types or the schema. |
bun run test:integration | Runs the tests in test/integration/ against the local litestore_test database. | Change code that depends on the database. |
bun run test:e2e | Resets the litestore_e2e database and runs the Playwright journeys in test/e2e/. | Change a journey the browser tests cover. |
bun run verify | Runs typecheck, lint and test in order and stops at the first failure. | Get ready to push. |
GitHub Actions runs verify on every push to main and on every pull request, so run it before you push. Continuous integration describes the checks the workflow runs.
Typecheck memory
typecheck sets NODE_OPTIONS='--max-old-space-size=5000', which allows
Node a 5 GB heap. On a smaller machine, stop the dev server before you run
it.