All docs

Blueprints

Ready-made setups, installed in one transaction

A blueprint is a kind of business expressed as software — its records, automatic tasks, reports, and navigation — packaged so you can install the whole thing into an organization and customise from there.

What a blueprint is

Modelling a business from scratch is real work: every data model, every automatic task, every report and sidebar entry. A blueprint skips the blank page. Each one is a self-contained, versioned package that describes a vertical — a CRM, an order book, a hotel — and installs into one organization as a single, reversible operation.

Blueprints ship bundled with every polimorf install; there are 31 built-in verticals covering commerce, sales, marketing, operations, hospitality, people, and support. Browse them in the catalog. A blueprint is a starting point: once installed, its schemas, workflows, and widgets are ordinary org resources you own and edit — there is no lock-in to the blueprint after the fact.

Definition over disk, not a running service

Each built-in blueprint is a single manifest.yaml — pure data. Installing it stamps real rows into your organization; it does not deploy code or run a background service.

The manifest

Everything a blueprint declares lives in one YAML manifest, parsed into a strict schema with no side effects. The top-level fields are:

FieldPurpose
slugUnique lowercase identifier (alphanumeric, - and _).
versionManifest version string, carried onto each install.
display_nameHuman label shown in the catalog and sidebar group.
descriptionShort summary shown on the catalog card.
iconLucide icon name for the catalog and navigation.
schemasData models to create — fields, traits, layout, list columns.
bindingsNamed hooks the installer wires to an existing schema you choose.
providesConcept names this blueprint owns, for auto-recommendation.
depends_onHard prerequisites installed first, in topological order.
recommendsCompanion suggestions — informational, never a dependency.
routesCustom Vue views, admin or client side, optionally in the nav.
widgetsDashboard widget presets resolving to built-in platform widgets.
workflowsAutomatic tasks, stamped enabled or disabled per the manifest.
settings_schemaFree-form config the install dialog collects.

A manifest that fails validation is simply marked invalid and skipped at boot — a malformed blueprint never blocks the platform or any other blueprint. Here is a trimmed real manifest:

leads/manifest.yaml
slug: leads
version: 0.1.0
display_name: CRM / Leads
description: Capture inbound leads and walk them through a configurable funnel.
icon: lucide:filter

schemas:
  - slug: lead
    display_name: Lead
    storage_mode: jsonb
    traits: [timestamped, soft_delete]
    fields:
      - {slug: name,  display_name: Name,  field_type: string}
      - {slug: email, display_name: Email, field_type: string}
      - {slug: stage, display_name: Stage, field_type: string, config: {default: new}}
      - {slug: score, display_name: Score, field_type: integer, optional: true}

# Map a name to a real schema at install. Optional here, so a lead can
# stay self-contained until you bind it to a customer profile later.
bindings:
  customer: {description: Promote qualified leads, access: write, required: false}

# Concepts this blueprint owns; powers auto-recommendation of providers.
provides: [lead]

# A companion suggestion — informational, never an install-time dependency.
recommends:
  - {slug: customers, reason: Promote leads into profiles, kind: binding_provider}

workflows:
  - slug: thank_you_on_new_lead
    name: Send thank-you email on new lead
    trigger_event: entry.created
    conditions: {schema: lead}
    enabled: false
    optional: true
    requires_schemas: [lead]
    steps:
      - {action: send_email, to: '{{ trigger.entry.data.email }}', subject: Thanks}

What it installs

