Freeframe

Documentation

Brew

v1.0.1Updated Oct 22, 2026A bold, hand-printed website for a craft brewery and taproom, with a live tap board, cans to go and tour booking.

Overview#

Brew is a complete website for a craft brewery, taproom or brewpub, shown as Cinderjack Brewing Co., a fictional independent brewery with a taproom and beer garden on NE Hawthorne Avenue in Bend, Oregon (US). It has a live "on tap now" board with an open-now status in Pacific time, fifteen beers with filters, an ABV/IBU map and SVG flavor charts, opening hours that work out every US federal holiday for any year, a food truck rotation, a dated events calendar, cans and merch to go with a pickup slot picker and a 21+ confirmation, brewery tour booking with live capacity, and a private events inquiry. The look is a hand-printed can label: ochre, juniper green and rust on cream, halftone dots, thick ink outlines with offset "misprint" shadows, mountain-ridge dividers, Alfa Slab One headings and a hand-drawn SVG label for every beer. This is the HTML + Tailwind CSS v4 version (1.0.1): plain HTML files, one stylesheet and two vanilla JavaScript files, with no build step needed to run it.

Nothing on the site goes out of date: the open status, tap board, food trucks, holiday hours, pickup slots, tour dates and the copyright year are worked out from today's date in Pacific time, and the events move forward while KEEP_DEMO_CURRENT is on (see Keeping the events current).

Live demo: freeframe.dev/templates/brew

Quick start#

  1. Unzip the download.
  2. Open index.html in a browser. Every page works from the file system; links are relative.
  3. To preview it the way a host would serve it, run any static server in the folder, for example:
sh
npx serve .

Requirements: none to run it. To rebuild the CSS after editing src/input.css or adding Tailwind classes you need Node.js 24 (see Building and deploying).

Pages#

File Purpose Notable sections and features
index.html Home Hero with open-now status, today's hours and today's food truck; live tap board (first 8 taps); three year-round beers; can shelf with prices; next three events; tours and private events; story and beer garden drawing
beers.html Beers Style, strength and "pouring now" filters; 15 beer cards with can art; ABV/IBU map; tasting-notes dialog with a flavor radar chart
taproom.html Taproom & menu Beer garden drawing; full tap board (12 taps); pour menu; flight builder; hours table; next five holiday hours; house rules; seven-day food truck schedule; snacks
events.html Events Next-up card with a countdown; type filters with counts; events grouped by month in date order; the regulars; tickets contact
shop.html Shop 15 products (beer and merch) with options and limits; cart panel with quantities, deposit and total; good-to-know notes
checkout.html Pickup order Pickup day and 30-minute slot picker; name, email and mobile; 21+ confirmation when the order has beer; order summary; confirmation with a reference
tours.html Tours Brewhouse cutaway drawing; tour choice, date and time with places left, party size, details; summary panel; saved bookings with cancel
visit.html About & visit Map drawing; story and timeline; six crew members with portraits; directions; hours and coming-up holiday hours
contact.html Private events & contact Three spaces; inquiry form with live capacity and minimum spend; contact details; confirmation with a reference
404.html Not found Links back to the main pages

Project structure#

brew/
  index.html … contact.html, 404.html   the pages (header and footer repeated in each)
  assets/
    css/style.css        compiled Tailwind CSS (generated by npm run build, committed)
    js/data.js           all the business data: hours, holidays, beers, events, products, tours, spaces
    js/main.js           all behavior: status, tap board, art, filters, cart, checkout, tours, forms
    img/favicon.svg      the cinder-cone-and-jackrabbit logo mark
    img/og-image.svg     source of the social sharing image
    img/og-image.png     1200 × 630 social image used by og:image
  src/input.css          Tailwind source: @theme tokens and a small @layer components
  package.json           npm scripts to rebuild the CSS
  README.md              short introduction
  DOCS.md                this guide
  CHANGELOG.md           version history
  LICENSE.txt            MIT license (in the download)

data.js must load before main.js; every page includes both at the end of <body>:

html
<script src="assets/js/data.js"></script>
<script src="assets/js/main.js"></script>

Customizing#

Brand and colors#

The design tokens live in the @theme block of src/input.css. Each becomes Tailwind utilities (bg-ochre, text-rust, border-ink and so on).

