Skip to content
New: Customize your theme with an AI assistant. Read the guide

The Job Ticket

Files: the ticket: blocks in your content files, src/sections.schema.ts (sharedTicket) · Skill level: Beginner

The summary ticket beside the booking form

The job ticket is Homio’s signature card: a white receipt with a mono number in the header, rows with small square marks, a punched tear line, and a total at the bottom. It shows prices, checklists, and short facts across the site. Some tickets are filled in by the theme (the estimator, the booking summary); others you write in a ticket: block in a content file.

Where Tickets Appear

Computed by the theme. You don’t type their rows or totals; they come from the pricing file and the service, area, or project files:

TicketWhereWhat sets it
The estimator/pricing/, cleaning service pages, default service pagesThe rate cards. number in estimateSection replaces the computed code
“Your ticket” beside the booking form/book/The rate cards. summaryTitle in booking-section.md
The service ticket in the heroService pagesThe service file and its rate card. ticket.rows in service-hero-section.md sets how many task rows show
The “Not covered” ticketRepair service pagesnotIncluded in the service file; ticketLabel and footnote in not-covered-section.md
The area ticketArea pagesThe area file (ZIP codes, crews, phone, hours) and the first rate card
The job ticket of a projectProject pages, recent-job blocksThe project file (ticket, crewSize, duration, scope, price)

The estimate code in the header (for example EST-4K7Q2) is built from the visitor’s selection, so the booking form shows the same code the visitor saw in the estimator, and you receive it with the request. Change the EST prefix with ticketPrefix in [settings.estimator] (src/config/config.toml).

Written by you in a ticket: block:

TicketFile
Page header, split layoutpageHeader.ticket in a page file, for example src/content/guarantee/english/-index.md, src/content/careers/english/-index.md, src/content/pages/english/gift-cards.md
Call to action, split layoutticket in src/content/sections/english/call-to-action.md
404 pageticket in src/content/sections/english/not-found-section.md
Booking thank-you pageticket in src/content/pages/english/book-thanks.md
Policy summarycontentPage.summary in src/content/pages/english/cancellation-policy.md and terms-conditions.md (add one to any page that has a contentPage block)
Industry site ticketticket: (a list of rows) in src/content/industries/english/<industry>.md
In a blog postThe <JobTicket> component (see below)

Ticket Fields

Every written ticket uses the same fields (sharedTicket in src/sections.schema.ts):

ticket:
number: "2041" # "2041" → "No. 2041"
label: "Standard clean" # header right: frequency, date, or service
title: "Standard clean · 2 bed, 1 bath"
meta: # optional label/value pairs under the title
- { label: "Crew", value: "2" }
rows:
- { type: "check", label: "Same crew every visit" }
- { type: "line", label: "Late cancellation", value: 40 }
total:
label: "To pay"
value: 0 # a number is money; a string is shown as written ("On quote")
unit: "per visit"
footnote: "Sample values. Set your own."
FieldWhat it does
numberThe mono number in the header. Digits show as “No. 2041”. In page headers, a number with letters shows as written (“GUARANTEE”)
labelShort text on the right of the header
titleThe ticket heading
metaOptional label/value pairs under the title
rowsThe rows (see the row types below)
totalThe bottom line: label, value, and an optional unit. A number counts up and is formatted as money
footnoteA small line at the bottom

Row Types

Each row has a label (inline Markdown is allowed), an optional detail (a second, muted line), an optional value, and a type:

typeShowsValue
checkA ticked row: included. The default when type is left outOptional
extraA plus row: an add-onA number shows as ”+$35”
excludedA dashed row: not coveredEmpty shows “not covered”
lineA plain label and valueText or a number
discountA discount lineA number shows as a negative amount
noteA plain noteOptional

Money or text. A number value is money: it is formatted per language with the currency in [settings.estimator] (40 shows “$40” in English and “40 $US” in French). A string is shown exactly as written ("up to 24 h before", "$0"). Use a string when the value is not an amount, or to control the exact text.

key is a stable id that some tickets use to fill a row in. For example, on the careers page a row with key: "pay-range" and an empty value shows the pay range of your open roles, and on the 404 page the row with key: "requested" shows the address the visitor asked for.

A Computed Total In The Call To Action

The call to action’s split layout can price its ticket from the rate cards instead of a typed total:

ticket:
title: "Standard clean · 2 bed, 1 bath"
rows:
- { type: "check", label: "Same crew every visit" } # sample promise
# The total is computed from the rate card, as in the estimator (sample rates give $115 per
# visit). Remove `quote` and set `total: { label, value, unit }` to type it instead.
quote:
service: "standard-cleaning" # rate-card id from src/content/pricing/
home: { bedrooms: 2, bathrooms: 1 }
frequency: "biweekly" # frequency id from the pricing file; empty = the card's default

Prefer quote wherever you show a price: it follows your rates. A typed total does not.

In A Blog Post

In an .mdx post or page, <JobTicket> turns a Markdown list into a ticket. Each list item becomes a check row:

<JobTicket title="What our move-out clean covers" code="TIP-014" label="Move-out" service="move-out-cleaning">
- Oven, hob, and extractor filters degreased
- Inside every cabinet and drawer
</JobTicket>
  • code is the ticket number and label the header text.
  • service (a rate-card id) adds that service’s “from” price as the total and a “Get a price” button to /book/?service=….
  • total replaces the price with your own text (“From $220”). footnote adds a small line.

Leave a blank line after the opening tag and before the closing tag, or the list is not read. More examples are on the /components/ page (src/content/pages/english/components.mdx).

/elements/ shows a ticket in every size and color on one page, with a working demo.

Do It With AI

Update the ticket in the page header of src/content/guarantee/english/-index.md: number
"[TEXT]", label "[TEXT]", rows [ROWS], total "[TEXT]". Use the row types check, line, and
excluded from sharedTicket in src/sections.schema.ts. Write money as a number unless it needs
special text. Do the French file too.
Find every `ticket:` block and `contentPage.summary` in src/content (English and French) that
shows a fee or price as typed text or a number, list them with their file, and update them to
match my prices: [FEES AND PRICES].
Type something to search...