.dev
Storefront templates

Develop and publish

The developer loop for a Feeef theme — edit, preview a draft on the real shop, then publish a release and decide when customers see it.

This is the loop I use after the folder exists. The first-time scaffold is Create a template. This page is what happens every day after that: develop against a draft, then publish a release.

Helium drafts use {slug}.h.feeef.store; Lithium drafts use {slug}.feeef.store. For Helium, review the runtime and hydration contract alongside this release workflow.

Two documents live on the store. They are easy to mix up, and mixing them up is how a half-finished hero reaches a customer.

DraftLive
Commandnpm run devnpm run publish -- --apply
Fieldmetadata.templatePreviewmetadata.templateData
Who sees itYou, with the preview cookieCustomers

npm run dev never writes the live document. Publish uploads a listing and a release. Customers see that release only when something installs it. From the CLI, that install is --apply.

Develop

Edit pages/, shared/, library/, locales/, and schema.ts. Then:

npm run check     # validate, write nothing
npm test          # smoke: render every App()
npm run dev       # watch, rebuild, upload the draft, open ?preview=

check is the fast one. Smoke catches a component that throws while rendering. Neither replaces clicking the draft: home, a product, checkout. The products and prices are the store's real catalog.

The preview URL sets an httpOnly feeef_preview cookie for 24 hours, so the next pages stay on the draft. Leave with the banner, /?preview=0, or by stopping the CLI. Stopping the CLI clears the draft blob.

The CLI and shop must read the same API. The CLI defaults to alpha; for a production store select the production API and sign in again:

feeef config set apiUrl https://api.feeef.org/v1
feeef signin

A few authoring facts I keep relearning:

  • schema.ts pages defines the editor page list. A new folder under pages/ also needs an entry there, or the editor will not offer the page.
  • feeef template add page updates feeef.template.json only. It does not edit schema.ts.
  • props is merchant content. code and propsSchema sit beside props, not inside it.
  • library/components/ is the drag-drop catalog. A library file is not on a page until someone inserts it.
  • Hand-editing dist/data.json is wasted work. The next build overwrites it.

The blank product page is already a slotted order form. Field visibility and order are props on those nodes. The worked example is on the create guide.

Publish

feeef template publish builds again, then uploads. You do not have to run npm run build first. npm run publish is the same command, and npm needs -- before CLI flags:

npm run publish -- --no-apply

What one publish writes:

TargetWhat lands there
template_componentsshared/, library/, and each unique page-level custom body
store_templatesThe listing: title, policy, price, head schema and data
store_template_releasesAn immutable semver snapshot and the changelog
store_template_localesdist/locales/*.json

Page-level customs are uploaded too, then the document stored on the listing points at them with type: "reference". That is why a missing slotsSchema on a shell makes the shop render an empty slot: the registry never receives the holes.

Locales are stripped out of the template document and stored as their own rows. The shop still speaks Arabic and English. The strings just do not ride inside templateData.

When customers see it

InvocationListing and releaseLive shop
npm run publishUpdatedAsks. Enter means no.
npm run publish -- --applyUpdatedInstalled. Customers see it.
npm run publish -- --no-applyUpdatedUnchanged
npm run publish -- --yesUpdated, no questionsUnchanged
npm run publish -- --yes --applyUpdated, no questionsInstalled

--yes means "do not ask me." It does not mean "install." I have published a changelog while the draft was still wrong, so the install stays a separate flag.

If your installed CLI still highlights yes on that question, update @feeef.dev/cli. Older builds treated Enter as install.

Who can see the listing

FlagPolicy
(none)private. Your store. Not in the public browse.
--publicAnyone can find it. Free unless you set --price.
--unlistedReachable with the link, not listed in browse.
--price 5000One-time price in DZD. 0 is free. The platform takes a cut on a sale.
--version 1.2.0Release semver. Omit it and the CLI bumps the patch.
--changelog "RTL on the form"Shown to merchants on Update.
--title "My theme"Listing title. Default is the manifest name or the folder name.
# private release, live on your store
npm run publish -- --apply

# free public listing, do not touch the live shop yet
npm run publish -- --public --no-apply

# paid public listing and install
feeef template publish --public --price 5000 --version 1.0.0 \
  --changelog "First release" --apply

A public or paid release can die in the security scan. The scan reads the custom function bodies. When it fails, that release does not exist. Fix the component the error names. The listing update may already have happened; the release is the part that stopped.

Paid themes cannot be unpacked with feeef template init --from. Merchants buy and install them from the app. Free public themes can be unpacked, and their library references are inlined so the folder stands alone.

After it is live

The merchant editor can still change props, slots, and layout children on the installed document. Your next npm run publish -- --apply installs the new release over that document. Say so in the changelog when the update will move blocks they rearranged.

Cover, screenshots, category, and the long description are listing fields. Publish sends title, policy, price, schema, and data. The rest is a later edit on the listing, from the merchant app or PATCH /store_templates/:id. Details are in Marketplace.

A demo link can preview a release without installing it:

https://{slug}.feeef.store/?templateId={listingId}&templateRelease={releaseId}

Exit with /?templateRelease=0. That is a different cookie from draft preview.

When something looks wrong

What you seeWhat it usually is
Preview matches the old shopCLI apiUrl is not the API the shop reads, or the preview cookie is gone
npm run publish and customers already have itYou passed --apply, or an older CLI treated Enter as yes
New page exists on disk and not in the editorschema.ts pages was not updated
A slot on a published shell is emptyThe component row was saved without slotsSchema
Public publish dies after "Publishing release"securityScan rejected a custom function
Inspector has no fieldspropsSchema is missing or nested under props

Command reference: CLI. First scaffold: Create a template. The same loop, as a note: Develop on a draft.

On this page