AI/AI rules
AI rules
Rules for AI coding tools working on a Poltura app or theme. The same text ships as AGENTS.md and as a Cursor rule.
On this page
These rules are for AI coding tools working on a Poltura app or theme. The full documentation index is at
https://developers.poltura.com/llms.txt, and every page is also available as Markdown by adding .md to its
address.
Always
- Read the matching docs page before writing code, through its
.mdaddress. - Use only the public packages:
@poltura/app-sdk,@poltura/app-ui,@poltura/app-contracts,@poltura/cliand@poltura/theme-sdk. Never import other@poltura/*packages and never reach a store's database. - Do not invent APIs. If a name is not in the docs or in the package's types, it does not exist.
- Before you say the work is done, run
poltura checkin the app or theme directory and fix every error it reports. Each finding names the rule and says what to change. Usepoltura check --jsonto read the result.
Apps
- An app is
poltura.app.jsonplus its sources. Scaffold one withpoltura app create <dir> --template nativeor--template hosted. - After every change run
poltura app buildandpoltura app validate, and fix every error before moving on. Before finishing, runpoltura check: it adds the permission, agent entry and code rule checks. - Parse input where it enters your code: no
unknownparameters or return types, no dictionaries ofunknown,anyorobject, no runtimetypeofon unparsed values, and a// SAFETY:comment on every type assertion. - Declare the fewest permissions the app needs. Each permission needs a
purposeof 8 to 280 characters that a merchant understands, because merchants read it before they approve. - Declare storefront blocks and their settings once, with
defineBlockfrom@poltura/app-sdk/elements, in the fileelementsnames. A worker reads the merchant's values withuseSettings(). - A worker file starts with
import '@poltura/app-ui/worker', renders withstartUiWorker(<Root />)from@poltura/app-ui/worker-runtime, and draws only with the primitives of@poltura/app-ui/admin(admin targets) or@poltura/app-ui/storefront(storefront targets). - Workers cannot fetch your server or the App API. They call your backend through
useAction(actionId), and the backend verifies the request withcreateActionHandlerfrom@poltura/app-sdk/actions. - Installation access tokens stay on your server. Never send one to a worker, an iframe or the browser.
- Call the App API with
PolturaClientfrom@poltura/app-sdk. Lists are cursor pages (limitup to 100, thennextCursor). Every write carries anIdempotency-Key. Money is{ amount: "49.99", currency: "EUR" }in major units; never multiply by 100. - Verify every webhook with
createWebhookVerifierfrom@poltura/app-sdk/webhooksbefore reading its body. Deliveries are retried, so handling one twice must be harmless. - Publish with
poltura app publish --api "$POLTURA_API" --token "$POLTURA_APP_TOKEN", withappIdinpoltura.app.jsonor--app. The token is a developer token (pltd_for CI, or a personalpltu_) from Developer apps. Never commit a token.
Themes
- A theme is TSX and JSON, edited in the store's theme code editor. Saves go to the theme's draft; publishing is a separate step.
- Import Poltura APIs from
@poltura/theme-sdk/<module>(there is no root import). Besides that a theme may import its own files, React and a fixed set of UI libraries the theme check names; anything else is refused. - Write one section per file,
src/sections/<type>.tsx, and one block per file,src/blocks/<type>.tsx, declared withdefineSectionordefineBlockfrom@poltura/theme-sdk/elements. Thetypeis kebab-case, matches the file name and stays fixed once merchants use it; rename withrenamedFrom. - A section's component receives
attrs. Spread them onto exactly one root element and merge classes withcn(attrs.className, ...)from@poltura/theme-sdk/ui. Without that, the merchant's style controls do nothing. - Settings are
field.*builders with alabeland adefault. Read them from the typedsettingsprop, and useEditableTextfor text merchants edit in place. - Draw prices with the
priceparts and format any other amount withuseFormat().money(). Never format money by hand. - Theme code renders on the server for every shopper of the store: no per-shopper state and no clock reads at
module scope, and no
windowordocumentoutside effects. - Default copy has no em dashes and no middle dots.
- In the code editor the theme check runs on every save. Fix every problem it reports before publishing.
- Working on a theme in files, run
poltura checkbefore finishing; it runs the theme check and the code rules.