# How apps work (/apps)

A Poltura app adds pages, panels and storefront blocks to every store that installs it. You describe the app
in one manifest, `poltura.app.json`, and publish a release with the `poltura` CLI. A platform reviewer checks
that exact release, and a merchant approves the permissions it asks for before it reaches their store.

Your code never runs inside the store's servers. UI runs in a separate, secure environment that draws Poltura's own
components, and anything that needs data runs on your server, which calls the App API with the token the
merchant's approval gave you.

- [Build your first app](/apps/build-your-first-app): Scaffold, build, validate and publish, in about fifteen minutes.
- [Example app walkthrough](/apps/tutorial): The complete Recommendations example, file by file.
- [Ship to merchants](/apps/ship): Review, install, updates and what it costs.


## Why build on Poltura [#why-build-on-poltura]

- **European merchants.** Poltura is a hosted e-commerce platform built for European merchants, Hungary first.
  Stores sell in many languages and currencies, so one app reaches shops in several countries.
- **Native from the first line.** Workers draw with Poltura's own components, so your app looks like the admin
  and like each store's theme without CSS of yours. See [UI](/apps/ui).
- **Trust built in.** Every release is reviewed before merchants see it, merchants approve each permission, and your
  code never runs on the store's servers.
- **Clear terms.** Free apps cost nothing to publish. Paid apps are not offered yet, so there is no revenue share
  and no payout. See [Ship to merchants](/apps/ship#what-it-costs).
- **Ready for AI tools.** Every page here is Markdown for your coding agent, with `llms.txt` and rules files for
  Cursor and other tools. See [Build with AI](/ai).

## Where an app shows up [#where-an-app-shows-up]

| Surface               | Declared with                                                        | Where the merchant sees it                                    |
| --------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------- |
| Admin page            | a worker with target `admin.page` and an entry in `adminPages`       | Apps in the admin navigation, `/apps/:installationId/:pageId` |
| Home card             | target `admin.home`                                                  | The admin home                                                |
| Detail panel          | `admin.product`, `admin.collection`, `admin.order`, `admin.customer` | Product, collection, order and customer pages                 |
| Hosted admin page     | `adminFrame.url` and `adminFrame.actions`                            | Connected apps, in an iframe you host                         |
| Storefront block      | `storefront.<template>`                                              | The customizer, on that template                              |
| Header or footer zone | `storefront.layout.header`, `storefront.layout.footer`               | The theme's header and footer                                 |
| Storefront app page   | `storefront.app-page` and an entry in `storefrontPages`              | `/apps/<slug>` on the storefront                              |

`poltura app build` turns the `workers` of `poltura.app.json` into the release manifest and copies `adminPages`
and `storefrontPages` onto it, up to 8 of each. Without those lists, the Apps navigation and `/apps/<slug>` stay
empty. Details: [Admin](/apps/admin), [Storefront](/apps/storefront), [UI](/apps/ui).

## Native or hosted [#native-or-hosted]

- **Native workers** draw with Poltura's primitives from `@poltura/app-ui`, so they look like the admin or the
  store's theme without any CSS of yours. They cannot fetch your server or the App API; they call your backend
  through a declared action, and the host signs the request.
- **Hosted pages** are an HTTPS page you serve in an admin iframe. Use them when you need your own DOM. The page
  proves which merchant is looking with a session token that lasts 60 seconds and is not an API token.

## What stays on your server [#what-stays-on-your-server]

- **Installation access tokens.** Your server receives them when the merchant approves the app's grant on Poltura ID. Workers
  and iframes never receive them. See [Authentication](/apps/auth).
- **Store data.** Your server calls the [App API](/api/app) under the permissions the merchant granted, and receives
  signed [webhooks](/apps/webhooks).

The manifest rejects fields that would reach into the platform itself before anything else is checked. The
[manifest reference](/apps/manifest) lists the names that fail.

## Packages [#packages]

(Not published to npm yet.)

| Package                          | What you import                                                                                           |
| -------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `@poltura/cli`                   | The `poltura` command: `app create`, `dev`, `build`, `validate`, `elements`, `publish`, and `theme check` |
| `@poltura/cli/ui-styles`         | `compileUiStyles`, to compile worker CSS outside the CLI                                                  |
| `@poltura/app-sdk`               | `PolturaClient` for the App API                                                                           |
| `@poltura/app-sdk/oauth`         | `createPublicAppOAuthClient` (server)                                                                     |
| `@poltura/app-sdk/session`       | `createAppSessionVerifier` (server)                                                                       |
| `@poltura/app-sdk/webhooks`      | `createWebhookVerifier` (server)                                                                          |
| `@poltura/app-sdk/actions`       | `createActionHandler` for worker actions (server)                                                         |
| `@poltura/app-sdk/elements`      | `defineBlock` and `field` for storefront blocks                                                           |
| `@poltura/app-sdk/frame`         | `connectAppFrame`, `requestAppSession` (hosted page, browser)                                             |
| `@poltura/app-ui/admin`          | Admin primitives and hooks                                                                                |
| `@poltura/app-ui/storefront`     | Storefront primitives and hooks                                                                           |
| `@poltura/app-ui/worker`         | Worker bootstrap; import it first                                                                         |
| `@poltura/app-ui/worker-runtime` | `startUiWorker`                                                                                           |
| `@poltura/app-ui/dom`            | Primitives for hosted pages                                                                               |
| `@poltura/app-contracts`         | Manifest parsing, permissions, API shapes and events                                                      |
