VibeWeek
Home/Grow/Workspace Templates & Cloning — Chat Prompts

Workspace Templates & Cloning — Chat Prompts

⬅️ Back to 6. Grow

If your B2B SaaS lets users create projects, workspaces, documents, dashboards, or any structured collection — eventually a customer will say "I want to start a new one that looks like the last one." Then: "I want to share a template with my team." Then: "I want to publish a template to your community for others." Templates are how users avoid recreating structure from scratch — and how power-users + agencies + consultants spread best practices.

The naive shape: "Duplicate" button on a project. Works for v1. Doesn't survive once templates need to be shared across users, contain references that should be reset (dates, assignees, statuses), have public/private modes, support placeholders ({{client_name}}), or distinguish between the structure (fields, sections) vs. the content (sample values).

A real template system handles: cloning vs templating (different operations), template metadata + categorization, sharing modes (private / workspace / public), placeholder substitution, reference handling (reset assignees, dates), nested resource preservation, version control, attribution, and a marketplace if scaled. Linear's template gallery, Notion's template directory, ClickUp templates, Airtable Universe — every modern collaborative SaaS ships this; it's table stakes for sticky workflows.

This chat walks through implementing a real template + cloning system: data model, cloning semantics, template metadata, sharing + permissions, placeholder substitution, marketplace patterns, and operational realities.

What you're building

  • Cloning of resources (project, workspace, document, dashboard, etc.)
  • Template definitions distinct from clones (templates are first-class objects)
  • Template metadata (name, description, preview, category, author)
  • Sharing modes (private / workspace / public)
  • Placeholder substitution ({{client_name}}, etc.)
  • Reference handling (reset / preserve / remap)
  • Template gallery / browse UI
  • "Use this template" creation flow
  • Marketplace patterns (if public)
  • Operational concerns (versioning, abuse, attribution)

1. Decide cloning vs templating

First decision: clone or template? They look similar but are different.

CLONING (instance copy)
- Take resource X; produce X' that's an independent copy
- All fields copied; reference IDs new
- One-time operation
- No ongoing relationship between X and X'
- Use case: "duplicate this project for next quarter"

TEMPLATING (reusable pattern)
- Take resource X; mark/save it as a "template"
- Template is a first-class object (separate from regular resources)
- Many users can spawn copies from the template
- Optional: template can be updated; existing instances NOT affected
- Use case: "save this as a template; let my team start projects from it"

Both are valuable. Most products ship cloning first; add templating when users ask "can I share this?"

Three increasingly-deep shapes:

LEVEL 1: CLONE ONLY (the simplest start)
- "Duplicate" button on a resource
- One-shot copy; no template object
- Pros: ships in 1-2 weeks
- Cons: no sharing; no metadata; no marketplace

LEVEL 2: WORKSPACE-PRIVATE TEMPLATES
- Save as template (creates a separate template object)
- Template stays in workspace; team members can use
- Template metadata (name, description, preview)
- Pros: 4-6 weeks; high-leverage for teams
- Cons: no public templates yet

LEVEL 3: PUBLIC TEMPLATE GALLERY
- Templates can be published to public gallery
- Categorized; searchable; rated
- Author attribution; usage analytics
- Pros: marketing channel; viral
- Cons: 12-24 weeks; abuse / quality moderation; ongoing curation

LEVEL 4: TEMPLATE MARKETPLACE
- Level 3 + paid templates / monetization
- Author payouts; revenue share
- Curation team
- Pros: ecosystem play
- Cons: massive ongoing engineering; rare in B2B SaaS

DEFAULT FOR MOST B2B SaaS:
- Year 1: Level 1 (clone only)
- Year 2: Level 2 (workspace templates)
- Year 3+: Level 3 (public gallery) IF community pull justifies
- Don't pre-build Level 4 without specific buyer

Output: scope decision; explicit boundary.

Output: scope statement; what's in v1 and what's not.

2. Design the data model

Schema for templates:

If just cloning (Level 1): no new schema needed. The "duplicate" function reads the source resource + creates new rows.

For Level 2+ (templating):

templates (
  id              uuid pk
  workspace_id    uuid  -- nullable for global / public templates
  resource_type   text  -- 'project', 'workspace', 'document', 'dashboard'
  name            text not null
  description     text
  preview_image_url text
  category        text  -- 'engineering', 'marketing', 'sales', etc.
  tags            text[]
  visibility      text  -- 'private' | 'workspace' | 'public'
  status          text  -- 'draft' | 'published' | 'archived'
  source_resource_id uuid  -- the resource this template was created from (snapshot)
  template_data   jsonb  -- full structured snapshot of the resource
  schema_version  int    -- for migrations as resource shape evolves
  author_user_id  uuid
  workspace_owner uuid  -- which workspace owns this template
  created_at      timestamptz
  updated_at      timestamptz
  published_at    timestamptz
  use_count       bigint default 0  -- denormalized counter
  star_count      int default 0
)

