Skip to Content
StoreOSv0.27.1
Guides

AI-driven development

Prompt recipes for building a Fluid theme, a custom storefront on the Storefront API, and a custom admin dashboard on the Core API — with the StoreOS docs MCP.

Use Cursor, Claude, Codex, ChatGPT, or any agent that speaks MCP to build on StoreOS. This page is a prompt pack for three jobs:

JobWhat the agent writesWhat StoreOS provides
ThemeA Fluid theme (*.fluid, config/document.json, CSS)Rendering, the customizer, catalog objects
Custom storefrontYour shop UI (any framework)Storefront API at api.storeos.dev/storefront
Custom dashboardYour staff UICore API at api.storeos.dev/core

The docs MCP reads documentation. It does not log in, list products, or place orders. Live store data goes through an API key in your app's environment.

Connect the server first → Docs MCP. Public URL: https://mcp.storeos.dev/docs. No API key.


Standing instructions

Paste this once into a Cursor rule, Claude project, or the first message of a session. The prompts later on this page assume it.

You are building against StoreOS. Use the storeos-docs MCP before you write or change StoreOS-specific code.

1. search the docs with 2–6 keywords.
2. get_page the matching guide and follow its examples. Prefer MCP Markdown over memory for API names, headers, Fluid tags, and CLI flags.
3. If search is thin, list_pages and open the closest path.

Paths:
- Themes: /docs/themes, /docs/themes/widgets, /docs/themes/structure, /docs/cli/theme
- Storefront: /docs/getting-started, /docs/storefront-client/methods, /docs/guides/checkout, /docs/graphql-api
- Admin: /docs/guides/admin-dashboard, /docs/core-graphql-api, /docs/guides/api-keys

Rules:
- Public calls go to https://api.storeos.dev. Storefront prefix /storefront. Core prefix /core/graphql.
- Send x-storeos-key on every data request. Never put the key in Authorization.
- Read STOREOS_API_KEY and the tenant uid from env. Never ask me to paste the key into chat, and never write the key into source.
- Storefront customer calls use @storeos/storefront-client unless I ask for raw GraphQL.
- Core operations are named domain__operation (identity__login, inventory__products). A staff Bearer token is required after login.
- GraphQL can return HTTP 200 with an errors array. Handle both.
- Themes are Fluid files. Use the storeos theme CLI. Do not invent a React theme package.
- For a custom dashboard, show API errors at the top of the form. Toasts are for success only.
- Stay inside the files I name. Do not refactor unrelated code.

How a turn should use MCP

Tell the agent the outcome, then let it fetch the page. A theme widget turn looks like this:

  1. search → widget schema collection setting
  2. get_page → /docs/themes/widgets
  3. get_page → /docs/cli/theme/new if it is adding a file
  4. Write widgets/<type>.fluid and the matching config/document.json entry
  5. Run storeos theme check

If the agent skips MCP and invents a tag, a header, or an operation name, reply with:

Stop. search storeos-docs for "<the thing you invented>", get_page the hit, and rewrite so it matches that page. List the path you read.

Theme development

A theme is a folder of Fluid templates. Merchants arrange your widgets in the console. You do not call the Storefront API from a theme: the engine injects product, collection, shop, and the rest. Read Fluid themes, structure, widgets, and the CLI.

Install once, in the theme folder's environment:

bunx @storeos/cli theme --help

Start a theme

Create a StoreOS Fluid theme in ./dawn-market.

Use storeos-docs MCP. get_page /docs/themes/quickstart and /docs/themes/structure before writing files.

Run:
  bunx @storeos/cli theme init dawn-market
  cd dawn-market

Keep the starter as a reference, then slim the home page to:
- announcement bar
- header
- one hero
- one product grid bound to a collection setting
- footer

get_page /docs/themes/layout-and-document so config/document.json matches the real document shape.
layout/theme.fluid must print content_for_header in <head> and content_for_layout in the body.
Do not add a <title> or meta description; StoreOS injects SEO.

When the files exist, run storeos theme check and fix every error. Leave warnings listed at the end of your reply.

Blank theme, when you want an empty page instead of the starter:

In this empty folder, run:
  bunx @storeos/cli theme init . --blank

Then get_page /docs/themes/quickstart and /docs/themes/layout-and-document.
Add only layout/theme.fluid, config/document.json, and assets/theme.css if init did not.
Home, product, and collection pages can be empty widget lists.
Run storeos theme check.

Add a widget

Add a home widget named promo-banner.

