Skip to content
littleworksdocs

Explore the documentation

Meet LittleworksA little backend for what you’re building on Shopify.Littleworks or your own appWhat it takes to give a Shopify feature a backend: with Littleworks, or with a custom app you build and run yourself.Connect to LittleworksChoose the CLI, a plugin, or a remote MCP connection.CLIConnect from your terminal with Shopify approval and no manual tokens.Claude pluginThe Littleworks MCP connection and agent guidance in one package.OpenAI pluginThe Littleworks MCP connection and agent guidance in one package.MCP with OAuthConnect a compatible client directly, without a marketplace plugin.Build with an agentThe operating guide for agents building on Shopify with Littleworks.Write a workA JavaScript handler, a small manifest, and a version you test and then publish.Keep secretsEncrypted credentials, shared across your store’s works.Call external servicesMake public HTTPS API requests from a work using http.fetch().Store dataDocument collections with a small API, scoped automatically to the work that uses them.Call ShopifyCall Shopify’s Admin and Storefront GraphQL APIs with credentials held by Littleworks.Store filesKeep uploads such as artwork and photos in the merchant’s Shopify Files, uploaded by the browser straight to Shopify.Expose an endpointConnect an existing frontend to a work through a small JSON API.Customer access and invitationsRequire a signed-in shopper or a narrow, expiring invitation before a work runs.RecipesUseful things to build for your store, with the backend already taken care of.Product reviewsCollect customer reviews, verify purchases, and publish approved content directly into your Shopify theme.Customer wishlistsGive signed-in customers a persistent list of products they can revisit across devices.Customer quote requestsCollect a customer’s products, quantities, and requirements without turning a request into an order.Back-in-stock alertsCollect confirmed signups on sold-out variants, email them through your own provider when stock returns, and see every signup and send in your admin.Transactional emailSend email from your works through your own provider, never twice for the same thing, and see what was sent and what failed.Build a merchant pageDescribe your records and what merchants do with them; Littleworks renders a native Shopify admin page.Run works on their ownRun a work when something happens in the store, on a schedule, or from a Shopify Flow workflow.Run background jobsQueue runs for later or in the background: fan out to thousands of customers, import in pages, follow up days later, and retry what fails.MCP tool referenceTools to inspect, deploy, run, and organize the backend for a connected store.Usage and allowancesSee what your works use, how much capacity remains, and when allowances reset.Inspect and troubleshootFind the relevant run, understand the failure, and make the next change deliberately.Limits and securityThe current runtime boundaries, data isolation model, and execution allowances.
Shopify admin
Build
Markdown

Expose an endpoint

Connect an existing frontend to a work through a small JSON API.

Every endpoint is protected before your code runs, so a work only handles requests that already passed these checks:

  • Input validation against the work’s inputSchema. Invalid requests are rejected and don’t use a run.
  • Rate limiting and burst protection per endpoint and per visitor, at Cloudflare’s edge and again at admission.
  • Allowed origins for browser calls (CORS).
  • Identity, when the work asks for it: a signed-in Shopify customer verified through the app proxy or a headless storefront’s signed assertion, a merchant session, or a single-use invitation token.
  • Edge caching, when a public GET work opts in. Responses served from the cache don’t run your work. See Cache a public read.

Your work still enforces business rules, such as whether this customer owns this record. For a public form, add what the feature needs on top: a uniqueness rule against duplicate signups, or a confirmation email before acting on an address.

Choose the entry point

TriggerWho can invoke it
callableAn authenticated merchant or store-scoped agent through Littleworks. No public HTTP function route.
HTTP, auth: "public"Anyone who can reach the endpoint, subject to input validation, origin policy, and traffic limits.
HTTP, auth: "customer"A signed-in storefront customer: verified through Shopify’s shared app proxy on a theme, or asserted by a headless storefront’s server (Hydrogen) with a signed token. See customer access.
HTTP, auth: "token"A caller with a valid invitation token for this work and version.
HTTP, auth: "merchant"An authenticated merchant or store-scoped agent. This is not customer-account authentication.

Declare an HTTP trigger

Manifest trigger
{
  "trigger": {
    "type": "http",
    "method": "POST",
    "auth": "public",
    "origins": [
      "https://your-store.example"
    ]
  }
}

Replace the example origin with the exact origin of the frontend, including its scheme. Declare GET or POST. POST accepts a JSON object; GET supplies query parameters as strings. Set an appropriate inputSchema for those values.

deploy_function, get_function and list_functions return the URLs of an HTTP work: previewUrl always, and url once the work is published (a paused work keeps it). Customer works add headlessPreviewUrl and headlessUrl for headless storefronts. Use them instead of constructing a path from a shop domain.

Real and preview URLs

