---
title: Templates
description: 'Let people make independent copies of an app, then choose whether to publish it in the public Template directory.'
sidebar:
  label: Templates
  order: 9
---

## What you can do

**Turn an app into a Template.** People who can already view the source App can make an independent copy. Each copy has its own owner and empty storage, and can be edited as soon as Charming creates it. Changing a copy never changes the Template, and changing the Template never changes copies already made.

**Publish it as Listed.** A Listed Template appears in the public [Template directory](https://charm.ing/templates). Anyone can discover and copy it without gaining access to the source App or its data. Listed always includes Template. Template alone does not make an App public or let strangers copy it from a shared link.

**Choose how the listing looks.** Save a draft title, summary, longer Markdown description, category, cover image, and ordered screenshot gallery before publishing. A cover or screenshot needs alt text; its caption is optional. Publishing needs a nonblank title and summary. The other fields are optional.

**Keep Public separate.** Public opens the live App Viewer to anyone with its link. It does not make the App a Template. Template does not make the live App public. If an App is both Public and a Template, visitors open the live, read-only App and see an option to create a copy. See [Privacy and sharing](privacy-and-sharing) for the full access model.

**Set what visitors see first.** The owner can write a starter prompt so a visitor who clicks "Open in Claude" or "Open in ChatGPT" gets that instruction instead of the generic prompt. A fresh copy takes the current starter prompt once. Later changes to the Template do not alter existing copies.

## How Templates work

```mermaid
flowchart TB
    A["Your App<br/>source, data, and secrets"]
    A -->|"Enable Template"| T["Template<br/>existing App viewers can copy"]
    T -->|"Publish as Listed"| L["Listed Template<br/>anyone can discover and copy"]
    T -->|"Copy source"| C["Independent copy<br/>empty data and its own owner"]
    L -->|"Copy source"| C

    A -.->|"Data and secrets stay behind"| D["Source App data<br/>not shared with the copy"]

    classDef start fill:#e8611c,color:#fff,stroke:#e8611c;
    classDef enabled fill:#fff7f1,color:#26251f,stroke:#e8611c;
    classDef listed fill:#f9cfa2,color:#26251f,stroke:#a8440f;
    classDef private fill:#fdfdfb,color:#a8440f,stroke:#e8611c,stroke-width:1.5px,stroke-dasharray:5 4;

    class A start;
    class T,C enabled;
    class L listed;
    class D private;
```

For an app using the opt-in ESM contract, a new copy also requires an author eligible for that contract. Copy selects the active source and its completed server/browser output, even if a newer edit is pending or failed. If that output needs preparation under the current runner profile, the response supplies a build to inspect; no new app exists until it publishes. Repeating the request while pending returns the same build. See [npm and platform imports](../guides/npm-and-platform-imports#history-and-copies).

Making a copy copies source and the starter prompt. Data and secrets stay on the source App. The person who copies starts with empty storage and adds their own secrets if the code needs any.

Every enabled Template has a detail page at `https://charm.ing/templates/<owner>/<app-name>`. Listed pages are public and search-indexable. An unlisted page at the same stable path is available only to an authorized App reader and sends `noindex`, `nofollow`, and private no-store headers.

Public owner profiles live at `https://charm.ing/<handle>` and show that owner's Public Apps and Listed Templates. The same route works for people and teams. A signed-in team member normally sees Team Home at the team's route; adding `?view=public` shows the public team profile instead.

## Technical

Open the App's **App settings**, then choose **Template**. Its canonical settings path is `/<owner>/~/apps/<app-name>/settings/template`. Listing content can stay as a draft while Template and Listed are off.

### Copy this prompt for your agent

```text
Set up one of my Charming apps as a Template. Read
https://charm.ing/docs/capabilities/templates.md first. List my apps
and ask me which one, then ask whether its current viewers should be
able to copy it or whether I want to publish a public listing. If I
choose a listing, help me prepare its required title and summary plus
any optional detail and media, then give me its canonical Template URL.
```

### How an agent performs this job

Call [`set_template`](/docs/technical-reference/mcp/tools/set_template) with `{ app_id }` to enable Template. It accepts an optional listing patch with `title`, `summary`, `content_markdown`, `category`, `cover_asset_key`, `cover_alt`, `cover_caption`, and `gallery`. Each gallery item has `asset_key`, `alt`, and an optional `caption`. Media must use safe image assets owned by the same App, and alt text must not be blank.

Pass `listed: true` to apply the patch, enable Template, and publish the listing. The resulting title and summary must both be nonblank. Pass `listed: false` to unpublish while keeping Template enabled. Omit `listed` to preserve the current Listed state. Omitted patch fields also keep their current values; `null` clears a nullable field, and `gallery: null` or an empty gallery clears the gallery.

Call [`unset_template`](/docs/technical-reference/mcp/tools/unset_template) to disable Template and clear Listed. Existing copies keep working. The deprecated [`set_remixable`](/docs/technical-reference/mcp/tools/set_remixable) tool accepts only `app_id`: it enables Template but cannot edit listing metadata and leaves the Listed state unchanged. Its deprecated `unset_remixable` partner has the same effect as `unset_template`.

[`set_public`](/docs/technical-reference/mcp/tools/set_public) is a separate action that grants the live App Viewer by link. It does not enable Template or Listed. [`set_starter_prompt`](/docs/technical-reference/mcp/tools/set_starter_prompt) is also separate: it sets or clears the App's chat starter prompt and does not change listing fields or state.

To find Listed Templates, call [`search_templates`](/docs/technical-reference/mcp/tools/search_templates) with an optional `query`. Results include the resolved listing title, summary, Markdown detail, category, cover, starter prompt, creator, builder count, canonical `templatePageUrl`, and browser `copyUrl`. The copy URL starts browser navigation where the visitor chooses to copy and signs in before Charming creates the owned App. It is not an MCP or REST write. After creation, find the copy with `list_apps` or `GET /app`, then read its source with `get_app_source` or `GET /app/<id>/source`.

### First-party Template listing API

The session-gated resource is `/api/v1/apps/{appId}/template-listing` and requires `app:template-edit`:

| Method  | Path                                              | Effect                                                                                      |
| ------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `GET`   | `/api/v1/apps/{appId}/template-listing`           | Read the draft, resolved fallback values, media URLs, validation state, and Template flags. |
| `PATCH` | `/api/v1/apps/{appId}/template-listing`           | Patch draft content only. It does not enable, disable, publish, or unpublish.               |
| `POST`  | `/api/v1/apps/{appId}/template-listing/enable`    | Enable Template while preserving the draft and Listed state.                                |
| `POST`  | `/api/v1/apps/{appId}/template-listing/publish`   | Require a title and summary, then enable Template and publish Listed atomically.            |
| `POST`  | `/api/v1/apps/{appId}/template-listing/unpublish` | Clear Listed while preserving Template and the draft.                                       |
| `POST`  | `/api/v1/apps/{appId}/template-listing/disable`   | Disable Template and clear Listed while preserving the draft.                               |

The first-party API uses camelCase draft fields: `contentMarkdown`, `cover: { assetKey, alt, caption? }`, and `gallery: [{ assetKey, alt, caption? }]`. The older public-agent `PUT /app/{id}/remixable` route changes only the Template and Listed flags; use the first-party resource or `set_template` for listing metadata.

### The contract

An owner, collaborator, or team member with `app:template-edit` can change Template content and state. An anonymous App must be [claimed](/docs/technical-reference/authentication#claim-an-anonymous-app) first.

Template copying requires both an enabled Template and either Listed or existing `app:read` access to the source App. Listed grants public discovery and copying, not `app:read` on the source App. It exposes neither the live App nor its data. Public grants `app:read` to the live hosted App Viewer but does not by itself allow a Template copy.

The App belongs to the signed-in user from creation. The copy flow creates no pre-auth App and no copy or Claim cookie. An existing copy remains in the user's App list and opens only after they choose "Open my copy."

Listing requires the app to already be copyable — a listed app can't be made uncopyable without also being unlisted. Any listed app appears in the store, whether or not it's also `public` (per [Privacy and sharing](privacy-and-sharing)): a public template renders the live app directly for visitors, with a "Create my copy" action in place of the usual template interstitial.

Disabling Template also unpublishes it. Unpublishing alone keeps Template enabled. Neither action removes existing copies or the saved listing draft.

An owner-facing app UI can call `window.charming.remixable.set(true)` or `.set(false)` from a Charming browser shell. It resolves with `{ remixable, public_url }`. See [Owner controls](/docs/technical-reference/browser-runtime#owner-controls) for availability and errors.

### The starter prompt visitors get

Use [`set_starter_prompt`](/docs/technical-reference/mcp/tools/set_starter_prompt) to set or clear the prompt. A copy carries the current prompt once; later template changes do not alter existing copies.

### Limits, access, and deletion

- See [Limits](limits#per-app-limits) for the starter prompt cap.
- Deleting or unlisting the source App does not remove copies already made.
- Listed pages and public owner profiles expose listing content, creator identity, and builder counts. They do not expose source App data or secrets.

## Related

- [Privacy and sharing](privacy-and-sharing): how Public, App roles, and Template access differ
- [Code export](code-export): export source directly instead of using the browser copy flow
- [Data storage](data-storage): what does and does not carry into a copy
- [How Charming works](../concepts/how-charming-works)
- [Browser runtime API](../technical-reference/browser-runtime)
- [Docs home](..)
- [llms-full.txt](https://charm.ing/docs/llms-full.txt)

Found a bug or need a feature? [Tell us](/docs/capabilities/feedback) with `submit_feedback` or `POST /app/{id}/feedback`. Your feedback shapes what we build next.
