Website
Website builder — pages, blocks, and templates
Compose your org's public website in a block-based editor — home page, custom pages, shared header/footer, and the templates that render every news post and event. Includes theme, publishing, and vanity domain setup.
The Website builder is TrailsIQ's block-based CMS for your public site. It powers your home page, an unlimited list of custom pages, and the templates that render every single news post and event through the same visual editor. Live at a canonical preview URL out of the box; wire it to a vanity domain to launch it as your real website.
What the website builder is
Every Pro or Enterprise org gets a full public website driven by a block-based editor. Storage is split two ways:
- Org-level layout — a single JSON blob on the organization row holds the site's on/off switch, the shared header + footer, and the accent-color theme.
- Page rows — one row per page (home, plus every custom page you add) holds the page's title, URL slug, publish flag, sort order, and the ordered list of blocks that make up its body. Two special "template" rows also live here: the Post template (rendered for every single news post) and the Event template (rendered for every single event).
The public URL structure is:
- Home:
/site/{your-org-slug}(canonical) or/on your vanity domain. - Named page:
/site/{slug}/{page}or/{page}on vanity. - Single news post:
/site/{slug}/news/{post}or/news/{post}on vanity. - Single event:
/site/{slug}/events/{event}or/events/{event}on vanity. - Built-in indexes:
/newsand/events(or their canonical prefixes). Create a page with slugnewsoreventsto override the built-in with your own layout. - iCal feeds:
/events.ics(whole calendar) and/events/{event}.ics(single event).
On first open, the builder auto-seeds a Home page (one Hero block), a Post template, and an Event template so nothing renders blank while you're getting oriented.
Opening the editor
Open Settings → Website from the sidebar. If your plan doesn't include the builder you'll see a "Pro plan required" card with an "Upgrade to Pro" link. Otherwise the editor launches full-screen — this is the only surface in TrailsIQ that takes over the whole viewport, because the canvas needs the space.
The top bar reads:
- × close button (returns to the previous page)
- Org name
- Page picker — dropdown grouped by Pages / Shared chrome / Templates. Draft pages show "(draft)" after their title
- + New — opens the "New page" modal
- ⚙ Page settings — for the current page (title, slug, publish flag, delete)
- Site Published / Site Hidden pill
- unsaved amber indicator when there are unsaved changes
- Undo / Redo (Cmd/Ctrl-Z / Cmd/Ctrl-Shift-Z)
- Save (Cmd/Ctrl-S) — writes the current page
- View live ↗ — opens the current page's preview URL in a new tab
- Publish / Hide — the site-wide on/off switch
Flash toasts appear top-right and auto-dismiss after ~3 seconds. Trying to navigate away with unsaved changes triggers a browser confirm.
The three-panel editor UI
Desktop = three columns. Mobile (≤760px) = one column with a bottom tab strip: Blocks / Preview / Details.
- Left panel — Blocks list. Every block on the current page, in render order. Drag the
⠿handle to reorder. Hover a row to reveal Duplicate + Delete icons. Header + Add button opens a grouped picker (Default blocks first, then Prebuilt blocks). Empty-state: "No blocks yet — click +Add." - Center — Live canvas. Renders shared header (locked, click the Shared header — click to edit badge to jump to the shared editor), the current page's blocks, then shared footer. Hovering a block puts a chrome bar with ▲ ▼ duplicate ✕ on top so you can select, reorder, duplicate or delete without switching panels. Empty page shows "Your site is empty" with a "+ Add your first block" button.
- Right panel — Settings. With no block selected: the Theme editor (a single Accent color input; hint "Used for buttons, headlines accents, hover states."). With a block selected: that block's editor form. Unrecognised block types fall back to a raw-JSON textarea with a "No editor yet for <type> — raw JSON below." header.
Every block editor pane also includes a Colors section, a Divider top / Divider bottom picker, and an Anchor ID field for in-page links.
Blocks — the building materials
The block palette is split into two groups.
Default blocks — the composition primitives.
- Text / embed — Heading, paragraph, or raw HTML (iframe embeds, etc.).
- Columns — N side-by-side columns; each can hold any combination of other blocks.
Prebuilt blocks — the ready-to-use content sections.
- Top menu — Fixed navigation across the top. Lives in the shared header page, not a regular page.
- Hero — Full-bleed cover image with headline and CTAs.
- Stats bar — 4-up counters populated from your live trail data.
- Trail conditions — Per-network open/closed status pulled live.
- Hourly forecast — Weather now + next-up.
- Card slider — Carousel of feature cards; center card stands out.
- News grid — Grid of article cards with image, title, excerpt. Auto-pulls from your published News dashboard (up to 12), or you can hand-curate a list.
- Find your trail — Dark CTA section with linked cards.
- Events list — Upcoming events with date, meta, and tag. Same auto vs manual toggle as News.
- Sponsors — Sponsor logos or names with optional links.
- Features grid — 3-column icon + title + description cards.
- How it works — Numbered steps row with connecting line.
- Call to action — Centred headline + subtitle + buttons.
- Marketing hero — Dark hero with badge, headline, buttons + optional phone mockup.
- Smartphone mockup — Standalone phone frame you can slot into columns.
- Feature showcase — Two-column: text + bullet list + image.
- Trails list — The full trail list grouped by network — same layout as the hub page.
- Footer — Lives in the shared footer page, not a regular page.
Every block supports rich per-block color overrides so you can tint a hero eyebrow, a card background, or a CTA button independently from the site accent. Typography is fixed to Barlow, Barlow Condensed, and Bebas Neue.
Creating and editing pages
+ New opens the "New page" modal:
- Title — the label that shows in the page picker (placeholder "e.g. Conditions").
- URL slug — prefixed with
/. Auto-fills from the title until you edit it. Hint: "Letters, numbers, hyphens. Auto-fills from the title." Server rules: lowercase letters + digits + hyphens, must start and end with an alphanumeric, unique per org.
Errors surface as "Slug can only contain lowercase letters, digits, and hyphens." or "A page with that slug already exists." Flash on success: "Page "{title}" created." The new page lands in your page picker; the canvas opens on an empty state ready for blocks.
⚙ Page settings on the topbar opens a modal for the current page: preview URL, Title, URL slug (locked to '' for the home page with hint "The home page's slug is locked."), "Page published (visible to visitors)" checkbox, and a Delete page button. Home cannot be deleted — the server refuses with "The home page cannot be deleted."
Switching pages with unsaved changes shows "You have unsaved changes. Switch pages anyway?" Flash messages on save/delete: "Page updated.", "Page deleted.", "Page saved."
The shared header + footer
The nav bar and footer aren't per-page — they live on a dedicated Shared chrome page in the page picker (under a "Shared chrome" group). Both are Menu / Footer blocks with their own editors.
Menu editor. Wordmark (defaults to your org name), Menu links (add/reorder a list of label+href pairs), and a Call-to-action button (label + href; leave the label blank to hide the button — hint "Filled button on the right of the menu."). Your org logo from Settings auto-renders next to the wordmark.
Footer editor. Tagline, Social links (Facebook, Instagram, X/Twitter, YouTube, LinkedIn, TikTok), Link columns (each with a heading + link list), and a Copyright line (defaults to "© {year} {org name}").
Both render on every public page — the canvas locks them and shows a purple Shared header — click to edit / Shared footer — click to edit badge; clicking jumps you into the shared editor.
Post + Event templates
Every news post and every event renders through a template — one for posts, one for events — so you set the layout once and all articles / events pick it up.
Post template. Editable in the page picker under Templates → Post template. It's composed with template-only slots: post_hero, post_title, post_meta (published date + "By {author}" byline), post_excerpt, and post_body. Drop these in whatever order you like; wrap them in Columns; add a CTA underneath; whatever fits your brand. If you clear the template, sensible defaults render (hero + excerpt + body).
Event template. Same idea. Slots: event_hero, event_title, event_when, event_location, event_excerpt, event_body, event_maintenance ("What we'll be working on" — auto-pulls the linked open maintenance issues), and event_signup (the RSVP form). Rearrange them, wrap them in Columns, drop a features grid underneath — anything.
Slot blocks are hidden from the palette on regular pages so you can't accidentally place a post_body on your home page and stare at a blank spot.
Theme and per-block styling
Accent color is the one site-wide lever, editable in the right panel when no block is selected. It cascades: explicit website accent → the org's Settings → Primary color → an STP fallback if both are blank. The accent drives buttons, headline accents, and hover states across every block.
Every individual block has a Colors section under its editor that overrides the accent for that block only — hero eyebrow, card background, section background, CTA button, whatever the block exposes. Overrides are stored as config.style.{key} and applied as CSS custom properties on the block root, so they never bleed sideways.
Logo comes from your Settings → Organization logo. Update it there once and the menu block, favicon, and every share preview pick it up.
Uploaded images. All image blocks share the same uploader: POST to a shared endpoint under website-images/{orgId}, JPG/PNG/WebP up to 5 MB, gated by your org's plan-storage quota. If storage is full the upload fails with the plan-limit error.
Publishing and previewing
Publishing is site-wide, not per-page. The Publish / Hide button in the topbar flips the whole website's visibility. Flash: "Website published." / "Website hidden."
Per-page publish flag. Every page has its own Page published checkbox in the Page settings modal, so you can draft a page while the site is live. Unpublished pages return a 404 to public visitors.
Preview. Managers always see everything, published or not, with a yellow banner across the top:
- "Preview — this site is currently hidden from visitors." when the site is off.
- "This page is unpublished — visitors get a 404." when a specific page is drafted.
View live ↗ on the topbar opens the current page's preview URL in a new tab so you can spot-check the render.
Custom (vanity) domain
By default your site lives at /site/{your-org-slug} on app.trailsiq.com. Attach a custom domain to launch it as your real website (trails.example.com for instance).
Setup lives at Settings → Custom domain (only visible when the install has Cloudflare-for-SaaS configured). Same Pro/Enterprise plan gate applies. The flow:
- Enter your hostname. Error copy blocks the obvious mistakes: "Enter a valid hostname like trails.example.com (no http://, no path).", "That domain is already attached to another organization.", "That hostname is reserved."
- Flash on success: "Custom domain registered. Add the DNS record at your registrar, then click "Re-check status"."
- Update your registrar's DNS to point the hostname at the CNAME shown on the page (or the A-record IP fallback if you're stuck at an apex domain that can't CNAME).
- Click Re-check status until the pill flips to "Live".
Once the domain is Live, TrailsIQ serves the block-based site directly at that hostname. Sessions and CSRF don't run on vanity requests (Cloudflare-for-SaaS dispatches without the web middleware) — the platform compensates via explicit props and honeypot + rate-limit protections. Cloudflare Turnstile is skipped on vanity too because Cloudflare's free-tier hostname cap makes it impractical.
If your builder is turned off, the vanity domain falls back to the bare hub page at /hub/{slug} so your visitors still see something.
Permissions and plan gating
Plan gate. The website builder is available on Pro and Enterprise. Free orgs see Settings → Website but land on a "Pro plan required" card with the body "The website builder is part of the Pro plan, alongside vanity domains." Mutating endpoints abort with "Website builder requires Pro or Enterprise." if hit directly.
Role gate. The "Manage website" permission (blurb: "Edit the website-builder pages, navigation, theme, and the home + about content that surfaces on the public hub. Requires Pro or Enterprise.") defaults on for owners and managers; off for field workers and volunteers. Toggle it per-role from Settings → Roles & permissions. Platform admins always pass. The sidebar entry only renders when the permission is on.
Custom domain shares the plan gate and adds its own role gate. The error copy on the customer domain create endpoint reads "Custom domains are available on the Pro plan and above."
Common gotchas
- The home page slug is locked. It can't be renamed or deleted. Renaming would orphan every
href="/"link across your site; deleting would leave you without a root URL. - Turning off the site hides everything from visitors but managers keep seeing every page with the yellow preview banner. Individual pages can be unpublished while the site is live.
- Menu + Footer live in the shared chrome page, not on individual pages. Trying to add them to a regular page's canvas isn't possible — the palette hides them.
- Post and event body slot blocks are template-only. They inject data from the currently rendering news post / event. Dropping a
post_bodyblock on your home page shows nothing. - Auto news/events blocks show published items only. A news post has to be published and its publish date reached; an event has to be published and still upcoming.
- Auto-mode blocks show up to 12 items. Max posts to show picks any number up to that.
- Image uploads count against your plan storage quota. A rejected upload returns the storage-limit error from the guard.
- Vanity domain quirk — no sessions. Signup flashes on vanity domains use URL query flags (
?signup=success&signup_msg=…) instead of session flash so success messages still land. - Internal links on the canonical preview host get auto-prefixed. A block's
href="/about"becomes/site/{slug}/abouton the canonical URL and stays/abouton vanity, so you can author bare links once and both hosts work. - Search and sharing are set per page, plus a site-wide fallback. Page settings has a Search title and Description; Settings → Website has the site description, the share image and the favicon used where a page sets none. Leave everything blank and each page still gets its own sensible title — the page name and yours — rather than one title repeated across the site.
What's next
- Read the News article to see how the News grid block turns your published articles into a live section.
- Read the Events article to see how the Events block,
/eventsindex, and per-eventevent_signupform all compose through the builder. - Set your custom domain on Settings → Custom domain and launch. The rest — page copy, hero photos, menu links — you can iterate on with the site live.