Quote with options
Base scope and optional work priced separately, with tick boxes and two totals side by side.
The tick box is an empty cell with its four borders on: no glyph involved, so it cannot render as tofu in a font that lacks a box character.
Tick boxes
Side-by-side totals
1 page
render_quote_options.rb
ruby
require 'json'
require 'soli/pdf'
template = JSON.parse(File.read('quote_options.template.json'))
data = JSON.parse(File.read('quote_options.data.json'))
pdf = Soli::PDF.render(
template: template,
data: data,
title: 'Quote FK-2025-031'
)
File.binwrite('quote_options.pdf', pdf)
Run it yourself
- Add the gem to your Gemfile — see Installation.
- Download quote_options.template.json and quote_options.data.json.
- Run
ruby render_quote_options.rb.
quote_options.template.json
json
{
"fonts": ["titillium"],
"options": { "header_height": 0 },
"footer": [
{ "type": "paragraph", "value": "${studio.name} · ${studio.email} · Quote ${quote.number} · Page #PAGE# of #TOTAL_PAGE#", "options": { "alignment": "center", "fontSize": 7.5, "color": "7A7290" } }
],
"content": [
{
"type": "table",
"header_columns": [
{
"content": [
{ "type": "text", "value": "${studio.name}", "fontSize": 18, "fontWeight": "bold" },
{ "type": "text", "value": "${studio.tagline}", "fontSize": 9 }
],
"width": 300, "alignment": "left",
"borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" }
},
{
"content": [
{ "type": "text", "value": "QUOTE", "fontSize": 24, "fontWeight": "bold" },
{ "type": "text", "value": "${quote.number}", "fontSize": 10 }
],
"width": 181, "alignment": "right",
"borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" }
}
],
"rows": [],
"options": { "header": { "fillColor": "4C3A8A", "textColor": "FFFFFF" }, "padding_x": 18, "padding_y": 16 }
},
{
"type": "table",
"header_columns": [
{
"text": "${quote.project} · For ${customer.name} · Valid until ${quote.valid_until}",
"width": 481, "fontSize": 9, "fontWeight": "bold", "alignment": "center",
"borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" }
}
],
"rows": [],
"options": { "header": { "fillColor": "F1EEF9", "textColor": "4C3A8A" }, "padding_x": 12, "padding_y": 8 }
},
{ "type": "move", "y": 22 },
{ "type": "paragraph", "value": "BASE SCOPE", "options": { "fontSize": 9, "fontWeight": "bold", "color": "4C3A8A" } },
{ "type": "move", "y": 2 },
{ "type": "paragraph", "value": "Included in the quoted price. No action needed.", "options": { "fontSize": 8.5, "color": "6E6880" } },
{ "type": "move", "y": 8 },
{
"type": "table",
"data": "base_items",
"header_columns": [
{ "text": "DELIVERABLE", "width": 281, "fontSize": 8, "fontWeight": "bold", "alignment": "left", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "4C3A8A" },
{ "text": "QTY", "width": 50, "fontSize": 8, "fontWeight": "bold", "alignment": "center", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "4C3A8A" },
{ "text": "UNIT", "width": 70, "fontSize": 8, "fontWeight": "bold", "alignment": "right", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "4C3A8A" },
{ "text": "AMOUNT", "width": 80, "fontSize": 8, "fontWeight": "bold", "alignment": "right", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "4C3A8A" }
],
"rows": [
[
{ "text": "${name}", "width": 281, "fontSize": 9.5, "alignment": "left", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "E7E3F0" },
{ "text": "${qty}", "width": 50, "fontSize": 9.5, "alignment": "center", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "E7E3F0" },
{ "text": "${unit}", "width": 70, "fontSize": 9.5, "alignment": "right", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "E7E3F0" },
{ "text": "${amount}", "width": 80, "fontSize": 9.5, "alignment": "right", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "E7E3F0" }
]
],
"options": { "padding_x": 6, "padding_y": 6 }
},
{ "type": "move", "y": 6 },
{
"type": "table",
"header_columns": [],
"rows": [
[
{ "text": "Base scope, net", "width": 401, "fontSize": 9.5, "fontWeight": "bold", "alignment": "right", "borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" } },
{ "text": "${totals.base_net}", "width": 80, "fontSize": 9.5, "fontWeight": "bold", "alignment": "right", "borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" } }
]
],
"options": { "padding_x": 6, "padding_y": 4 }
},
{ "type": "move", "y": 24 },
{ "type": "paragraph", "value": "OPTIONS", "options": { "fontSize": 9, "fontWeight": "bold", "color": "4C3A8A" } },
{ "type": "move", "y": 2 },
{ "type": "paragraph", "value": "Tick the options you want and return this page. Each is priced independently and can be added later.", "options": { "fontSize": 8.5, "color": "6E6880" } },
{ "type": "move", "y": 8 },
{
"type": "table",
"data": "options",
"header_columns": [
{ "text": "", "width": 22, "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "4C3A8A" },
{ "text": "OPTION", "width": 259, "fontSize": 8, "fontWeight": "bold", "alignment": "left", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "4C3A8A" },
{ "text": "QTY", "width": 50, "fontSize": 8, "fontWeight": "bold", "alignment": "center", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "4C3A8A" },
{ "text": "UNIT", "width": 70, "fontSize": 8, "fontWeight": "bold", "alignment": "right", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "4C3A8A" },
{ "text": "AMOUNT", "width": 80, "fontSize": 8, "fontWeight": "bold", "alignment": "right", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "4C3A8A" }
],
"rows": [
[
{ "text": "", "width": 22, "borderSides": { "top": "true", "left": "true", "right": "true", "bottom": "true" }, "borderColor": "4C3A8A", "valign": "middle" },
{ "text": "${name}", "width": 259, "fontSize": 9.5, "alignment": "left", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "false" } },
{ "text": "${qty}", "width": 50, "fontSize": 9.5, "alignment": "center", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "false" } },
{ "text": "${unit}", "width": 70, "fontSize": 9.5, "alignment": "right", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "false" } },
{ "text": "${amount}","width": 80, "fontSize": 9.5, "alignment": "right", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "false" } }
]
],
"options": { "header": { "fillColor": "F1EEF9", "textColor": "4C3A8A" }, "padding_x": 6, "padding_y": 7 }
},
{ "type": "move", "y": 6 },
{
"type": "table",
"header_columns": [],
"rows": [
[
{ "text": "All options, net", "width": 401, "fontSize": 9.5, "fontWeight": "bold", "alignment": "right", "borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" } },
{ "text": "${totals.options_net}", "width": 80, "fontSize": 9.5, "fontWeight": "bold", "alignment": "right", "borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" } }
]
],
"options": { "padding_x": 6, "padding_y": 4 }
},
{ "type": "move", "y": 26 },
{ "type": "rect", "width": 235, "height": 74, "fill": "F4F3F7" },
{ "type": "move", "x": 246, "y": 0 },
{ "type": "rect", "width": 235, "height": 74, "fill": "4C3A8A" },
{ "type": "move", "x": -232, "y": 14 },
{ "type": "paragraph", "spans": [ { "text": "BASE SCOPE ONLY", "fontWeight": "bold", "color": "6E6880" } ], "options": { "fontSize": 8 } },
{ "type": "paragraph", "spans": [ { "text": "${totals.base_gross}", "fontWeight": "bold", "color": "2A2438" } ], "options": { "fontSize": 20 } },
{ "type": "paragraph", "spans": [ { "text": "incl. VAT ${quote.vat_rate} · ${totals.base_vat}", "color": "6E6880" } ], "options": { "fontSize": 8 } },
{ "type": "move", "x": 246, "y": -44 },
{ "type": "paragraph", "spans": [ { "text": "WITH ALL OPTIONS", "fontWeight": "bold", "color": "FFFFFF" } ], "options": { "fontSize": 8 } },
{ "type": "paragraph", "spans": [ { "text": "${totals.all_gross}", "fontWeight": "bold", "color": "FFFFFF" } ], "options": { "fontSize": 20 } },
{ "type": "paragraph", "spans": [ { "text": "incl. VAT ${quote.vat_rate} · ${totals.all_vat}", "color": "D9D0F0" } ], "options": { "fontSize": 8 } },
{ "type": "move", "x": -260, "y": 36 },
{ "type": "paragraph", "value": "${quote.note}", "options": { "fontSize": 8, "color": "7A7290" } }
]
}
quote_options.data.json
json
{
"data": {
"studio": {
"name": "Fjord & Kessler",
"tagline": "Brand and packaging design",
"email": "studio@fjordkessler.at"
},
"customer": {
"name": "Ovenhaus Bakery, Vienna"
},
"quote": {
"number": "FK-2025-031",
"project": "Brand relaunch",
"valid_until": "15 Jan 2026",
"vat_rate": "20%",
"note": "Options may be added at any point during the project at the prices shown. Prices hold for 60 days from the issue date; after that they are re-quoted at the then-current rates."
},
"base_items": [
{ "name": "Brand identity system", "qty": "1", "unit": "3,200.00", "amount": "3,200.00" },
{ "name": "Packaging design, three SKUs", "qty": "3", "unit": "480.00", "amount": "1,440.00" },
{ "name": "Brand guidelines document", "qty": "1", "unit": "900.00", "amount": "900.00" }
],
"options": [
{ "name": "Motion identity package", "qty": "1", "unit": "1,200.00", "amount": "1,200.00" },
{ "name": "Photography art direction", "qty": "1 day", "unit": "750.00", "amount": "750.00" },
{ "name": "Storefront signage design", "qty": "1", "unit": "640.00", "amount": "640.00" }
],
"totals": {
"base_net": "€5,540.00",
"options_net": "€2,590.00",
"base_vat": "€1,108.00",
"base_gross": "€6,648.00",
"all_vat": "€1,626.00",
"all_gross": "€9,756.00"
}
}
}
More in Business documents