SPEC-STV-06-Template-System
SPEC-STV-06 · Spec header. Spec ID: SPEC-STV-06 · Title: Template System · Version: 1.0.0 · Status: Planned · Authority: Specification · Priority: P1 · Owner role: Frontend lead · Reviewers: Backend architect, Product architect · Last reviewed: 2026-05-11 · Sync targets: app/Services/Templates/**, docs/TEMPLATE_SYSTEM.md · Depends on: SPEC-STV-HUB, SPEC-STV-04 · Consumed by: SPEC-STV-03, SPEC-STV-10 · Conflict rule: Hub wins. · Change policy: Frontend lead + 1 reviewer; Registry bump.
1 · Categories (seeded)
- Project documentation
- API documentation
- Product spec
- Meeting notes
- Company wiki
- SOP
- Roadmap
- Task board
- Knowledge base
- Client documentation
- Mobile app spec
- Laravel project spec
- AI project spec
2 · Payload schema
A template's payload JSON is a serialized page tree:
{
"page": {
"title": "Product Spec",
"icon": "📐",
"cover_url": null,
"seo": null
},
"blocks": [
{ "type": "heading_1", "content": { "text": [{"text":"Overview"}] } },
{ "type": "callout", "content": { "text": [...], "icon":"🎯", "color":"blue_bg" }, "children": [...] },
...
],
"sub_pages": [
{ "page": {...}, "blocks": [...], "sub_pages": [...] }
],
"databases": [
{
"name": "Roadmap items",
"properties": [
{ "name": "Status", "type": "status", "config": {...} },
{ "name": "Due", "type": "date", "config": {} }
],
"views": [{ "name": "Board", "type": "board", "config": {...} }],
"seed_rows": [...]
}
]
}3 · Instantiate flow
- User picks a template (filter by category, preview image).
- POST
/templates/{id}/instantiatewith{ parent_page_uuid?, workspace_uuid }.
TemplateService::instantiate()creates the page tree depth-first inside a transaction, then queues aIndexRagSourceJobper new page.
- Returns the root page uuid + a deep link.
4 · Save-as-template flow
- User opens page menu → "Save as template".
POST /pages/{uuid}/save_as_templatewith{ name, category, scope: "workspace|global" }(globalis admin-only).
TemplateService::serialize($page)walks the page subtree and produces the payload. Files referenced by blocks are NOT duplicated — they remain infilesand are referenced by uuid; instantiation re-references the same files.
5 · Preview
GET /templates/{id}/preview returns a read-only render of the payload. The preview surface respects mobile breakpoints.
6 · Workspace vs global
workspace_id = null→ global template, visible to every workspace.
workspace_id = X→ only visible inside that workspace.
- Only admins (workspace-level) can save a workspace template. Only system admins can save a global template.
7 · Versioning
A template is content-addressed by sha256(payload). Editing a template creates a new row (immutable history); old instantiations are not retroactively updated.
8 · Seeds
A php artisan templates:seed command loads the 13 starter templates from database/seeders/templates/*.json so a fresh install ships with the full library.