Documentation menu

Author a portable estimator template

PRODUCT / 0.2.0-alpha.1WEBSITE HANDBOOK · IMPLEMENTATION-CHECKED
On this page

A template author needs pricing and form knowledge, not database access. An .oqs.json file describes a portable estimator; importing it creates an application identity and draft. This guide builds a small room-cleaning example you can download and validate.

Start with one complete document

Download room-cleaning-example.oqs.json. It uses USD, one quantity field, a base price and a per-room rate:

Examplejson
{
  "schemaVersion": "1",
  "template": {
    "id": "room-cleaning-example",
    "name": "Room cleaning example",
    "category": "Home services",
    "version": "1.0.0"
  },
  "estimator": {
    "id": "room-cleaning-example",
    "name": "Estimate a room clean",
    "locale": "en",
    "currency": { "code": "USD", "minorUnits": 2 },
    "steps": [
      {
        "id": "home",
        "title": "Your home",
        "fields": [
          {
            "id": "rooms",
            "label": "Rooms to clean",
            "type": "quantity",
            "required": true,
            "validation": { "min": 1, "max": 20, "integer": true }
          }
        ]
      }
    ],
    "rules": [
      {
        "id": "base",
        "label": "Visit and supplies",
        "type": "fixed",
        "amountMinor": 5000
      },
      {
        "id": "rooms",
        "label": "Room cleaning",
        "type": "per_unit",
        "field": "rooms",
        "rateMinor": 2000
      }
    ],
    "leadCapture": { "mode": "disabled", "fields": [] },
    "output": { "message": "Example prices. Confirm the scope before booking." }
  }
}

Three rooms produce 11000, or $110. The example collects no contact. It is a learning document, not an additional official industry template or a suggested market price.

Validate and calculate from source packages

Build the Engine and Schema in the OpenQuoteStack monorepo or use their locally packed output. These packages do not require the web application or database:

Examplets
import { readFile } from "node:fs/promises";
import { parseDocument } from "@openquotestack/schema";
import { calculateEstimate } from "@openquotestack/engine";

const input = JSON.parse(
  await readFile("room-cleaning-example.oqs.json", "utf8"),
);
const document = parseDocument(input);
const result = calculateEstimate(document.estimator, { rooms: 3 });
console.log(result.totalMinor); // 11000

parseDocument validates the wrapper, budgets and references. parseEstimator is available when you want only the normalized estimator. Do not replace runtime validation with a TypeScript cast.

Make identifiers deliberate

Choose stable IDs for the template, estimator, steps, fields, choices and rules. They must satisfy Schema identifier rules and be unique in their respective collections. Choice IDs are answer values; labels are presentation.

Template version describes the template's own evolution. schemaVersion identifies the portable structure. Product/package compatibility remains relevant because strict older readers may reject additions within version 1.

Add complexity in small increments

Add a bathroom quantity and its per-unit price, validate, then calculate known cases. Add a deep-clean boolean and percentage only after the basic total is correct. Use the percentage guide to choose its base and position.

For every visibility branch, test both outcomes. For every price rule, include a case where it applies and one where it does not. Test minimum, maximum and fractional rounding where relevant.

Import and inspect the customer experience

Import the file through the organization interface. A portable name/ID collision does not overwrite an existing calculator; import creates a new identity.

Preview the draft in desktop and mobile width. Review labels, units, required fields, focus order, validation, explanations and terms. A valid Schema file can still describe a confusing customer experience.

Export the imported draft and compare the semantics, accounting for normalized defaults and the application's new identity. Customer records and integration secrets are not part of the portable document.

Prepare a contribution

Explain intended use, example units/rates, pricing concepts and tested cases. Include English and Brazilian Portuguese content when possible. Use image URLs only when stable, appropriate and licensed for the template's use.

Keep customer information, API keys, webhook secrets and external executable code out of the file. Follow the template reference and contribution guide when submitting a community template.