Litestore · Developer docs
Codebase

Structure

Find your way around the Litestore repository and choose where new code belongs.

The repository has a fixed layout, and each new module or integration has a place it belongs. Following these conventions keeps your code where the next person will look for it.

Everything is in one project, so a storefront page can import a domain rule directly without crossing a package boundary.

Directory tree

Key conventions

Treat this layout as a set of rules. No script checks it, so reviewers do: a file in the wrong place gets copied by the next person who looks for an example.

Route folders

app/ contains Next.js convention files and nothing else:

page.tsx
layout.tsx
loading.tsx
error.tsx
route.ts

UI for a specific route goes in modules/<area>/admin/ or modules/<area>/storefront/.

No folder in app/ contains a _components/ folder or any other underscore folder.

Server actions

"use server" files live only in a module's admin/ or storefront/ folder, for example modules/orders/admin/actions.ts. Each admin action declares its permission with modulePermission or withAnyPermission from platform/permissions/procedures.ts.

Actions save data through the module's CRUD object, built on BaseCRUD in platform/crud/base-crud.ts. It handles soft delete, activity logging and cache invalidation in one step, so callers don't have to handle each of these themselves.

Queries

Read-only queries go next to the actions in queries.ts. Cached reads are tagged with a value from CACHE_TAGS in platform/cache.ts. When a write happens, it clears the same tag that the read was cached under, so the next read fetches fresh data.

Module folders

A business area keeps its rules at the root of its folder and its surface code in admin/ and storefront/. For example, the coupon rules are in modules/promotions/ and the coupon admin is in modules/promotions/admin/. Module rules never import from admin/ or storefront/; the surfaces import the rules.

Import boundaries

Server modules start with import "server-only". If a "use client" component imports one of them, directly or through another file, next build fails, so server code and database access can't end up in the browser bundle. Storefront and admin code also stay apart, and neither imports from the other.

Adding code

You are addingWhere it goes
A storefront sectionPages don't store layout. If it's text and images, write it into a page's HTML content. Otherwise change the route, or PageContent and PageFeed in modules/storefront/pages/page-view.tsx if every page should get it. Storefront pages explains how pages render.
An admin entitymodules/<area>/admin/ (actions, queries, crud, schema, table, detail page) and a route under app/admin/. CRUD explains the persistence layer.
A reaction to an eventWrite a handler in jobs/domain-events.ts. Events explains how.
A third-party integrationPut it in modules/integrations/, behind the existing interface.
A shared rule or formatPut a domain rule in the owning modules/<area>/ and infrastructure or a pure helper in platform/. Define each one in a single place and import it from there everywhere else.
A tuning valueA typed constant in platform/config/, with a one-line comment.
When you add a file, look for the folder that already handles that kind of work and for an existing file nearby that does something similar.

Next steps

On this page