id: fragment.editor-templates.001
freshvibe_way_version: v8
date: 2026-07-31
last_rewritten: 2026-07-31 (Phase 8 v2)

# editor-templates — manage templates for the content types

## What it does

A **template** is a pre-filled record (e.g. "Modern Downtown Apartment" for a Listing type) that the operator can clone to start a new record. The templates panel lets the operator:

- List all templates (per-site + opt-in globals)
- Create a new template from a record
- Edit a template
- Delete a template (soft-archive, per b243 Rule 1)
- Clone a template into a new record

## Why this is its own feature

Templates are the operator's "starting points" — they let the operator create a new recipe without re-typing all the standard fields. The cluster rule holds:

1. **List templates per type** — paginated, sortable
2. **Create template from record** — "Save current record as template" button in the record form
3. **Edit template** — same form as records
4. **Clone template to new record** — "New from template" button in the records list
5. **Site-scope default** — templates default to site-scoped, opt-in global
6. **AI affordances** — per §3.11-§3.14

## Where the data lives

Templates are stored in the **same per-site content-items store**, but with a special `type` prefix (`template:Recipe`, `template:Listing`). The records store doesn't distinguish between templates and records — the type field does. The templates fragment just queries with the `template:` prefix.

## Where it sits in the chrome

The templates panel is one of the panels available in the operator's `{ }` Dev button dock. It co-exists with `editor-content-admin` and the other fragments.

## Usage

```js
import { openTemplatesPanel } from '../editor-templates/index.js';

const panel = openTemplatesPanel({
  type: 'Recipe',         // optional: filter to this type
  onClone: (template) => { /* pre-fill the record form */ }
});
```

## Contract

This fragment exposes:
- `openTemplatesPanel(opts)` → DOM element
- `closeTemplatesPanel()` → void
- `createTemplateFromRecord(record, type)` → Promise<template>

Cross-fragment imports go through `index.js`, not `runtime/`. Implementation is in `app-fragments/editor-templates/runtime.js` (kept private to this folder).