Installing stamps each declared resource into the target organization and records the created ids so an uninstall can reverse exactly what it added. Concretely a blueprint can bring:

  • Schemas — data models with typed fields, traits (e.g. timestamped, soft_delete), a storage mode (jsonb or promoted), an optional form layout, list columns, and a display field. See the schema designer.
  • Workflows — automatic tasks keyed to a trigger_event (such as entry.created) with conditions and steps. They are stamped enabled or disabled as the manifest declares, so most ship off until you flip them on. See workflows.
  • Dashboard widgets — presets, not bespoke components. Each resolves to a built-in platform widget with prefilled props, so the dashboard renderer never needs blueprint-specific code.
  • Navigation — the installed schemas get sidebar entries in the client workspace. Two or more schemas are grouped under a collapsible section named after the blueprint; a single schema lands as a top-level item.
  • Routes — custom views that resolve to registered Vue components, on the admin or client side. Built-in /blueprint/* routes are developer-only, so they do not appear in the client navigation.

Each stamped row is tagged with the blueprint's slug, so leftovers from an aborted install are swept automatically before a retry — you never get wedged on a stale slug collision.

Bindings and concepts

A blueprint rarely lives alone. A binding is a named hook the installer wires to an existing schema you nominate. The leads blueprint declares a customer binding: leave it unset and leads stay self-contained with inline contact details; point it at your customer schema and qualified leads can be promoted into full profiles. Each binding has an access of read or write and may be required or optional — required bindings must be supplied or the install is rejected before anything is stamped.

Bindings match by concept. A blueprint lists the concepts it owns in provides; a consumer's binding name must equal that concept name exactly for the recommendation engine to auto-match a provider. One concept is owned by exactly one blueprint, and two blueprints must never bind each other's concepts — that would form an install cycle, which the registry warns about at boot.

Recommendations are not dependencies

A recommends entry — or an inferred provider for one of your bindings — is a UI hint surfaced on the install dialog. It never forces an install and never enters the install order. Only depends_on does that.

Dependencies and the chain installer

A blueprint can declare hard prerequisites in depends_on — for example the hotel, bookings, events, and finance blueprints each depend on locations. When you install a root, the chain installer resolves its full transitive closure and orders it with a three-colour depth-first search: every dependency lands before any consumer (leaves first, root last). Cycles and missing dependencies are detected up front and reported, not discovered mid-install.

Members already present in the organization are kept and reused, not re-stamped — the resolver surfaces them separately so the install dialog can show "these dependencies are already installed". The whole chain installs in topological order:

bash
# Resolve the full install chain first (topological, leaves before root).
# Shows which dependencies will be pulled in and which are already present.
curl https://api.polimorf.com/admin/v1/blueprints/hotel/install-chain \
  -H 'Authorization: Bearer <access_token>'

# Install the root plus every transitive depends_on in one call.
# per_blueprint is sparse — members with no entry install with defaults.
curl -X POST https://api.polimorf.com/admin/v1/blueprints/hotel/install-chain \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "per_blueprint": {
      "hotel": {
        "bindings": {"customer": "guests"},
        "selection": {
          "schemas": {"cleaning_status": {"included": false}},
          "workflows": {"send_arrival_summary": false}
        }
      }
    }
  }'

Rollback scope

A single blueprint install is atomic: if stamping fails, every row it added is reversed and the organization returns to its prior state. A chain install rolls back only the blueprints this call stamped, in reverse order (consumers before providers). Dependencies that were already installed beforehand are deliberately left in place — other consumers may rely on them — so a failed chain install is reported as "requires manual review", not fully reversible.

Uninstall is guarded the same way: the platform refuses to remove a blueprint that other installed blueprints still depend on, and tells you which ones to remove first.

Customise on install

You do not have to take a blueprint whole. Resources the manifest marks optional can be opted out of at install time; required ones — each carrying a required_reason the install dialog shows — always stay. Your selection covers four kinds of resource:

Selection keyControls
schemasDrop optional schemas, or individual optional fields within a schema.
workflowsSkip optional workflows you do not want stamped.
widgetsExclude optional dashboard widget presets.
routesExclude optional custom routes.

The installer keeps the selection honest: if you drop a schema that a kept workflow references through requires_schemas, an optional workflow is skipped automatically, and a required one blocks the install with a clear message rather than stamping an orphan trigger. Your exact picks are stored on the install so the platform always knows what it added.

Sample data

Built-in blueprints ship field definitions only — no fixture rows — because hardcoding data into every manifest would bloat the package and rot. Instead a procedural generator inspects a schema's field types, slugs, and config hints (enum options, numeric min/max, currency codes) and emits plausible preview rows. Output is read-only and never touches the organization database — the seed lives in the request, so the same organization, blueprint, and schema always yield the same preview while two different organizations see slightly different snapshots.

Preview rows match the content list endpoint's shape, so the very same renderers display real and sampled data identically. Request count is clamped to 1–50.

The public catalog

The catalog of installable blueprints is exposed anonymously — no organization context, no auth — at GET /api/v1/public/blueprints. It returns only browsing metadata: slug, display name, description, icon, a derived category, and schema / workflow / widget counts. It deliberately never exposes settings, bindings, or manifest internals; those live behind the developer-authenticated /admin/v1/blueprints/catalog endpoint.

GET /api/v1/public/blueprints
GET /api/v1/public/blueprints

{
  "items": [
    {
      "slug": "leads",
      "display_name": "CRM / Leads",
      "description": "Capture inbound leads and walk them through a funnel.",
      "icon": "lucide:filter",
      "category": "sales",
      "schemas": 1,
      "workflows": 2,
      "widgets": 1,
      "deprecated": false
    }
  ],
  "total": 31
}

This is what powers the marketing catalog page. From the build console, the developer endpoints add an install plan (the annotated, opt-in / opt-out resource tree), the resolved install chain, recommendations, and the procedural sample preview per schema.

Where to next

  • Getting started — install your first blueprint and hand a client a clean workspace.
  • Schema designer — the field types and traits a blueprint's schemas are built from.
  • Workflows — the automatic tasks blueprints ship, and how to write your own.