MCP: get_page /docs/cli/theme/new and /docs/themes/widgets.

Run: storeos theme new widget promo-banner --page home
Then edit widgets/promo-banner.fluid. Do not hand-roll the document entry if the CLI already added it.

Markup:
- a <section> with no max-width wrapper (the layout owns page width)
- eyebrow, heading, body, and a button
- image on the right on wide screens, stacked on small screens

Schema settings:
- eyebrow: text, default "This week"
- heading: text, required
- body: rich text if that kind exists on the widgets page, otherwise text
- buttonLabel: text, default "Shop"
- buttonLink: link
- image: image
- tone: select of "sand" | "ink" | "paper", panel style

Use props.* in the template. Follow the schema JSON shape from the widgets page exactly.
Run storeos theme check.
Add a product-page widget size-guide.

storeos theme new widget size-guide --page product
get_page /docs/themes/contexts/product and /docs/themes/objects-and-filters.

The widget reads the current product (title, options if the product object exposes them — confirm on the objects page, do not guess fields).
Settings: heading (text), note (text), rows (a list of label/value if the schema supports a list; otherwise three text pairs size1, chest1, size2, chest2, size3, chest3).
Render a simple table. If product is missing, print nothing.
Run storeos theme check.
Add a snippet product-card and use it from the product grid.

storeos theme new snippet product-card
get_page /docs/themes/widgets for {% render %} and /docs/themes/objects-and-filters for the product fields that exist (title, url, price, compare_at_price, featured_image).

snippets/product-card.fluid only uses variables passed into render, plus shop.
Show image, title, price, and compare-at price when it is higher.
The grid widget renders the snippet once per product. Do not fetch HTTP inside the template.
Run storeos theme check.

Restyle a built-in widget

Restyle the built-in button widget so it matches this theme.

get_page /docs/themes/widgets (built-in widgets) and /docs/cli/theme/new.
Run: storeos theme new widget button

Keep StoreOS's props. Do not add a {% schema %} block.
Replace the markup with a single <a> or <button> using the same props the built-in file already reads.
Style it in assets/theme.css with theme CSS variables from content_for_header, not hard-coded brand hex in every widget.
Run storeos theme check.

Match a reference design

Attach a screenshot, then:

Restyle this theme to match the attached homepage. Shop flow stays intact.

MCP first:
- get_page /docs/themes/styling
- get_page /docs/themes/widgets
- get_page /docs/themes/layout-and-document

Inventory only the blocks visible in the screenshot. Map each to an existing widget or one new widgets/<type>.fluid.
Put colors and fonts in the theme document global settings, and consume them as the CSS variables the styling page documents.
Do not copy another theme's files in from outside this folder.
Do not add FAQ, blog, or countdown widgets unless they are in the screenshot.
After edits, run storeos theme check and summarize the widget list per page (home, collection, product, search).

Collection data inside a widget

The home product grid should let the merchant pick a collection in the customizer.

get_page /docs/themes/widgets (collection settings and widget.data).
Add a collection setting named source.
Render product cards from the collection payload that setting loads — use the field names on that page.
Empty state: "Add products to this collection" when the collection has no products.
Run storeos theme check.

Locales

Move customer-facing strings in widgets/ and snippets/ into locales/en.default.json.

get_page /docs/themes/filters for the t filter and /docs/themes/structure for locales.
Replace literal "Add to cart", "Sold out", and "Search" with {{ 'key' | t }}.
Keep merchant-edited props.* as props (those are settings, not locale strings).
Run storeos theme check.

Preview, check, package

I will preview this theme against a real store.

get_page /docs/cli/theme/dev.
Tell me the exact command for:
1. storeos theme dev with no flags, then Connect local theme in the console
2. storeos theme dev --storefront <url> --store <tenant-uid>

Do not invent sample products. Start dev only after I confirm which option.
Then run storeos theme check.
storeos theme check failed. Paste is below.

<paste the check output>

get_page /docs/themes/validation.
Fix only the errors (✗). Do not "clean up" unrelated widgets.
Re-run storeos theme check and paste the new output.
Warnings can stay; list them.
Package this theme for upload.

get_page /docs/cli/theme/package and /docs/themes/validation.
Run storeos theme package.
If check fails, fix errors and package again.
Reply with the zip path and the check summary. Do not upload it.

Theme repair prompts

config/document.json references a widget type that has no file.
get_page /docs/themes/validation and /docs/themes/layout-and-document.
Either add the missing widgets/<type>.fluid or remove the entry.
Every type in the document must exist as a file or as a built-in named on the widgets page.
Run storeos theme check.
Merchants say colors they pick in the customizer never show up.