URLRuns
Real: https://littleworks.app/f/{store}/{name}The current version of a published work, as a real run. Draft works return FUNCTION_NOT_PUBLISHED; paused works return FUNCTION_PAUSED.
Preview: https://littleworks.app/f/{store}/preview/{token}/{name}The newest version, as a test run, whatever the work’s status.
Customer works: /apps/littleworks/{name} and /apps/littleworks/preview/{token}/{name}The same pair through the store’s app proxy, for themes. A headless storefront’s server calls the direct /f/ pair instead, returned as headlessUrl and headlessPreviewUrl, with a signed customer assertion.

The preview token is unguessable and belongs to one work. Use the preview URL to try a draft, or a pending version of a published work, from an unpublished theme or another frontend before publishing. Point published frontends only at the real URL: a preview URL runs whatever is deployed next, and documents it creates are test records. A merchant can rotate a work’s preview token in Littleworks; the old preview URL then returns 404.

Call from your frontend
const response = await fetch(workUrl, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ message: "Hello" }),
});

if (!response.ok) throw new Error("The request could not be completed");
const result = await response.json();

Here, workUrl is the URL returned by deployment. The input must match your work’s schema. Littleworks hosts the endpoint; your agent still needs to build and place the frontend using the appropriate theme or storefront tools.

Decide what a public request may do

For example, accepting a verified-purchase review requires server-side validation of a purchase-linked invitation. A public endpoint and a customer-supplied order ID alone do not establish eligibility. Never put an agent token in storefront code.

Return JSON

Return a JSON-compatible value or Response.json(...) with a status. Littleworks forwards the body and status, not arbitrary headers, cookies, streaming output, or HTML. This is an API endpoint, not a frontend hosting service.

Cache a public read

A published public GET work can let Cloudflare’s edge answer repeat requests. Reviews, badges, counters and other display data change far less often than shoppers read them. A cached response is fast and doesn’t use a run; the request that fills or refreshes the cache is an ordinary run.

Manifest trigger
{
  "trigger": {
    "type": "http",
    "method": "GET",
    "auth": "public",
    "origins": [
      "https://your-store.example"
    ],
    "cache": {
      "seconds": 3600,
      "staleSeconds": 600
    }
  },
  "inputSchema": {
    "type": "object",
    "properties": {
      "product": {
        "type": "string"
      },
      "country": {
        "type": "string"
      }
    },
    "additionalProperties": false
  }
}
Entry pointCached
HTTP GET, auth: "public", real URLYes, when the trigger declares cache.
Preview URLNever. It runs the newest version as a test run and returns X-Littleworks-Cache: BYPASS.
auth: "customer", "token" or "merchant"Never. Those responses belong to one caller.
POST, callable, page and automation worksNever.
Requests with Authorization or Idempotency-KeyNever; they run the work.
  • Freshness. seconds (10–86,400) is how long a response is served as fresh. staleSeconds (0–86,400, default 0) lets the edge keep serving it for that much longer while one run refreshes it in the background, which improves latency, not run count. If a refresh fails, the last response can be served a little longer.
  • What is stored. Only status 200 responses. Errors, 4xx and 5xx results, and Littleworks errors such as FUNCTION_PAUSED or a full run allowance always reach the caller.
  • The query is the key. The whole query string, sorted, keys the cache, so the input schema needs explicit properties and additionalProperties: false: an unknown parameter is rejected instead of creating a new entry. A repeated parameter or a query longer than 1,024 bytes runs the work without the cache.
  • Shared responses. Cached responses are shared by everyone who sends the same query; never return personal data from a cached work. Cached works receive no buyer IP, so pass market and language as explicit parameters (for example country and language for Storefront @inContext).
  • Read-only. Every run of a cached work, test runs included, can read documents, secrets, Shopify (queries only) and external services with GET or HEAD. Writes, auth.issueToken and cache.purge fail with CACHED_WORK_READ_ONLY. Deploying reports a warning when the source appears to write.
  • Changes take effect within about 15 seconds. Publishing, rolling back, pausing, resuming, deleting and purging reach every edge location within about 15 seconds; until then the previous responses may still be served. Browsers never cache responses (Cache-Control: no-store).
  • Purge after a write. Another work in the same feature calls await cache.purge("reviews.list") after it changes what the cached work returns, for example when a review is approved (at most 5 purges per run). Agents use purge_cache; the CLI uses littleworks cache purge <name>. A purge clears every query of the work.
  • Check it. After publishing, request the real URL twice and read the X-Littleworks-Cache header: MISS (a run, with X-Run-Id), then HIT (with Age). STALE means a refresh is under way; BYPASS means the request ran without the cache. Local development has no edge cache.

Savings depend on traffic: a key saves runs only when it is requested again within seconds. Fewer, broader keys save more. One badge map for the whole store beats one request per product. The Usage page shows responses served from cache separately from runs.

Handle traffic protection

Littleworks automatically applies burst, concurrency, per-work and store execution limits, plus storage and external-request allowances. Littleworks time-based limits return HTTP 429 with Retry-After and error.retryAt. Cloudflare may block a flood before it reaches Littleworks; handle HTTP 429 even when the response is not JSON. Back off; do not automatically replay a mutation. The Shopify admin shows affected works and retry guidance. These limits are platform policy, not merchant settings.