Token Value Used for
--color-cream #f5ead3 Page background
--color-paper #fbf5e8 Cards and fields
--color-sand #ead9b5 Alternate sections (with the halftone utility)
--color-ink #241a13 Text, outlines and offset shadows
--color-muted #5f4c3a Secondary text on cream, paper and sand
--color-ochre / --color-ochre-soft #e0a133 / #f3d692 Fills, buttons, date blocks; ochre is text only on dark
--color-rust #983a19 Accent text on light backgrounds
--color-rust-bright #f08a5d Accent text on dark sections
--color-pine / --color-pine-deep #24493f / #16302a Juniper green; dark sections, tap board and footer
--color-sage #c9d4c4 Secondary text on dark

Change a color in one place and rebuild:

css
@theme {
  --color-ochre: #d98e2b;
}

Keep the contrast pairs above: ochre and rust-bright are for dark backgrounds or fills with ink text, rust and muted for light ones. The printed look comes from four small utilities in src/input.css: halftone (dot screen), sunburst (rays behind the cans), print-shadow and print-shadow-sm (the offset ink shadow).

Typography#

Two Google Fonts, loaded with one <link> in the <head> of every page:

html
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Alfa+Slab+One&amp;family=Golos+Text:wght@400..800&amp;display=swap">
  • Alfa Slab One (font-display): headings, prices, tap numbers and the text on the can labels.
  • Golos Text (font-sans): body text, buttons and labels.

To swap a font, change the <link> on every page and the family in --font-display or --font-sans in src/input.css, then rebuild. The SVG can labels in main.js and og-image.svg name the families directly (font-family="Alfa Slab One, …"), so update them too.

Content#

Page text is in the HTML files. Everything the pages compute from lives in assets/js/data.js, returned as window.BREW_DATA:

Constant What it holds
BREW Name, time zone (America/Los_Angeles), locale, currency, phone numbers, email, address
HOURS Regular hours per weekday, Sunday first, as ['HH:MM', 'HH:MM'] or null for closed
LAST_CALL_MINUTES When "Last call" shows before closing (30)
HOLIDAY_HOURS What the taproom does on each federal holiday: null closed, hours, or 'regular', plus a note
EXTRA_HOURS Special days every year by "MM-DD" (Christmas Eve, New Year's Eve)
STYLE_GROUPS, STRENGTHS Beer filters: four style groups and three ABV bands
FLAVOR_AXES The six axes of the flavor chart
BEERS The 15 beers (see below)
SEASONAL_TAP The tap that Rimfire and Tumbleweed take turns on, each from its release event (see Tap board)
LIQUID The color of each beer in the glass (keg bars and the flight paddle)
POURS, STRONG_ABV Pour sizes and prices; beers over STRONG_ABV are poured 10 oz only
TRUCKS, TRUCK_ROTA Food trucks and which trucks take turns on each weekday
SNACKS The taproom counter menu
EVENT_TYPES, EVENTS Event categories and the 32 dated events (11 in the regular program, 21 seasonal)
PRODUCTS, DEPOSIT, PICKUP Shop items, Oregon's 10¢ container deposit and pickup slot settings
TOURS, TOUR_BOOK_AHEAD_DAYS, TOUR_MAX_GROUP The two tours, how far ahead they can be booked, the largest group
SPACES, HIRE_EVENT_TYPES, HIRE_MIN_DAYS_AHEAD Event spaces, the event type list and the notice needed
KEEP_DEMO_CURRENT, DEMO_ANCHOR Keep the dated events ahead of today (see below)

Add a beer by appending an object to BEERS:

js
{
  id: 'hop-harvest', name: 'Hop Harvest', style: 'Fresh Hop Pale', group: 'hoppy', abv: 5.8, ibu: 45,
  tap: null, cans: false, tapped: null, motif: 'pine', colors: ['#cfe0c3', '#983a19', '#241a13'],
  tagline: 'Hops picked in the morning, in the kettle by lunch.',
  notes: 'Wet Centennial straight from the farm…',
  hops: 'Centennial (fresh)', pairing: 'Fish tacos',
  flavor: { bitter: 3, malt: 2, roast: 0, body: 2, tart: 0, fruit: 3 }
}
  • id is used in URLs (beers.html?beer=hop-harvest) and must be unique; add its glass color to LIQUID.
  • group must be a key of STYLE_GROUPS; the strength band is worked out from abv.
  • tap is the tap number on the board (null when it isn't pouring); tapped is how many days ago the keg went on (3 or fewer shows "Just tapped"). Beers listed in SEASONAL_TAP get both from their release events instead.
  • motif picks the label drawing from MOTIFS in main.js (cone, whirl, hare, rim, pine, mesa, flake, tumble, tower, ridges, stones, cave, sprig, cactus, berry); colors is [label, band, ink].
  • To sell it to go, add a product with beer: '<id>' to PRODUCTS.

The hero copy, the three "year-round" cards and the can shelf on index.html are written in the HTML (the cans and shelf prices are filled from the data through data-can="<beer id>" and data-product-price="<product id>"), as are the style filter buttons on beers.html (their counts are recalculated).

Images and artwork#

All artwork is SVG; there are no photos to license.

  • Can labels are drawn by canSvg(beer) in main.js from each beer's motif, colors, name and ABV (viewBox 120 × 200). Long names wrap onto two lines.
  • Merch drawings (MERCH_ART: tee, cap, glass, growler, pin, stickers, crowler; viewBox 160 × 200).
  • Flavor radar (radarSvg), ABV/IBU map (drawn in the beers section of main.js), flight paddle and event type icons (EVENT_ICONS) are generated from the data.
  • Scenes written inline in the pages: the beer garden (taproom.html, index.html), the brewhouse cutaway (tours.html), the neighborhood map (visit.html) and six crew portraits (visit.html).

To use product photos instead, replace the productArt(p, …) call in the shop grid with an <img> in a 4:5 box (the art area is h-52). Keep the 1200 × 630 size for the social image: edit assets/img/og-image.svg, then render the PNG (from the Freeframe repository, node scripts/og-png.mjs assets/img/og-image.svg assets/img/og-image.png index.html, or export it from any vector editor). The favicon is assets/img/favicon.svg.

The header and footer are repeated in every HTML file. To add a page, copy an existing one, change its <title>, description and Open Graph tags, and add a link to the <nav aria-label="Main"> list, the mobile menu (#mobile-menu) and the footer of every page. Mark the current page's links with aria-current="page".

The top bar shows the open status (data-status), today's truck (data-truck-today) and the phone number. The "Order" button links to checkout.html and shows the cart count (data-cart-count).

Features#

Open status and hours#

Every element with data-status gets a data-state of open, lastcall or closed and its data-status-text child is filled: "Open now · until 10pm", "Last call · closing at 10pm" or "Opens tomorrow at 11am" (never a bare "Closed"; on a holiday it reads "Thanksgiving · Opens Friday at 12pm"). Add data-status-short for the compact version. data-today-hours shows today's hours, tbody[data-hours-table] is filled from HOURS with today's row highlighted, and ul[data-holidays="5"] lists the next five days with changed hours.

The code is taproomStatus(), dayInfo() and paintStatus() in main.js; they use the taproom's wall clock in BREW.timeZone via Intl.DateTimeFormat, whatever the visitor's time zone, and refresh every minute.

Federal holidays#

federalHolidays(year) works out the eleven US federal holidays for any year by rule: fixed dates (New Year's Day, Juneteenth, Independence Day, Veterans Day, Christmas Day) and nth-weekday rules (Martin Luther King Jr. Day, Presidents' Day, Memorial Day, Labor Day, Indigenous Peoples' Day, Thanksgiving). The taproom keeps holiday hours on the actual date, not the federal "observed" weekday. HOLIDAY_HOURS says what happens on each; EXTRA_HOURS adds days that aren't federal holidays:

js
const EXTRA_HOURS = {
  '12-24': { name: 'Christmas Eve', hours: ['11:00', '16:00'], note: 'Closing at 4pm.' }
};

Closed days are skipped by the pickup slots, tour dates and events, and shown in the food truck schedule.

Tap board#

[data-tapboard] elements show every beer with a tap number, in tap order (data-tapboard="8" shows the first eight and a "+ 4 more taps" link). Each row has the name (linking to its tasting notes), style, ABV, IBU, the pour price (10 oz for beers over STRONG_ABV), a "Just tapped" badge and a keg level bar. The heading reads "On tap now" while open, otherwise "Pouring today from 12pm". Keg levels are a stable demo value per beer and day that drains through opening hours (kegLevel()); replace that function if you have a real source.

Tap 4 is the seasonal tap. SEASONAL_TAP names the beers that take turns on it and the release event of each:

js
const SEASONAL_TAP = { tap: 4, beers: { rimfire: 'rimfire-release', tumbleweed: 'tumbleweed-release' } };

Each beer goes on at the start time of its release event and pours until the next one's release starts (assignSeasonalTap() in main.js), so the board, the tasting notes ("Back on tap Saturday, October 24 at 12pm") and the events calendar always agree: Tumbleweed pours from the spring opening of the beer garden, Rimfire from its October release day. Leave tap: null on those beers in BEERS. To pour a beer year-round instead, remove it from SEASONAL_TAP and give it a tap number.

Food trucks#

truckOn(date) picks the truck for a date from TRUCK_ROTA[weekday]: when a weekday lists several trucks they take turns by ISO week number, so Friday to Sunday alternate every other week. Closed days have no truck. [data-truck-today] shows today's truck (or the next opening day's after closing) and ul[data-truck-week] the next seven days with serving times (opening until an hour before close).

Pour menu, snacks and flight builder#

ul[data-pour-menu] lists the taps with pint and 10 oz prices, ul[data-snacks] the SNACKS, and [data-pour-price="pint"] spans show prices from POURS. The flight builder ([data-flight]) has four selects filled with the taps; the paddle SVG and the summary (average ABV and IBU, a light-to-bold drinking order) update on change.

Beer filters, map and tasting notes#

beers.html renders BEERS into [data-beer-grid]. The style chips (data-filter-style), strength chips (data-filter-strength) and the "Pouring now" toggle (data-filter-tap) use aria-pressed, update the count in a polite live region and keep the URL in sync with ?style=, ?strength= and ?tap=1 (validated with own-key checks). The ABV/IBU map dims beers that don't match. "Tasting notes & flavor chart" opens the native <dialog id="beer-dialog"> with the can, stats, notes, flavor radar, hops, pairing and where to buy it; ?beer=<id> opens it on load. The dialog traps focus, closes with Esc, the close button or a click on the backdrop, and returns focus to the button that opened it.

Events and the countdown#

events.html lists upcoming EVENTS in date order (events that have ended, fall on a closed holiday or would start after that day's closing time, such as an evening show on Christmas Eve, are hidden), grouped by month, with a relative label ("Tomorrow", "In 2 weeks"), the time range, price and, for ticketed events, seats left and a phone link. Type chips (data-filter-type, ?type=) filter the list. The next-up card ([data-event-next]) shows the soonest event with "Starts in 6 hours" or "Starts in 2 days". ul[data-events-next="3"] on the home page shows the next three. Seats left are a stable demo number (never below 30% of seats).

Keeping the events current#

The events are written for the weeks after DEMO_ANCHOR ('2026-10-21'), in two kinds. While KEEP_DEMO_CURRENT is true, main.js keeps both current:

  • The regular program (bands, trivia, beer dinners: events without yearly) moves forward by the whole weeks elapsed since the anchor, so it is always ahead of today and every event keeps its weekday:

    js
    const SHIFT_DAYS = D.KEEP_DEMO_CURRENT ? Math.max(0, Math.floor(daysBetween(D.DEMO_ANCHOR, TODAY) / 7) * 7) : 0;
  • Seasonal events (yearly: true: the Rimfire and Tumbleweed releases, costume night, the winter makers market, the summer block party and so on) come back once a year at the same time of year. After one has passed it moves to the next year, on the same weekday in the week ending on the written date's anniversary (yearlyOn()), so costume night is always the Friday before Halloween and never drifts into spring.

The calendar shows events up to the last date of the regular program (about twelve weeks ahead), so seasonal events appear as their season comes round and the list is full on any date. The written dates are what the site shows on the day it was built.

On a real site, enter your own dates in EVENTS and set KEEP_DEMO_CURRENT = false in data.js; every event then keeps its date, past events drop off the list on their own and there is no twelve-week limit. The seasonal tap follows the release events' dates either way. Nothing else in the template is dated: hours, holidays, trucks, slots and tour dates are always worked out from today.

Cart and shop#

shop.html renders PRODUCTS into [data-product-grid], with Beer/Merch tabs (data-shop-tab). Products with an option show a select: tee sizes, or for the crowler fill the beers currently on tap. "Add to order" (data-add="<product id>") adds one, up to the product's limit, and shows a toast. The cart panel ([data-cart-panel]) has quantity buttons (data-qty, data-step) and remove buttons (data-remove), the subtotal, Oregon's container deposit (DEPOSIT × units per product), "None in Oregon" for sales tax, and the total paid at pickup. shop.html?add=<product id> (used by the tasting-notes dialog) adds one item on load.

Checkout and pickup slots#

checkout.html offers the next PICKUP.days open days (pickupDays()), each with slots every PICKUP.slotMinutes from 30 minutes after opening until 30 minutes before close (pickupSlots()). Same-day slots need PICKUP.leadMinutes notice, and PICKUP.slotsFull percent of slots show as full (a stable demo value; replace pickupSlots() with your real capacity). The form checks a slot, name, email and a 10-digit mobile; when the order contains beer it requires the 21+ confirmation. On success the cart is cleared and the confirmation shows a reference like CJ-4821, the pickup time, the lines and the total, and asks for photo ID for beer orders.

Tour booking#

tours.html books TOURS: the brewhouse tour (Fri 4pm, Sat and Sun 12pm and 2pm, 14 places, under-21s free) and the barrel room tour (Sat 4pm, Sun 3:30pm, 8 places, 21+). Dates run from tomorrow to TOUR_BOOK_AHEAD_DAYS ahead on open days; each start time shows "9 of 14 left" or "Full" (tourSeatsLeft(): a stable demo number minus the visitor's own saved bookings). Steppers keep the party within the places left and TOUR_MAX_GROUP. A booking gets a reference like CJT-1234, is saved in localStorage and appears under "Your bookings" with a cancel button, which frees the places again. tours.html?tour=barrel preselects a tour.

Private events inquiry#

contact.html reads SPACES. Choosing a space, date and guest count updates the dark estimate panel: the minimum spend for that weekday (minSpend[0] Sunday to Thursday, minSpend[1] Friday and Saturday), a warning when the guests exceed the space, a per-head figure (only for 8 guests up to the space's capacity, worked out from the minimum for the chosen day), and a note when the taproom is closed that day. Sending checks 8–400 guests and that the count fits the chosen space (SPACES[id].guests), with an inline error otherwise. Dates must be at least HIRE_MIN_DAYS_AHEAD (14) days out; the date field's min is set to match. contact.html?space=garden preselects a space.

Header, mobile menu, reveals and back to top#

Below 1280px the main menu collapses into #mobile-menu, toggled by #menu-toggle (aria-expanded, Esc closes it and returns focus). Elements with .reveal fade in as they scroll into view; everything above the viewport edge is revealed too, and nothing animates with reduced motion. A back-to-top button appears after a screen of scrolling and steps aside for sticky panels marked data-back-to-top-hide.

Forms#

Every form validates in the browser with inline messages ([data-error="<field>"], aria-invalid, and focus on the first problem) and finishes with the business's own confirmation and a reference. The forms don't send anything until you connect them.

Form Page Checks Reference
Pickup order checkout.html Slot chosen, name, email, 10-digit mobile, 21+ box for beer CJ-1234
Tour booking tours.html Date and time, places left, name, email, optional phone CJT-1234
Private events contact.html Space, event type, date 14+ days out, 8–400 guests within the space's capacity, name, email, optional phone CJE-1234

To connect one, find its submit handler in main.js (each has a comment at the point to change) and send the data before showing the confirmation. With Formspree, for example, add action to the form and post it:

js
const res = await fetch('https://formspree.io/f/your-id', {
  method: 'POST',
  body: new FormData(form),
  headers: { Accept: 'application/json' }
});
if (!res.ok) { /* show an error message and stop */ }

Make the handler async, and only show the success panel when the response is OK. The pickup order isn't in a form field, so append it before sending: data.append('pickup', pick.day + ' ' + clock(pick.time)) and the cart lines from Cart.get(). For real tour capacity or pickup slots, replace tourSeatsLeft() and pickupSlots() with calls to your booking system.

Saved data (localStorage)#

Key Shape Validated on read
cinderjack-cart { lines: [{ id, opt, qty }] } Unknown product ids and invalid options are dropped, quantities are clamped to 1…limit, duplicates merged, at most 30 lines
cinderjack-tours [{ ref, tour, date, time, adults, minors, name }] References must match CJT-0000, tours must be keys of TOURS, dates real calendar dates, counts whole numbers within limits; at most 6 kept

All access goes through one safeStorage object: localStorage when it works, otherwise an in-memory stand-in, so the cart and bookings still work for the page view when storage is blocked (sandboxed iframes, strict privacy modes). To reset, clear the two keys in the browser's developer tools, or run localStorage.removeItem('cinderjack-cart').

URL parameters#

Parameter Page Effect
?style=hoppy|crisp|dark|wild beers.html Style filter
?strength=session|standard|strong beers.html Strength filter
?tap=1 beers.html Only beers pouring now
?beer=<beer id> beers.html Opens that beer's tasting notes
?type=music|trivia|release|food|community events.html Event type filter
?add=<product id> shop.html Adds one of that product (products without options)
?tour=brewhouse|barrel tours.html Preselects a tour
?space=loft|barrel|garden contact.html Preselects a space
?now=YYYY-MM-DDTHH:MM every page Previews the site at a Pacific date and time (status, board, trucks, slots, events)

Every value is checked with an own-key lookup (Object.prototype.hasOwnProperty.call), so ?beer=constructor matches nothing.

SEO and sharing#

Each page has its own <title>, meta description, Open Graph tags (og:title, og:description, og:image, og:locale en_US), a Twitter card and theme-color, all in the page's <head>. Social sites need an absolute image URL, so after deploying change every og:image to your domain:

html
<meta property="og:image" content="https://cinderjack.example/assets/img/og-image.png">

Add a sitemap.xml and robots.txt at the root for search engines. A brewery can also add Brewery structured data (schema.org) with the address, phone and openingHoursSpecification matching HOURS.

Accessibility#

  • Skip link, landmarks (header, nav, main, footer), one <h1> per page and a logical heading order.
  • Current page marked with aria-current="page"; today's row in hours tables with aria-current="date".
  • Filters, tabs, day and slot pickers are buttons with aria-pressed; disabled slots are real disabled buttons with "(full)" for screen readers.
  • Counts, cart contents, tour summaries and estimates update in polite live regions; the toast is a role="status".
  • The tasting-notes dialog is a native modal <dialog> labelled by the beer's name.
  • Charts and drawings have text alternatives (role="img" with a label or <title>); decorative cans are hidden.
  • Visible focus outlines, WCAG AA contrast in every section, and no motion with prefers-reduced-motion.

When editing, keep one h1, label every new input and give error messages an id referenced by aria-describedby.

Building and deploying#

Rebuilding the CSS#

assets/css/style.css is compiled from src/input.css and the classes used in the HTML and JavaScript. After changing either, rebuild with Node.js 24:

sh
npm install
npm run build    # or: npm run watch while you work

Classes added only inside JavaScript strings must be written out in full ('bg-ochre', not 'bg-' + color) so Tailwind can find them.

Deploying#

The folder is a static site. Upload it as-is to Netlify (drag the folder onto Netlify Drop), Cloudflare Pages, GitHub Pages, Vercel or any web host. There is no server code; DOCS.md, README.md, src/ and package.json can be left out of the upload.

Troubleshooting#

  • The status says "Opens …" when you're open. Check HOURS and BREW.timeZone, and whether today is in HOLIDAY_HOURS or EXTRA_HOURS. Preview other times with ?now=2026-10-23T13:00.
  • The events list is empty or shows the wrong dates. With KEEP_DEMO_CURRENT off, events before today are hidden: enter future dates in EVENTS. Events on a closed holiday are hidden too.
  • A new beer has no can art or breaks the board. Its motif must be one of the MOTIFS keys, colors needs three values, and LIQUID needs an entry for its id.
  • New Tailwind classes have no effect. Rebuild the CSS with npm run build; classes in JavaScript must be whole strings.
  • The cart forgets items after a reload. The browser is blocking localStorage (private mode, sandboxed iframe): the cart then works in memory for the page view only. Open the site normally.
  • Pickup or tour slots show as full. That's the demo availability (PICKUP.slotsFull, tourSeatsLeft()); set slotsFull to 0 or connect your booking system.
  • The social image doesn't appear when sharing. og:image must be an absolute URL on your domain.

License#

MIT. The code and all included artwork are free for personal and commercial use; the full text is in LICENSE.txt, included in the download. Alfa Slab One and Golos Text are licensed under the SIL Open Font License. Cinderjack Brewing Co., its beers, staff, food trucks, bands and events are fictional.

Search documentation

Search the guides and every template's documentation