get_page /docs/themes/structure (content_for_header) and /docs/themes/styling.
Confirm layout/theme.fluid prints content_for_header inside <head>.
Confirm CSS uses the theme variables from that page, not a second hard-coded :root palette.
Run storeos theme check.

Custom storefront

You own the website. StoreOS owns catalog, checkout rules, and orders. Calls go through the public gateway with a key scoped to storefront:…. Start from Getting started, SDK methods, and Checkout.

Env (server-side key):

NEXT_PUBLIC_SITE_URL=http://localhost:3000
NEXT_PUBLIC_SITE_API_TENANT=your-tenant-uid
STOREOS_API_KEY=sos_live_…

The prompts below say my-store and Next.js. Swap the framework name if you already have an app.

Bootstrap

Create a Next.js storefront in ./my-store that reads the catalog from StoreOS.

MCP:
- get_page /docs/getting-started
- get_page /docs/storefront-client
- get_page /docs/storefront-client/configuration
- get_page /docs/guides/api-keys

bun create the app, bun add @storeos/storefront-client.
Add lib/store.ts with StoreFront using NEXT_PUBLIC_SITE_API_TENANT and STOREOS_API_KEY.
Call it from server code only. Do not put the key in a client component or NEXT_PUBLIC_ var.
Home page: getProducts({ limit: 12 }) and render title, price, and handle.
If env is missing, show a short setup message that names the variables, not a stack trace.
Do not invent REST paths. Use SDK methods from the methods page.
Add a /shop page and a /product/[handle] page to this storefront.

get_page /docs/storefront-client/methods (getProducts, getProduct).
/shop supports search and pagination using the params that page documents (page, search, and meta.hasNextPage).
/product/[handle] uses getProduct({ handle }). 404 when the product is missing.
Link each card to /product/[handle].
Keep the StoreFront client on the server.

Store config and collections

Footer needs the store name, support contact, and policy links from StoreOS.

get_page /docs/storefront-client/methods for getTenant (or the store-config method that page documents).
Render only fields that method returns. Skip any field that is null.
Cache the result for the request, not in a module-level global that survives across tenants.
Add /collections/[id] for one collection.

get_page /docs/storefront-client/methods for getCollection, getCollections, and getProducts.
getCollection takes an id. List products with the collection filter that page documents (collectionIds).
Title and description come from the collection. Empty collection: "Nothing in this collection yet."
Nav links should use the collection id the list method returns.

Cart and checkout

Add a cart and a /checkout page. Follow the checkout guide, not a generic ecommerce flow.

MCP:
- get_page /docs/guides/checkout
- get_page /docs/storefront-client/methods for cart, previewDiscounts, verifyCoupon, createOrder, getTenant

Use the cart methods the SDK page documents (upsertCart / getCart or the React useCart path if we are on the React SDK — pick the one this repo already uses).
Checkout collects shipping address and delivery area, shows delivery charge from tenant charges, optional coupon via previewDiscounts, payment method COD or ONLINE.
Place order with createOrder. Redirect to /order-confirmation/[invoiceUID] using the id the response actually returns (confirm the field on the checkout page).
Show API failures at the top of the checkout form. Do not toast them.
Switch this storefront to the React SDK for cart and auth only. Catalog pages can stay on the REST client.

get_page /docs/storefront-client/react.
Add the providers, peers, and hooks that page lists.
apiKey stays in server helpers. The browser must not receive STOREOS_API_KEY.
Wire useCart to the existing cart button. Do not rewrite the product page layout.

Customer auth

Add email login and register at /auth.

get_page /docs/graphql-api/authentication and the auth methods on /docs/storefront-client/methods (login, register).
Session cookie stays httpOnly if the React SDK server helpers do that — follow that page.
After login, redirect to /account/orders.
Errors from the API render above the form.
Add phone OTP login at /auth/phone.

get_page /docs/guides/phone-otp and the OTP methods on /docs/storefront-client/methods.
Two steps: send code, then verify. Use the method names on those pages.
Resend waits on the cooldown the guide describes. If the guide has no cooldown, add a 30s client timer and say so in the PR summary.
Add /account/orders for the signed-in customer.

get_page /docs/storefront-client/methods for getMyOrders.
Redirect anonymous visitors to /auth?next=/account/orders.
List invoice id, date, total, and status using the fields the method returns.

GraphQL instead of the SDK

Use this when you want a hand-written client. Otherwise stay on the SDK.

