Quote System · Niche files

Niche file guide

A niche is one .json file that describes a quote form: its questions, wording, starter texts and illustrations. This guide explains every part, so you can create a niche, change one, or check one you received.

How it works

Every form has the same shape. First come the niche's own steps (for example "About the Trees"), then an optional photo step, then the shared contact step (name, phone, email, address with map pin, date, time and note), and finally the send buttons.

The niche file only describes its own steps and how things are worded. Saving requests, emails, WhatsApp messages, the quote page, the PDF and the dashboard all work the same for every niche.

Where niche files live. Built-in niches are in packs/<id>/pack.json. Niches imported from the dashboard (Niche library → Import niche) are stored privately in data/niches/<id>.json. An imported niche with the same id as a built-in one replaces it, and that is how updates are installed. Restore original brings the built-in one back.

Quick start

The easiest way to make a niche is to start from an existing one. Go to Niche library, open the ⋯ menu on a similar niche and choose Export file. Change the id, name and ref_prefix, edit the questions, then import it. This is a complete minimal niche:

{
  "format": "rfq-niche",
  "format_version": 1,
  "id": "window-cleaning",
  "version": "1.0.0",
  "requires": "1.2",
  "name": "Window Cleaning",
  "category": "Home improvement",
  "description": "Window cleaning: property type, windows and frequency.",
  "ref_prefix": "WC",
  "icon": "home",
  "steps": [{
    "id": "windows",
    "title": "About Your Windows",
    "nav": "Windows",
    "intro": "A rough idea is enough.",
    "fields": [
      { "name": "property", "label": "Property type", "type": "segment", "required": true,
        "options": { "house": "House", "flat": "Flat", "office": "Office" } },
      { "name": "windows", "label": "Roughly how many windows?", "short": "Windows", "type": "segment", "required": true,
        "options": { "s": "Up to 10", "m": "11–25", "l": "More than 25" } },
      { "name": "frequency", "label": "How often?", "type": "segment",
        "options": { "once": "One-off", "monthly": "Monthly", "quarterly": "Every 3 months" } }
    ]
  }],
  "photos": null,
  "title": "{property} · {windows}",
  "assess": { "windows": { "label": "Size", "levels": { "s": "good", "m": "info", "l": "hot" } }, "@date": [], "@location": [] },
  "defaults": { "hero_title": "Get a {Free Window Cleaning Quote}" }
}

Top-level keys

KeyRequiredWhat it does
format, format_versionyesAlways "rfq-niche" and 1.
idyes2–40 lowercase letters, numbers or dashes, e.g. "roofing". Unique in the library.
nameyesShown in the library and as the default business name.
ref_prefixyes2–3 capital letters for request numbers: RF → RF-261002-AB12.
stepsyes1–6 form steps (see Questions).
versionYour version of the file, e.g. "1.2.0". Shown in the library.
requiresThe oldest quote system version the niche works with, e.g. "1.2". Newer niches are refused by older systems with a clear message.
category, descriptionUsed for the library's filters and cards.
iconOne of: car truck trash skip tree home roof fence grass flower road brush box sofa solar sun zap ruler layers wrench tag clipboard.
photosnull for no photo step, or a photo step (see Photos).
contactChanges to the shared contact step (see Contact step).
titleThe request's title in lists and messages: a template using question names, e.g. "{load_size} · {items}".
specsQuestion names shown in one line under the title.
assess, list_flagsThe quick assessment cards and which of them appear as chips in the request list (see Quick assessment).
summaryRows of the live summary beside the form: [["Label", "icon", ["question", …]], …].
require_any"Answer at least one of these": [{"fields": ["rooms", "paint_area"], "message": "…"}].
status_labelsRename statuses, e.g. {"booked": "Job booked"}. Keys: new contacted offer_sent booked completed lost.
words, defaults, landingsWording, starter texts and extra landing pages (see Texts & wording).
art{"hero": "…", "side": "…"}, SVG shapes for the banner (400×170) and the sidebar picture (320×150).

Questions

Each step has an id (a lowercase word, not photos, contact or submit), a title, a short nav label for the progress bar, an intro line, and fields.