UNIQUE INDEX (workspace_id, name) WHERE visibility = 'workspace'
INDEX (visibility, category) WHERE status = 'published'

template_uses (
  id              uuid pk
  template_id     uuid not null
  used_by         uuid not null  -- user
  workspace_id    uuid not null
  created_resource_id uuid  -- the new resource created from template
  used_at         timestamptz
)

template_stars (
  user_id         uuid
  template_id     uuid
  starred_at      timestamptz
  PRIMARY KEY (user_id, template_id)
)

Why store template_data as snapshot JSONB (rather than reference source):
- Templates need to be stable; source can change/delete
- Use is read-only; performance better with snapshot
- Template versioning easier
- Can re-export later if needed

template_data shape (varies by resource_type):

For a project template:

{
  "schema_version": 1,
  "resource_type": "project",
  "fields": {
    "name": "Project name placeholder",  // PLACEHOLDER text
    "description": "Default description",
    "color": "blue",
    "starts_at": null,  // RESET ON USE
  },
  "sections": [
    { "id": "section1", "name": "To Do", "order": 0 },
    { "id": "section2", "name": "In Progress", "order": 1 },
    { "id": "section3", "name": "Done", "order": 2 }
  ],
  "tasks": [
    {
      "id": "task1",
      "title": "Kickoff meeting",
      "section": "section1",
      "assignee": null,  // RESET ON USE
      "due_date": null,  // RESET (or relative-to-creation)
      "priority": "high",
      "tags": ["meeting"]
    },
    // ... more
  ],
  "settings": { ... },
  "placeholders": [
    { "key": "client_name", "label": "Client Name", "default": "Acme Corp" },
    { "key": "start_date", "label": "Start Date", "type": "date" }
  ]
}

Placeholder substitution:
- Template-creator marks fields as {{placeholder_name}}
- On use: prompt user for values; substitute throughout
- Preserves cloning ergonomics

Implement:
1. Migration for templates + uses + stars tables
2. JSONB validation per resource_type
3. RLS / multi-tenancy
4. Indexes for browse + search
5. Snapshot vs reference design decision documented

Output: schema that supports the operations.

3. Implement clone (Level 1)

Cloning is the simpler operation. Get this right first.

Clone semantics — the hard decisions:

1. New IDs everywhere (don't reuse source IDs)
2. References within the cloned resource: REMAP to new IDs
3. References OUTSIDE the cloned resource: PRESERVE (link to original) or RESET (don't link)
4. Owner / creator: CHANGE to user doing the clone
5. Created/updated timestamps: NEW (clone time, not source time)
6. State that should reset:
   - Status (e.g., done → not done)
   - Assignees (often reset)
   - Comments (often NOT cloned)
   - Activity log (NOT cloned)
   - View counts / metrics (NOT cloned)
7. State that should preserve:
   - Title (often + " (copy)")
   - Description
   - Structure / configuration
   - Custom fields (cloned with empty values, OR with default values, OR with source values)

Implementation pattern:

async function cloneProject(sourceId: string, userId: string, workspaceId: string): Promise<Project> {
  const source = await db.projects.findById(sourceId)
  if (!await canRead(userId, source)) throw new PermissionError()
  
  // Create new project
  const newProject = await db.projects.create({
    workspace_id: workspaceId,
    name: source.name + ' (copy)',
    description: source.description,
    color: source.color,
    created_by: userId,
    status: 'active',  // RESET; don't inherit source status
  })
  
  // Build ID remap table for references within
  const idMap = new Map<string, string>()
  
  // Clone sections (preserving order; new IDs)
  const sourceSections = await db.sections.findByProjectId(sourceId)
  for (const s of sourceSections) {
    const newSection = await db.sections.create({
      project_id: newProject.id,
      name: s.name,
      order: s.order,
    })
    idMap.set(s.id, newSection.id)
  }
  
  // Clone tasks
  const sourceTasks = await db.tasks.findByProjectId(sourceId)
  for (const t of sourceTasks) {
    await db.tasks.create({
      project_id: newProject.id,
      section_id: idMap.get(t.section_id),  // REMAP
      title: t.title,
      description: t.description,
      priority: t.priority,
      // NULLED fields
      assignee_id: null,  // RESET
      status: 'todo',     // RESET
      due_date: null,     // RESET
      // ... handle custom fields, attachments, etc.
    })
  }
  
  // Skip: comments, activity, attachments (with caveats), references, etc.
  
  return newProject
}

Handle nested resources:
- Each nested type has its own clone logic
- Use a clone-strategy pattern (each resource type defines what to copy / reset)

Handle large projects (1000s of tasks):
- Background job for clones > 100 items
- Show progress to user
- Use bulk INSERT for performance

Handle permissions:
- Source resource: read access required to clone
- Target workspace: create access required
- Don't clone if user can't access EVERYTHING in source (e.g., private sections)

Handle attachments / files:
- Decision: clone the underlying file (storage cost) OR reference (cheaper but breaks if source deleted)
- Default: copy files for full independence (most reliable)

Implement:
1. Per-resource clone strategies
2. ID remapping
3. Nullification of state-fields
4. Background job for large clones
5. Permission checks
6. UI: "Duplicate" button + progress feedback

Output: cloning that works for the common case.

4. Implement template creation (Level 2)

Templates are NOT just snapshots. They have placeholders, metadata, and reusability.

Template-creation flow:

1. User opens a project
2. Clicks "Save as Template"
3. Modal:
   - Template name (default: "[Project name] Template")
   - Description (encourage: "When to use this template")
   - Visibility (Private / Workspace / Public if eligible)
   - Category (dropdown)
   - Tags
   - Preview (auto-generated; user can replace)
4. Optional: configure placeholders
   - Tap on a field → "Make this a placeholder"
   - Define placeholder key + label
   - Set default value
5. Confirm + save

What gets stored:

- Snapshot of structure (sections, tasks, fields)
- All TEXT fields scanned for placeholder syntax
- Placeholders extracted to a separate list
- Metadata (name, description, etc.)

Placeholder syntax (recommend Mustache / Handlebars-style):

"{{client_name}} Q1 2026 Project Plan"

In template_data:
{
  "fields": {
    "name": "{{client_name}} Q1 2026 Project Plan",
  },
  "placeholders": [
    { "key": "client_name", "label": "Client Name", "default": "Acme" }
  ]
}

When a user uses the template:

1. User clicks "Use this template"
2. Modal asks for placeholder values
3. Server substitutes placeholders throughout template_data
4. Server creates new resource with substituted data (similar to clone)
5. User lands on new resource

Reset rules (similar to clone):
- Assignees: reset to null OR map to {{template_creator}} = user doing the use
- Dates: reset OR offset relative to creation date
- Statuses: reset to default
- Custom fields: include OR exclude based on template-creator choice

Updating templates:
- Templates can be updated (new version)
- Existing resources created from template are NOT auto-updated
- New uses get the latest version
- Optional: version history; users can pin to specific version

Implement:
1. "Save as template" UI
2. Placeholder definition UX (mark fields; define key + label)
3. Template snapshot creation
4. "Use this template" flow with placeholder prompts
5. Substitution logic (Handlebars or simple regex)
6. Reset rules per resource type
7. Template update / versioning

Output: a template system users can create, share, and use.

5. Build the gallery UI

For Level 2+ (templates), build a gallery so users can browse + use.

Gallery routes:
- /templates — main browse page
- /templates/[id] — template detail page
- /templates/categories/[category] — filtered

Browse page:

Layout:
- Filter sidebar: Category, Tags, Sort by (popular / new / starred)
- Search bar
- Grid of template cards:
  - Preview image
  - Name
  - Description (truncated)
  - Author name + avatar
  - Use count + star count
  - "Use template" button
- Pagination

Detail page:
- Full preview (rendered template structure)
- Author bio
- Description (long form)
- Tags + category
- Use count + stars
- Reviews / comments (if enabled)
- "Use template" CTA
- "Star" button
- Share button (copy link)

For workspace-private templates:
- Workspace-only browse view (under /settings/templates or /templates/workspace)
- Separate from public

For public templates (Level 3):
- Available at /community/templates or /gallery
- Indexed for SEO
- Shareable via link

Permissions:
- Anyone can VIEW public templates
- Only authenticated users can USE
- Only template author + admins can EDIT
- Workspace admins can curate workspace template list

Implement:
1. Browse page with filters + search
2. Detail page
3. Card components
4. Permissions enforcement
5. SEO (for public gallery)
6. Sharing (copy link; per-template URL)

Output: discovery UX that drives template adoption.

6. Operational + abuse handling

Public templates require moderation.

Abuse vectors:
- Spam templates (low-quality; misleading)
- Malicious placeholder values (XSS; injection)
- Copyright violations
- Inappropriate content
- Misleading claims ("get 100K customers in 30 days")

Moderation:

Pre-publication (for public visibility):
- Author flag: "Submit for review"
- Manual review queue (for v1; automate when scale demands)
- Auto-checks: text screening, image moderation
- Approval before publication

Post-publication:
- Report button on every public template
- Reports trigger review
- Quick-remove for clear violations
- Audit log of moderation actions

Author reputation:
- New authors: review-required
- Trusted authors: auto-publish
- Reputation: built from non-flagged templates + community engagement
- Sanctions: reduce reputation on flags; ban on egregious violations

Quality signals:
- Star count
- Use count
- Conversion (use → keep using)
- Review average
- Bounce rate (used and immediately deleted)

Curation:
- Featured templates
- Category leaderboards
- Editor's picks
- Seasonal collections

Attribution + IP:
- Author retains attribution; doesn't forfeit IP
- Workspace customers' DATA isn't in templates (templates are STRUCTURE only)
- Clear ToS that templates are for reuse / sharing

Implement:
1. Reporting + moderation queue
2. Author reputation system
3. Manual moderation UI
4. Auto-checks (XSS, profanity, image)
5. Featured / curated templates
6. Attribution display
7. ToS / publishing agreement

Output: a public gallery that doesn't become a spam wasteland.

7. Edge cases + operational realities

Walk me through:

1. Template references workspace-specific data (e.g., specific user, custom field, integration)
- Template uses placeholder for user (substitute on use)
- Custom fields: prompt user to map source fields to target workspace fields
- Integrations: don't include in template; user must reconnect after use

2. Source resource deleted; templates derived from it
- Templates are independent (snapshot); not affected
- Continue to use templates

3. Template uses a feature that's removed from product
- Mark template as "deprecated"
- Users get warning when trying to use
- Migration path: tell author to update

4. Schema evolves; old templates don't match
- Templates store schema_version
- Migration on use: transform old → new schema
- Or: deprecate old templates beyond N versions

5. Public template later contains private/sensitive info (oversight by author)
- Author can edit + republish
- Old uses NOT affected
- Important: private workspace data should NEVER be in templates (workspace customer data isn't shipped in templates)

6. Use template across workspaces (e.g., agency uses same template for multiple clients)
- "Use template" creates fresh resource in chosen workspace
- Each use gets new IDs; independent

7. Template massive (10,000 tasks); use takes minutes
- Background job for use; show progress
- Email when done

8. Workspace deleted; templates owned by workspace
- Cascade-delete templates (or transfer to admin user)
- Public templates: special handling (often retain or transfer ownership)

9. User publishes template; later wants to remove
- Allow removal
- Existing uses are NOT affected (snapshots)
- Template archived (not deleted; for moderation history)

10. Template marketplace: paid templates
- Stripe integration
- Author revenue share (typical: 70-80% to author; 20-30% to platform)
- Refund policy
- Tax handling

11. Organization has many similar templates
- Template "folders" or categories within workspace
- Search within workspace
- Bulk template operations

12. SEO-driven public gallery
- Per-template URL with metadata
- Sitemap
- Schema markup (e.g., schema.org/SoftwareApplication or HowTo)

For each: code change + UX impact + ops consideration.

Output: operational maturity.

8. Recap

What you've built:

  • Cloning of resources (Level 1)
  • Workspace-private templates (Level 2)
  • Public template gallery (Level 3; if applicable)
  • Placeholder substitution
  • Reset rules for state fields
  • Browse + search + detail UI
  • Permissions + visibility
  • Moderation + reporting
  • Author attribution + reputation
  • Versioning + schema migration
  • Edge cases handled

What you're explicitly NOT shipping in v1:

  • Paid template marketplace (Level 4; defer)
  • Cross-workspace template sharing (private to author / workspace only)
  • Template forking / collaborative editing (defer)
  • Template AI generation (e.g. "generate a template for X") (defer; could be cool)
  • Template-as-API (programmatic use) (defer)

Ship Level 1 in 2 weeks; Level 2 in 4-6 weeks; Level 3 in 12-24 weeks if community demand justifies.

The biggest mistake teams make: shipping public template gallery without moderation infrastructure. Spam templates damage product trust quickly.

The second mistake: not handling references properly. Templates with broken references (missing users, deleted custom fields) frustrate users.

The third mistake: not using placeholders. Templates without placeholders are basically clones; users have to manually edit each instance. Placeholders are the high-value pattern.

See Also