Add a small GraphQL client for the storefront. Do not add Apollo.

get_page /docs/graphql-api and /docs/graphql-api/queries.
POST https://api.storeos.dev/storefront/graphql
Headers: content-type application/json, x-storeos-key from STOREOS_API_KEY.
Authorization Bearer only when the customer is signed in.
First query: products for the home page, only the fields the product card needs. Confirm field names with get_page on the products query reference under /docs/graphql-api/reference/queries/products.
Throw when the body has an errors array, and include the first message.

Storefront repair prompts

Home page returns 401 missing_api_key.

get_page /docs/guides/api-keys and /docs/getting-started.
Check that server requests send x-storeos-key and that STOREOS_API_KEY is not NEXT_PUBLIC.
The key needs a storefront scope (storefront:query is enough for catalog reads; checkout needs mutations — confirm on the api-keys page).
Do not log the key. Tell me which file attaches the header.
Checkout totals disagree with the guide (delivery fee or coupon).

get_page /docs/guides/checkout.
Recompute the summary from previewDiscounts and tenant charges. Remove any client-side price math that contradicts that page.
Show the API error message above the form when createOrder fails.
Search the storeos-docs MCP for "pagination" on storefront list methods.
get_page the methods page section that describes meta (totalCount, hasNextPage).
Fix /shop so page changes use that meta. Do not invent cursor pagination if the API is page/limit.

Custom dashboard

A custom dashboard is a staff app: login, then store-scoped GraphQL on the Core API. Shoppers never call it. Read Build a custom admin dashboard and Core GraphQL.

HeaderValue
x-storeos-keyKey with core:query, core:mutation, or core:all
AuthorizationBearer <accessToken> from identity__login
Content-Typeapplication/json

Endpoint: POST https://api.storeos.dev/core/graphql.

Put the key in a backend-for-frontend. The browser sends the staff session to your server; your server attaches x-storeos-key.

Shell and login

Scaffold a staff dashboard (Vite + React is fine) with a BFF.

MCP:
- get_page /docs/guides/admin-dashboard
- get_page /docs/core-graphql-api
- get_page /docs/guides/api-keys

Server route POST /api/graphql forwards the JSON body to https://api.storeos.dev/core/graphql with:
- x-storeos-key from STOREOS_API_KEY (server env only)
- Authorization forwarded from the incoming request when present

Login page calls identity__login through that proxy. Persist accessToken in memory + httpOnly cookie if you add a cookie route; do not put the API key in localStorage.
App shell: sidebar groups Sales, Catalog, Settings. Store label can wait.
GraphQL errors (HTTP errors and body.errors) render in a banner at the top of the page. Success toasts only.
After login, confirm the token works.

get_page /docs/core-graphql-api.
Call inventory__products with where: { page: 1, limit: 5 } through the BFF and print title + status.
If the error is a permission error, stop and tell me the permission name from the reference page. Do not bypass RBAC.
Operation names stay domain__operation. get_page the query reference before adding fields.

Orders and catalog

Build an orders list and an order detail route.

get_page /docs/guides/admin-dashboard (Orders) and search storeos-docs for sale__invoices (or the invoice list query the reference actually ships).
get_page that query and the invoice object page before writing the selection set.

List: newest first, search box, status filter, pagination from the meta type on that page.
Detail: customer, totals, status, line items — only fields that exist on the type.
Status changes go through the mutation named on the reference. Confirm destructive cancels.
Server errors at the top of the detail page.
Build products list + create/edit.

search storeos-docs for inventory__products and inventory__createProduct.
get_page both reference pages and /docs/guides/admin-dashboard (Catalog).

List columns: image, title, status, price — drop a column if the type has no such field.
Create form: title, price, status. Match the input type on the mutation page.
Show field errors from the API at the top of the form.
Publish vs draft must be explicit so staff do not accidentally expose a draft on the shop.
Add stock levels and an adjustment form for one product.

search storeos-docs for AdjustStock (or the stock mutation the schema documents).
get_page that page and the stock section of /docs/guides/admin-dashboard.
Form: quantity delta, optional note, variant key when the product has variants.
Show the new level from the mutation payload. Do not optimistically invent a level if the payload returns one.

Staff, roles, and overview

Add a staff page: list members and invite by email.

search storeos-docs for AddUserToTenant and the user list query.
get_page /docs/guides/admin-dashboard (Staff and roles).
Invite form: email + roles. Show the temporary password once if the mutation returns one, then clear it from component state on navigation.
Hide the invite button when you have no signal the user can invite; the API still enforces the role.
Add an Overview home with KPI cards.