TypeLooks likeNotes
segmentChoice cards, pick oneBest for 2–8 short choices. Needs options.
chipsChoice cards, pick severalSaved as "a,b". Needs options.
selectDropdown with searchFor long lists. "free": true also accepts typed answers.
text, number, email, tel, textareaInput boxesnumber accepts minnum, maxnum, unit, prefix.
dayRow of upcoming datesUsually you only rename the contact step's date.
Field keyWhat it does
nameLowercase letters, numbers and _. Unique, and not one of the contact names (full_name phone email location pickup_date pickup_time notes).
label, shortThe question, and an optional short label used in emails, lists and the quote page.
options{"key": "Label"}. Keys are stored with requests, so keep them stable once a niche is live. Labels can be changed any time. Labels may use {currency}.
requiredtrue / false. Business owners can also change this in Settings → Form fields.
colWidth on a 12-column grid: 12 full, 6 half, 4 third.
help, placeholder, iconA hint under the question, a placeholder, and an icon inside text boxes.
enabledfalse = available in Settings → Form fields but switched off by default.

Modules

Instead of a question, a field can use a ready-made module that adds several linked questions:

ModuleAddsOptions
{"use": "vehicle"}Make, Model (suggestions follow the make) and Year.—
{"use": "route", …}Pickup and drop-off addresses with map pins, the road distance between them, and a date. The contact step's own address and date are removed automatically.from, to, from_short, to_short, date, date_short, time (true/false), from_fields / to_fields (up to 4 questions under each address).
{"use": "measure", …}A length or area, typed in m/ft (m²/ft²), or drawn on a street or satellite map.name, label, kind ("length" or "area"), draw (false = typing only), required, short, help.

Photos

"photos": {
  "title": "Photos of the Roof",
  "intro": "photos of the roof and any damage help us quote accurately.",
  "tip": "Tip: take a photo of the whole roof from the street…",
  "error": "Please add at least one photo of the roof.",
  "slots": {
    "roof":   { "label": "Whole roof",      "art": "<path d=\"…\"/>" },
    "damage": { "label": "Damage close-up", "art": "…" }
  }
}

Up to 6 named tiles, plus "Add more photos". The minimum number of photos is set by the business in Settings. The art outline is drawn on an 80×56 grid.

Contact step

Rename or adjust the shared fields. Allowed changes are label, short, placeholder, help, required, plus "_step": {"title", "intro", "nav"}:

"contact": {
  "_step":       { "intro": "We'll use this to send you our quote." },
  "location":    { "label": "Property Address" },
  "pickup_date": { "label": "Preferred Start Date", "short": "Start date" },
  "notes":       { "placeholder": "e.g. Access through the side gate…" }
}

Quick assessment

The coloured cards at the top of each request, in priority order (the first 6 are shown). Each entry is a question name, or one of the built-in cards @photos, @date, @location and @distance.

KeyWhat it does
labelCard title (default: the question's short label).
levelsAnswer → good (green), info (grey), warn (amber), bad (red) or hot (orange, urgent/valuable). Add "default" for the rest. With several answers, the most serious wins.
textAnswer → wording on the card, e.g. {"road": "Road, permit needed"}.
alsoShow a second answer on the same card: {"from_lift": {"no": "warn"}} → "2nd floor · No lift".
sizesFor measures: {"50": "good", "200": "info", "1000000000": "hot"}, in metres or m².
longFor @distance: kilometres from which the trip is marked hot.

Texts & wording

words

How the system talks about this niche. Keys: customer, customers, offer ("offer" when you pay the customer, "quote" when they pay you), about (e.g. "your {title}"), details, visit (the date's name, e.g. "Delivery"), another, wa_heading, contact_heading, next_steps (list), chat, completed.

defaults

Starter texts loaded when a business chooses the niche. They can then change them in Settings. Keys: business_name tagline hero_title hero_text usps why_title why_points help_title help_text art_text consent_text offer_template legal_text mail_from_name. In hero_title, {curly} words are highlighted. usps is three lines of Title | subtitle.

landings

Extra landing pages with their own banner, for ads or another service name: {"vehicle-transport": {"label": "…", "hero_title": "…", "hero_text": "…"}} → index.php?lp=vehicle-transport.

Import & updates

  1. Niche library → Import niche and choose the file. It is checked first. If something is wrong, you get a list like "step 1 › question 3 (gates): "options" must list the choices…" and nothing is changed.
  2. A new niche appears in the library. Press Preview to try the real form without switching (only you can see a preview, and it can't send requests).
  3. Press Use this niche to switch. Existing requests keep their original questions.
  4. To update a niche, import the new file with Replace ticked. Keep the option keys the same so older requests still read correctly.
The live form is protected. If a niche file ever becomes unreadable, the form shows "coming soon" with your phone number instead of an error. The dashboard and System health say exactly what to fix.

Safety rules