Litestore · Developer docs
Codebase

Stack

Litestore is built on Next.js, React, Prisma, PostgreSQL and other public packages, grouped here by the part of the app that uses them.

Litestore is built from public packages, and each one has its own documentation. Read this page when you need to find out which framework or library a part of the app is built with, or before you upgrade a dependency.

Your server
One Next.js app
Storefront
Admin
Marketing
PostgresOne database
The storefront, admin and marketing tools run as one Next.js app, and that app uses one Postgres database.

The versions below are the ones declared in package.json, and they have been tested together. When you upgrade one, run bun run verify and the integration and end-to-end tests to find out whether the upgrade broke anything.

Core framework

PackageVersionWhat it does
Next.js 16^16.1.1It provides the App Router, and in development it runs under Turbopack with next dev -p 3000 --turbopack --disable-source-maps.
React 19^19.2.3Litestore uses Actions and useOptimistic, so most pages need very little client state.
TypeScript^5.9.3It covers the whole repository, and bun run typecheck runs tsc --noEmit across it.
Zod 4 and zsa^4.3.5 and ^0.6.0They validate input.
oRPC@orpc/server ^1.13.9It provides the typed RPC API, defined in platform/api/orpc.ts, routed from platform/api/router.ts and served at app/api/rpc/.

Server Components let a storefront page read the database directly, so there's no separate API layer to keep in sync. Since TypeScript covers the whole codebase, a schema change that breaks something shows up as a build error before it can affect checkout.

Each module keeps its input schemas in the same predictable place:

modules/<area>/admin/schema.ts
modules/<area>/storefront/schema.ts

Litestore wraps server actions so that validation and permission checks run before the mutation.

Database and caching

The database is PostgreSQL 15+, and its constraints enforce Litestore's guarantees. The baseline migration adds CHECK constraints such as these:

stock_movement_quantity_math
order_amounts_refunded_not_over_total

Prisma 7 (7.4.2) runs on top of Postgres. It provides one schema file, a committed migration history in prisma/migrations/ and a fully typed client. When Litestore creates the client, it extends it with the soft-delete filter from platform/db/soft-delete-extension.ts, and the client connects through @prisma/adapter-pg.

Litestore uses Redis through Upstash (@upstash/redis, @upstash/ratelimit) for three jobs.

JobWhere
Key-value helpers (getCache/setCache)platform/cache.ts
Rate limitersplatform/rate-limit/
Payment idempotency locksplatform/rate-limit/payment-lock.ts

Payments and email

Stripe (^20.3.1) handles checkout, capture, refunds and disputes. All of these go through platform/stripe-client.ts, platform/stripe-payment-provider.ts and modules/orders/payments/payment-webhook.ts, and Litestore copies each one into the PaymentTransaction ledger. Customers can browse and fill a cart without Stripe configured, but checkout needs it.

Resend (^6.9.2) and React Email send mail. The templates in modules/email/templates/ are React components that @react-email/components renders.

People sign in with a magic link sent by email. Production needs RESEND_API_KEY; outside production no email is sent and the link is printed in the terminal running bun run dev.

Infrastructure and runtime

Bun 1.2.2 is the declared packageManager, and it runs every script in package.json. The application itself runs on Node.js.

Uploads go to S3-compatible storage (@aws-sdk/client-s3, @aws-sdk/lib-storage). They pass through platform/s3.ts into your own bucket, so the files are stored in your own account.

Inngest (^3.54.0) runs the background work. Crons and event handlers are in jobs/, and the same app serves them at app/api/inngest/. jobs/domain-events.ts takes each emitted domain event and turns it into cache invalidation and side effects.

Sentry (@sentry/nextjs ^10.40.0) connects through four instrumentation files. If you leave the DSN unset, the app still runs, but Sentry receives no error reports.

instrumentation.ts
instrumentation-server.ts
instrumentation-client.ts
instrumentation-edge.ts

Biome (^1.9.4), Vitest (^4.0.18) and Playwright (1.58.0) are the development tools in the same package list.

CommandWhat it does
bun run lintIt lints and formats the code with Biome.
bun run testIt runs Vitest.
bun run test:e2eIt runs the Playwright journeys.
bun run verifyIt runs typecheck, lint and test.

Authentication and styling

Better Auth (^1.4.19) is configured in platform/auth/server.ts with the magicLink and admin plugins, and sessions last 7 days. Litestore registers Google sign-in only when both AUTH_GOOGLE_ID and AUTH_GOOGLE_SECRET are set, so a self-hosted store works without it.

Tailwind v4 (^4.1.18) handles styling. The design tokens are declared in the @theme block of app/styles.css, so the admin and the storefront share one scale.

Radix UI primitives and @tanstack/react-table provide the unstyled behaviour under ui/ and ui/data-table/.

Architecture decisions

Litestore's stack is based on four design decisions, each of which keeps the number of moving parts low.

Single deployment
The catalog and the cart run in one process, so there are no network calls between microservices to manage.
Server-side data shaping
Server Components fetch exactly what each page needs, so Litestore has no GraphQL layer and clients can't ask for arbitrary shapes.
Shared app
The storefront doesn't call the admin through an API, so there's no class of bug where something works in the admin but shows up wrong on the site.
Fork customization
Litestore has no plugin sandbox, so you edit the code directly.

The developer overview explains why a fork is the way to customize.

Versions

The versions in package.json are the tested ones. When you upgrade Next.js or Prisma, run bun run verify and the integration and end-to-end tests before you deploy.

After an upgrade, check more than whether the app still starts. Look at what the new version changed, and make sure bun run verify still passes.

On this page