get_page the Overview section of /docs/guides/admin-dashboard.
search storeos-docs for the report query that page points at.
get_page that query. Cards: the metrics that query actually returns for a date range (default last 7 days).
Empty range: zeros, not an error.
Loading: skeletons. Failure: banner at the top, not a toast.

Dashboard repair prompts

Core GraphQL returns 200 with errors and the UI shows a blank table.

get_page /docs/core-graphql-api.
Update the BFF client so body.errors becomes the form banner message (first error.message, plus extensions.code when present).
Do not treat HTTP 200 as success by itself.
Add a unit test or a small fixture with an errors array and no data.
Login works in the playground and fails in the app.

Compare our proxy to the headers table on /docs/core-graphql-api.
We need x-storeos-key from server env and Content-Type application/json.
Turnstile is not required on identity__login through the gateway — confirm on /docs/guides/admin-dashboard and delete any captcha requirement we added.
Do not print the key or the password.
The products page queries a field the schema does not have.

get_page /docs/core-graphql-api/reference/objects/Product (and the inventory__products query page).
Remove unknown fields. If a column has no matching field, drop the column and note it in the reply.
Re-run the query through the BFF.

Session starters

One message to open a session. Replace the bracketed bits.

Theme

Repo: this folder is a StoreOS Fluid theme (layout/theme.fluid, config/document.json).
Goal today: [add a testimonials widget on the home page].
Use storeos-docs MCP. get_page /docs/themes/widgets and /docs/cli/theme/new before editing.
Run storeos theme check before you stop.
Do not add widgets the goal does not need.

Storefront

Repo: Next.js app. StoreOS client is lib/store.ts (server-only STOREOS_API_KEY).
Tenant env: NEXT_PUBLIC_SITE_API_TENANT.
Goal today: [collection page with pagination].
Use storeos-docs MCP. get_page /docs/storefront-client/methods for the methods you call.
Do not invent endpoints. API errors go at the top of the page.

Dashboard

Repo: staff dashboard. Browser calls our /api/graphql BFF. The BFF adds x-storeos-key.
Goal today: [order detail with status update].
Use storeos-docs MCP. get_page /docs/guides/admin-dashboard and the Core reference page for each operation you add.
Operations are domain__operation. Permission errors stay visible.
API errors at the top of the form. Toasts only on success.

Review prompts

Run these before you merge. They ask for a check, not a rewrite.

Review this theme diff.

get_page /docs/themes/validation and /docs/themes/structure.
Report:
- document types with no widget file
- {% schema %} that does not match the widgets page
- missing content_for_header or content_for_layout
- a <title> or meta description the theme should not own
Then run storeos theme check and quote the result.
Do not change files unless I reply "fix".
Review this storefront diff for StoreOS usage only.

get_page /docs/guides/api-keys, /docs/getting-started, and /docs/guides/checkout.
Report:
- API key reachable from client code
- requests that skip x-storeos-key
- SDK method names that are not on /docs/storefront-client/methods
- checkout math that disagrees with /docs/guides/checkout
- API errors shown only as toasts
Do not change files unless I reply "fix".
Review this dashboard diff for StoreOS usage only.

get_page /docs/core-graphql-api and /docs/guides/admin-dashboard.
Report:
- operations that are not domain__operation
- selection sets you could not find on a reference page (name the page you opened)
- missing staff Bearer token on calls other than identity__login
- API key shipped to the browser
- GraphQL body.errors ignored
- permission checks that exist only in the UI
Do not change files unless I reply "fix".

What belongs in the prompt

IncludeWhy
The outcome and the route or widget nameStops the agent from scaffolding a second app
get_page paths from this guidePins the agent to current docs
Env names (STOREOS_API_KEY, tenant uid variable)The agent wires config without seeing the secret
"Run storeos theme check" on theme workSame checks as upload
A pasted error, with the key redactedThe agent fixes your failure, not a guessed one

Keep the API key, staff password, and customer OTP out of the chat. If a log line contains sos_live_…, delete that line before you paste.


DocUse it for
Docs MCPInstall the server in Cursor, Claude, Codex, ChatGPT
Theme quickstartinit, dev, package
Widgets and settingsSchema and built-ins
Getting startedFirst storefront client
CheckoutCart → order
Custom admin dashboardModule map for a staff app
Core GraphQLHeaders, identity__login, naming
API keysScopes and x-storeos-key

On this page