GitHub

The whole store, in one repository.

Catalog, checkout, payments, returns, campaigns, partners, reviews, email and AI content are modules on one database, not integrations.

PostgreSQLRedisS3StripeResend
~/litestore
What you clone23 modules
Storefront + admin
one Next.js app
Schema
70 models
Tests
1,517 in 151 files
Modules behind a paid tier
0

A stack assembled from six subscriptions.

A platform, a CMS, a reviews widget, an affiliate tool, an email tool and a BI seat. Each one holds a piece of the truth, none of them agree, and every one of them sends an invoice.

An integration is a boundary. A module is a join.

Because reviews and orders share a database, a verified-buyer badge is a join rather than a claim. That is the whole difference between twenty-three modules and twenty-three subscriptions.

Where the 23 sit

Four groups
1database

Build, sell, grow, run

Build17%Sell26%Grow30%Run26%23 modules

Run the day from one screen.

The admin computes the work, puts it on a calendar, and talks to the services you already use.

Twenty-nine kinds of task

Each one is computed from live store data and shows what it is worth. Ship the order and the task disappears.

Sales start and end on time

A sale is live when now is inside its window. No job to run, nothing to switch off.

fn
K

The assistant is a shortcut away

Search, actions and the AI assistant open from anywhere in the admin.

Everything external is swappable

Payments, email, storage, cache and analytics each work through their own interface.

A storefront, already rendering.

The products block reading your catalog with your theme settings. No template was forked and no starter was cloned to get here.

New season
Sunset Linen Shirt4.8

4 colours · in stock

$128
Everyday Merino Crew4.6

6 colourways · machine washable

$96

Forty of them, all bindable.

order.paid, cart.abandoned, return.approved, collab.commission.accrued. A workflow is an event name and a function — waits of days survive restarts.

order.paidstock.movedemail.sentcollab.accruedcart.abandoned

Everything external is behind a boundary.

Payments, email, storage, cache, analytics and newsletters each sit behind their own interface. An unconfigured service hides its screens rather than failing halfway.

Build, sell, grow, run.

Every module sits in one of four groups, and every one reads the same tables.

Drag the deck4 groups
4 modules

Build

6 modules

Sell

7 modules

Grow

6 modules

Run

Storefront blocks
Pages & blog
Themes & tokens
AI content
Products & variants
Collections & categories
Inventory & locations
Cart & checkout
Payments
Channels & markets
Discounts & gift cards
Campaigns
Collabs & referrals
Reviews
Email & newsletter
AI product intelligence
SEO & structured data
Orders & fulfillment
Returns & refunds
Customers
Conversations
Analytics & activity
Integrations & API

Does more surface mean more to maintain?

It also means more for the assistant to work with. An AI that only sees products can write product descriptions. This one sees orders, customers and reviews, so it can suggest an action rather than a sentence.

Store assistant
your key
What needs shipping today?Write descriptions for the new collectionWhich coupons expire this week?
Ask about orders, stock, customers…

Clone to running.

No account, no CLI login and no dashboard in between. Configuration is checked at startup, so a missing value stops the boot rather than breaking checkout later.

Getting started

  1. 1Clone the repositorygit clone
  2. 2Install and configurebun install · env.ts
  3. 3Apply the schemaprisma migrate deploy
  4. 4Start itbun dev

Five services, all standard.

Postgres, Redis, S3 and an email sender are required. Stripe is only needed for checkout — browsing and carts work before payments are wired.

Requirements5 services
PostgreSQL 15+
required
Redis
required
S3-compatible storage
required
Resend
for sign-in
Stripe
for checkout only
Oat & Ash
Wemovedoffahostedplatformandkepteveryorder.

Sarah Chen

Founder, Oat & Ash

Add what you need.

Write it into the same codebase. The compiler checks it fits.

lib/rules/workflows.ts

Durable
{
  event: "cart.abandoned",
  name: "recover-abandoned-cart",
  run: async (payload, step) => {
    await step.sleep("settle", "3d")

    await step.run("send-offer", () =>
      queueEmail({ template: "cart-recovery", to: payload.email })
    )
  },
}

A full cart-recovery flow. The three-day wait survives restarts and deploys, and the email is sent once.

01

Event workflows

React to any domain event in one entry

02

Storefront blocks

Add a block type the compiler then demands you finish

03

Product page modules

Place your own module into a PDP section

04

Admin modules

Inherit list, detail, mutations, activity, and permissions

Plus payment providers, outbound webhooks, swappable services, and checks that fail the build when an extension is wrong.

How extensibility works

These are seams inside your own copy of the code. There is no versioned plugin API.

23Modules

None behind a paid tier

70Data models

One Prisma schema

1,517Tests

Across 151 files

40+Domain events

Each bindable to a workflow

What you clone is what you run. There is no private repository behind it.

Twenty-three modules

Everything from catalog to collabs is included, with no paid tier holding modules back.

Forty events, all bindable

Pick an event and write what should happen. Waits of days survive a deploy.

One database

Reviews and orders are in the same database, so a verified-buyer badge is checked against a real order.

One app. Twenty-three modules. No plan.

Clone the repository and every module is already there.

23 modulesMIT licensedOne database