Freeframe

Documentation

Wardline

v1.0.0Updated Nov 3, 2026Compliance automation, calm and audit-ready.

Overview#

Wardline is a corporate B2B SaaS website for a compliance automation product, built as a WordPress block theme. The fictional company, Wardline, Inc., is based at 1520 E Cary St in Richmond, Virginia, and makes a platform that helps startups and mid-size companies prepare for SOC 2, ISO 27001, HIPAA, GDPR, PCI DSS and NIST CSF with continuous control monitoring, evidence collection, policies, vendor risk, access reviews and a public trust center. The theme has a home page with a control dashboard that switches between frameworks; a six-tab platform tour with a product mockup per tool; a framework explorer with control families and cross-mapping; an eight-question readiness assessment; a pricing calculator; a searchable integrations directory; a trust center with rolling report dates and a document request form; customer stories with before-and-after charts; a three-step demo booking in the visitor's time zone; and a 404 page. It is version 1.0.0 (see template.json and style.css), works with WordPress 7.1 and PHP 7.4 or newer, and is the WordPress version of the HTML template of the same name. See it live at freeframe.dev/templates/wardline.

Headings, copy, lists, plan cards, story text, buttons and the pricing questions are core WordPress blocks arranged in block patterns, so you edit them in the block editor without touching code. The parts that are worked out in the browser (the dashboard, the framework cards, the tabs and product mockups, the explorer, the assessment, the calculator, the directory, the trust center lists and form, the story filter and charts, and the demo booking) work as in the HTML version: they are Custom HTML blocks driven by assets/js/main.js, which reads the product data from assets/js/data.js. Colors and fonts are design tokens in theme.json: change them in Appearance > Editor > Styles and the whole site follows. Every date is worked out in America/New_York (Eastern time) from rules rather than fixed dates, so the demo never goes stale.

The copy is careful about what a compliance tool can claim: Wardline helps customers prepare, and independent auditors (a licensed CPA firm for SOC 2, an accredited certification body for ISO 27001) issue reports and certificates. Keep that distinction if you adapt the theme for a real product.

Quick start#

Requirements: WordPress 7.1 or newer and PHP 7.4 or newer. No plugins are needed.

  1. Download wardline.zip from freeframe.dev/templates/wardline (the WordPress tab).
  2. In your WordPress admin go to Appearance > Themes > Add New Theme > Upload Theme, choose the zip and click Install Now, then Activate. The theme is listed as Freeframe Wardline.
  3. Go to Appearance > Wardline setup and click Create the demo pages. This creates the Home, Platform, Frameworks, Readiness assessment, Pricing, Integrations, Trust center, Customers and Book a demo pages from the theme's page patterns, sets Home as the front page (Settings > Reading) and creates the header menu. Pages that already exist with the same slug are left alone, so it is safe to click it again.
  4. Visit your site. Edit any page in Pages, and the header, footer and templates in Appearance > Editor.

You can also try the theme without installing anything: the Try it in WordPress button on freeframe.dev opens it in WordPress Playground (WordPress running in your browser) with the demo pages already set up.

To work on the theme's files locally you need Node.js 24 and pnpm; WordPress itself runs in WordPress Playground, so there is no PHP, web server or database to install:

sh
pnpm install
pnpm dev     # builds the CSS, then starts WordPress with the theme at http://127.0.0.1:9400

pnpm dev signs you in as admin (password password) and creates the demo pages. The site is rebuilt from scratch every time you start it; your edits to theme files are live, edits made in the WordPress admin are not kept.

Pages#

Each page is a page pattern (in Patterns > Wardline pages) made of section patterns. Every section is also offered on its own in the block inserter under Patterns > Wardline.

Page Slug Page pattern Sections (pattern files in patterns/)
Home / page-home.php home-hero (control dashboard), customer-logos, how-it-works, framework-cards (built from FRAMEWORKS), numbers, who-does-what, home-story, home-cta
Platform /platform/ page-platform.php platform-header, product-tour (six tabs; #evidence opens one), roles, access-security, platform-cta
Frameworks /frameworks/ page-frameworks.php frameworks-header, framework-explorer (#explorer), overlap-matrix, who-issues-what, frameworks-cta
Readiness assessment /assessment/ page-assessment.php assessment (questions and results), assessment-method
Pricing /pricing/ page-pricing.php pricing-plans (plan cards), pricing-calculator (#calculator), plan-comparison, pricing-faq
Integrations /integrations/ page-integrations.php integrations-header, integrations-directory, integrations-other, integrations-connect, integrations-cta
Trust center /trust/ page-trust.php trust-header (report dates), trust-controls, trust-documents, subprocessors, document-request (#request)
Customers /customers/ page-customers.php customers-header, story-filter, story-kelvara (#kelvara), story-mendwell, story-hirebeam, story-results, customers-cta
Book a demo /contact/ page-contact.php demo-booking
404 any missing URL templates/404.html 404

WordPress posts use templates/single.html; the blog, archives and search results use templates/index.html, templates/archive.html and templates/search.html.

Project structure#

freeframe-wardline/
  style.css                 theme header (name, version, requirements, license); no styles
  theme.json                design tokens: palette, fonts, font sizes, spacing, layout widths, button
  functions.php             loads the files in inc/
  inc/setup.php             stylesheet and scripts (with the script's strings and page URLs), editor
                            styles, the `js` class script, theme color and favicon, page titles,
                            pattern categories
  inc/icons.php             registers assets/icons/*.svg for the Icon block
  inc/icon-labels.php       the icons' names shown in the editor
  inc/block-styles.php      button block styles
  inc/site-setup.php        Appearance > Wardline setup: creates the demo pages and the menu
  templates/                page.html (pages), page-with-title.html, single.html, index.html,
                            archive.html, search.html, 404.html
  parts/                    header.html and footer.html (they show the header and footer patterns)
  patterns/                 every section and page (PHP files with block markup)
  assets/css/theme.css      the compiled stylesheet (do not edit: built from src/)
  assets/css/editor.css     the same for the block editor (generated by src/editor-css.mjs)
  assets/js/data.js         the product data (window.WARDLINE): FRAMEWORKS, CONTROLS, INTEGRATIONS,
                            PLANS, ADDONS, ASSESSMENT, TRUST_CATEGORIES, DOCUMENTS, DEMO and more
  assets/js/main.js         every interaction (the HTML version's script plus a WordPress adapter)
  assets/icons/             the icons used by Icon blocks (outline SVG paths)
  assets/img/               favicon.svg (header logo), logo-footer.svg, social image, illustrations
  assets/fonts/             Anek Latin, Source Sans 3 and Roboto Mono, with their licenses
  src/theme.css             the Tailwind CSS source of assets/css/theme.css
  src/icons.css             icons drawn after button text with CSS (generated)
  src/editor-css.mjs        writes assets/css/editor.css after each build
  languages/                freeframe-wardline.pot, the template for translations
  blueprint.json            WordPress Playground setup used by `pnpm dev`
  screenshot.png            the picture shown in Appearance > Themes
  package.json              the CSS build and the local WordPress (Node.js tooling)
  readme.txt, README.md, DOCS.md, CHANGELOG.md, LICENSE.txt

Customizing#

Brand and colors#

The palette is in theme.json (settings.color.palette) and shows in Appearance > Editor > Styles > Colors. The stylesheet maps every Tailwind color to these presets (--color-teal: var(--wp--preset--color--teal) in src/theme.css), so changing Teal in Styles changes every button, link, chip and focus ring that uses teal.

Color Value Used for
Ink #0b1a2c Headings, body text, dark bands, the header strip and footer
Paper / Card / Cloud #f6f8fa / #ffffff / #edf1f5 Page background, panels, alternate bands
Line / Line strong #dbe2ea / #93a1b3 Hairlines and input borders
Slate / Slate 2 #3f4d61 / #566376 Secondary text and captions (AA on light backgrounds)
Frost #a9b8ca Secondary text on ink
Teal, Teal deep, Teal soft, Teal bright #0b6f80 … The accent: buttons, links, focus rings, charts
Passing, Attention, Failing (and their soft tints) green, amber, red Status pills, always with a symbol and a word

Some SVG art (the seals, Venn diagram, charts and monograms in main.js, and the inline mockups and illustrations in the patterns) uses hex values directly; search for #0b6f80 to update them too.

Typography#

Three families are bundled in assets/fonts/ and declared in theme.json (no requests to Google):

  • Anek Latin (500–700) for headings (font-display)
  • Source Sans 3 (400–700, italic 400) for body text (font-sans, the body font)
  • Roboto Mono (400, 500) for control IDs, labels and figures (font-mono)

Swap a family in Styles > Typography, or add your own fontFace files to theme.json. In SVG, quote "Source Sans 3" (font-family="'Source Sans 3'"), because a family name ending in a number must be quoted.

Content#

Page copy (headings, paragraphs, plan cards, story text, the pricing questions) is in the pages: edit it in the block editor. Everything data-driven lives in assets/js/data.js on window.WARDLINE, as in the HTML version:

Constant What it holds
FRAMEWORKS Six frameworks with a one-letter code, seal shape, issuer, summary and prep
FAMILIES Fifteen control families by two-letter prefix
CONTROLS The 81-control library as [id, title, frameworkLetters]
INTEGRATION_CATEGORIES, INTEGRATIONS Six categories and 24 integrations with checks, setup minutes and access
ANNUAL_DISCOUNT, PLANS, ADDONS Pricing rules
ASSESSMENT Sizes, five scored questions, targets, deadlines and score bands
TRUST_CATEGORIES, SUBPROCESSORS, DOCUMENTS, PERSONAL_DOMAINS Trust center content and email checks
DEMO, SPECIALISTS Demo form options, slot times and routing
STORIES Customer stories and their before-and-after metrics

Adding a control mapped to SOC 2, ISO 27001 and NIST CSF updates every count, bar, Venn diagram and matrix cell:

js
["AC-10", "Break-glass accounts sealed and alerted", "SIN"],

Adding an integration:

js
{ id: "shiftledger", name: "Shiftledger", category: "hr", checks: 7, summary: "…", access: "Read-only report token", minutes: 5 },

Numbers in the copy that come from the data (81 controls, 24 integrations, 361 checks) are spans with data-stat that the script fills, so they follow data.js. Edit data.js in a child theme (see Child themes) so an update doesn't overwrite it.

Images and artwork#

All artwork is SVG drawn for this template; there are no photos. The header logo is an Image block (assets/img/favicon.svg), the footer logo another (assets/img/logo-footer.svg): select one and Replace to use your own. The step illustrations, the integrations hub, the 404 shield, the six platform mockups and the hero dashboard are Custom HTML blocks with inline SVG and HTML; they are pictures of a product, not content, so replace a whole block with an Image block (keep roughly the same aspect ratio) when you have real screenshots. Framework seals (seal()), integration monograms (monogram()), the Venn diagram and the story charts are drawn by main.js. The seals are original generic badges, not any standards body's mark; keep it that way unless you have permission to use an official logo. The customer marks next to the logo names are Icon blocks.

The social image is assets/img/og-image.png (1200 x 630, source og-image.svg); the favicon assets/img/favicon.svg is used until you set a Site Icon in Settings > General.

The header and footer are template parts (parts/header.html, parts/footer.html) showing the header and footer patterns. Edit them in Appearance > Editor > Patterns > Header / Footer.

The header has two Navigation blocks showing the same menu: the desktop one (from 1024 px) and the one in the phone menu. Edit the menu once in Appearance > Editor > Navigation (the setup creates "Main menu": Platform, Frameworks, Integrations, Pricing, Customers, Trust center and Readiness assessment). A menu item with the class ff-mobile-only (Readiness assessment, under the link's Advanced settings) only shows in the phone menu, as in the HTML version, where the desktop header links to it from the dark strip at the top. WordPress marks the current page's link with aria-current="page", and the script marks the header's "Book a demo" button on the demo page (class ff-current-link). A Navigation block that doesn't point at a menu shows the most recently created one; to pin a menu, select the Navigation block and choose it in the block settings, for both blocks.

The footer's link columns are List blocks: click a link to change it, press Enter to add one. The office status line (class ffd-office-status) is replaced by the script; the copyright year is written by PHP. The phone number and emails appear in the header, the footer and several pages; search for them when you change them.

Features#

Hero control dashboard#

initHeroDashboard() switches the dashboard on the home page between three frameworks with the [data-dash-fw] buttons (aria-pressed). Each framework's passing, attention and failing counts, readiness percentage and audit-window offset are in the states object inside that function. The audit window date is today plus the offset (46 days for SOC 2, 73 for ISO 27001, 29 for HIPAA), so on Nov 3, 2026 SOC 2 shows "Dec 19, 2026 · in 46 days".

Platform tabs#

initTabs() drives the product-tour section with the ARIA tabs pattern: arrow keys, Home and End move between tabs, and the URL hash (#controls, #evidence, #policies, #vendors, #access, #trust) opens a tab directly. The tab list and each product mockup are Custom HTML blocks; the text beside each mockup is ordinary blocks inside the tab panel Group. Dates inside the mockups use data-day-offset (see Keeping the demo current).

Framework explorer and cross-mapping#

initFrameworks() on the Frameworks page renders the selected framework's issuer, preparation note, control count and families from FRAMEWORKS and CONTROLS, then compares it with a second framework. A control counts toward a framework when its letters include the framework's code. With the shipped data SOC 2 has 61 controls, ISO 27001 63, HIPAA 36, GDPR 17, PCI DSS 49 and NIST CSF 46; SOC 2 and ISO 27001 share 57 ("57 of SOC 2's 61 controls (93%) also count toward ISO 27001. Adding ISO 27001 after SOC 2 means 6 new controls, not 63."). renderMatrix() draws the pairwise matrix; each number links to that pair. URL parameters: ?fw=<id>&vs=<id|none> (soc2, iso27001, hipaa, gdpr, pci, nist); unknown values fall back to SOC 2 compared with ISO 27001. The page keeps the URL in step with history.replaceState.

Readiness assessment#

initAssessment() steps through eight questions (size, cloud, policies, identity, logging, vendors, target, deadline); options come from ASSESSMENT. In assess():

  • Score: the five scored answers add up their points (20 each at best, 100 in all).
  • Band: 80+ "Well prepared", 55+ "Solid foundation", 30+ "Early stage", below that "Starting out".
  • Gaps: every scored answer below 20 points, ranked by points missing (ties keep question order); 10 or more missing is "High priority", otherwise "Medium priority".
  • Range: low = round((targetLow + gapWeeks) × sizeFactor), high = round((targetHigh + gapWeeks × 1.5) × sizeFactor), with size factors 1, 1.15, 1.35, 1.6.
  • Deadline verdict: "Realistic" when high fits the deadline weeks (13, 26 or 52), "Tight" when only low fits, "At risk" otherwise; "No date" with no deadline.

Example: 51–200 people, one cloud set up by hand, draft policies, MFA without SSO, some logs, no vendor reviews, SOC 2 Type II, 3–6 months gives 47 ("Early stage"), 16–24 weeks and "Realistic". Answers are saved as they are chosen; the results link to /contact/?fw=<framework>&size=<size>.

Pricing calculator#

initPricing() and quote() on the Pricing page. The plan follows the employee count (5–2,000): Essentials up to 100, Growth up to 500, Scale up to 2,000.

monthly = base + extra employees × perEmployee + extra frameworks × extraFramework + add-ons
annual per month = round(monthly × (100 − ANNUAL_DISCOUNT) / 100)
Plan Base Included employees / frameworks Per extra employee Per extra framework Included add-ons
Essentials $690 25 / 1 $8 $240 none
Growth $1,450 100 / 2 $6 $200 Trust center
Scale $3,200 500 / 3 $4 $160 Trust center, vendor risk

The default (60 employees, 1 framework, annual) is $776 a month ($9,312 a year). 120 employees, 2 frameworks, vendor risk and training is Growth at $1,656 a month billed annually. The plan cards' "from" prices ($552, $1,160, $2,560) are filled from PLANS; the matching card gets a teal ring and the "Matches your estimate" label.

Integrations directory#

initIntegrations() filters INTEGRATIONS by category chip and a search over name, summary and category, and sorts by name or by number of checks. Chip counts follow the search, the filters are saved, and ?category=<id> (cloud, identity, hr, ticketing, code, endpoint) opens a category. Identity and SSO plus "mfa" shows "2 integrations · 33 automated checks".

Trust center#

initTrust() renders the control categories (TRUST_CATEGORIES, 20 of 21 passing), the subprocessor table and the report dates. The script looks for its markup inside [data-trust]; in WordPress the first trust section carries the class ff-trust and the adapter puts data-trust on <main>. "Request access" buttons check that document in the request form below; ?doc=<id> prechecks one.

Customer stories#

initStories() draws two bars per metric from STORIES[].metrics (before in gray, after in teal, each with a text label and an aria-label), and the chips filter the story sections by framework (class ffd-frameworks--soc2_pci on each story Group becomes data-frameworks="soc2 pci").

Demo booking and time zones#

initDemo() on the Book a demo page runs three steps: team (role, size, at least one framework, timeline), details (name, work email, company, note) and a time. Slots are DEMO.times in Eastern time (10:00, 11:30, 13:00, 14:30, 16:00) on the next five business days after today, skipping weekends and US federal holidays computed by rule in holidaysFor(year) (Saturday holidays move to Friday, Sunday holidays to Monday). With ?now=2027-11-24T12:00 the days are Fri Nov 26 to Thu Dec 2, with the note "Closed Nov 25 for Thanksgiving Day." Some slots show as booked by a fixed hash of date and time (slotTaken()). Times show in the visitor's own zone with the Richmond time underneath; the "Show times in" select switches between it and six others, and ?tz= preselects one. The call is routed by SPECIALISTS (HIPAA to Soledad Ilunga, PCI DSS to Evander Lachance, 201+ employees to Ravindra Satterwhite, everyone else to Leontyne Fairbairn). ?fw=, ?size= (s1–s4) and ?plan= prefill the first step.

initMenu() toggles the phone menu (aria-expanded, Escape closes it and returns focus). initOfficeStatus() shows "Open now" or "Closed now" for Mon–Fri, 8:30 a.m.–5:30 p.m. ET, and "Closed today for …" on federal holidays. Elements with .reveal fade in as they scroll into view; reduced motion shows everything at once, and the pulse dot in the status strip stops.

Keeping the demo current#

Nothing dated goes stale:

  • KEEP_DEMO_CURRENT = true in main.js rolls the trust center dates: the SOC 2 Type II period ends on the latest September 30 whose report has been issued (the fourth Wednesday of October), the ISO 27001 certificate runs in three-year cycles from March 14, 2025, and the latest penetration test is the most recent August. On Nov 3, 2026 that is Oct 1, 2025 – Sep 30, 2026, issued Oct 28, 2026. Set it to false to show the fixed dates in FIXED_REPORTS.
  • data-day-offset="-3" (with data-format="short|medium|weekday") fills a date relative to today; data-today fills today's date; data-year fills the copyright year (also written by PHP).
  • The hero audit window, the document review day and the demo slots are worked out from today.
  • ?now=YYYY-MM-DDTHH:MM previews the whole site at another Eastern time.

For a real site with fixed dates, set KEEP_DEMO_CURRENT to false, edit FIXED_REPORTS, and replace the data-day-offset elements in the mockups with real dates.

Block styles#

In the block settings' Styles panel:

Block Styles
Button Fill (default, the teal button), Ghost, Ink, Light (on dark), Outline (on dark)

The class is-small on a Button block makes it the smaller size. The arrow after button text is drawn with CSS (icon-after-arrow-right, from src/icons.css). The pricing questions are Details blocks with the class faq, which draws the summary and its plus sign.

Forms#

There are two forms that collect details, and neither sends anything until you connect it. They are in Custom HTML blocks.

Form Pattern Validates Success state
Document request (data-access-form) document-request at least one document, full name, company, a valid work email (not a personal domain from PERSONAL_DOMAINS), the NDA box when a chosen document needs it reference TR- + 6 characters, the next business day for review, next steps
Book a demo (data-demo-form) demo-booking step 1: role, size, a framework, timeline; step 2: first and last name, work email, company; step 3: a slot reference DM-MMDD-XXXX, the time in Eastern and the visitor's zone, the specialist, next steps

To connect a form service such as Formspree, post the form data in the submit handler and show the success panel only when the service answers OK. In assets/js/main.js (in a child theme), find the comment "To connect a real endpoint" (document request) or "To connect a real scheduler" (demo):

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

Make the handler async. For bookings you would usually call your scheduling tool's API instead and use its confirmed time. You can also replace a form's Custom HTML block with a form plugin's block; add the classes label, field and btn to its labels, fields and button so it matches.

Saved data (localStorage)#

Key Shape Validation on read
wardline:assessment:v1 { "size": "s2", "cloud": "single", …, "target": "soc2t2", "deadline": "d6" } each answer must be a known option key
wardline:pricing:v1 { "employees": 120, "frameworks": 2, "addons": ["vendor"], "billing": "annual" } whole numbers in range, known add-on ids, monthly or annual
wardline:integrations:v1 { "category": "identity", "q": "mfa", "sort": "name" } known category or all, up to 60 characters, name or checks
wardline:demo-draft:v1 { "role", "size", "frameworks", "timeline", "first", "last", "email", "company", "note" } known keys only, strings trimmed; removed after booking

These are the HTML version's keys. All access goes through safeStorage in main.js: when localStorage is blocked (sandboxed iframes, strict privacy settings), it falls back to memory, so every feature keeps working for the page view. Keys from storage and the URL are checked with Object.prototype.hasOwnProperty, so values like ?fw=constructor are ignored. To reset, clear the site's data in the browser.

SEO and sharing#

Page titles come from WordPress: the page title, a vertical bar and the site name (for example "Pricing and cost calculator | Wardline"); the home page shows "Wardline: compliance automation for SOC 2, ISO 27001 and HIPAA", built from the site title and tagline (Settings > General) by freeframe_wardline_front_title(). The theme doesn't output meta descriptions or Open Graph tags; use an SEO plugin such as Yoast SEO, Rank Math or The SEO Framework, and give it assets/img/og-image.png (or your own 1200 x 630 image) as the default social image. WordPress already generates a sitemap at /wp-sitemap.xml. A SoftwareApplication or Organization structured-data block is a good addition once you have real details.

Accessibility#

Built in: a skip link to the main content (added by WordPress, styled by the theme), landmarks (header, labelled navigation, main, footer), one h1 per page, labelled sections, visible teal focus rings (bright teal on dark bands), the ARIA tabs pattern, toggle buttons with aria-pressed, a menu button with aria-expanded, status shown with a symbol and a word as well as color, charts with text labels and aria-label summaries, live regions for counts, overlap text and estimates, inline errors tied to their fields with aria-describedby and aria-invalid, focus moved to the first problem, keyboard-focusable scrollable tables, and reduced-motion support. The demo passes axe (WCAG 2.1 A and AA) in its checks.

When you edit: keep one Heading 1 per page, give images alt text (or mark them decorative), label every field you add, and keep body text at the Slate colors or darker.

Building and deploying#

You only need this if you change the theme's files. The stylesheet assets/css/theme.css is compiled with Tailwind CSS from src/theme.css and the classes used in patterns/, parts/, templates/, inc/ and assets/js/:

sh
pnpm install
pnpm build   # compile assets/css/theme.css and assets/css/editor.css
pnpm watch   # recompile assets/css/theme.css on every change (run pnpm build before you commit)

Run pnpm build after adding a utility class to a pattern, template or the script's markup, otherwise the class has no style; keep each class name whole in the script (not built from pieces). Classes you type in the editor's Additional CSS class(es) field are only styled if the stylesheet already contains them.

To deploy, zip the theme folder (named freeframe-wardline, without node_modules/) and upload it in Appearance > Themes, or copy the folder to wp-content/themes/ on your server. Use HTTPS, and connect the forms before you go live.

Translations#

The theme is translation-ready with the text domain freeframe-wardline. All text in patterns, templates and PHP goes through WordPress's translation functions; the script's own labels and messages (validation errors, statuses, button labels) are translated in PHP (freeframe_wardline_script_strings() in inc/setup.php). Sentences the script builds from pieces (dates, estimate lines, the overlap sentence) are written in English in main.js; translate them there. The product's content in assets/js/data.js is edited there directly. Create a translation with Loco Translate, or with WP-CLI and Poedit:

sh
wp i18n make-pot wp-content/themes/freeframe-wardline wp-content/themes/freeframe-wardline/languages/freeframe-wardline.pot

Save freeframe-wardline-es_ES.mo (for example) in wp-content/languages/themes/ or in the theme's languages/ folder. Page content created by Wardline setup is copied into your pages in the site's language at that moment; translate it in the editor like any other content.

Child themes#

Use a child theme for changes you want to keep when Wardline is updated (your frameworks, prices and integrations in particular). Create wp-content/themes/wardline-child/style.css:

css
/*
Theme Name: Wardline Child
Template: freeframe-wardline
*/

Templates, parts, patterns and theme.json in the child theme override the parent's files of the same name. To use your own data.js, replace the parent's data script (freeframe-wardline-data) under the same handle in the child's functions.php:

add_action( 'wp_enqueue_scripts', function () {
	wp_deregister_script( 'freeframe-wardline-data' );
	wp_register_script( 'freeframe-wardline-data', get_stylesheet_directory_uri() . '/data.js', array(), '1.0', array( 'in_footer' => true, 'strategy' => 'defer' ) );
}, 15 );

Do the same for assets/js/main.js (handle freeframe-wardline), keeping the inline window.freeframeWardline strings and page URLs. The parent's stylesheet only contains the classes the parent uses: if your child theme uses new utility classes, compile a stylesheet for the child (copy package.json and src/theme.css, point the @source lines at the child's folders) and enqueue it.

Troubleshooting#

  • The pages look unstyled or new classes do nothing. The stylesheet only contains classes it found when it was built. Run pnpm build after editing patterns, then reload.
  • "This block contains unexpected or invalid content". A pattern or page was edited by hand with markup that doesn't match the block. Click Attempt recovery, or re-insert the section from Patterns > Wardline.
  • The assessment opens on the results. Answers are saved; use "Start over", or remove wardline:assessment:v1.
  • Demo slots are on the wrong days. Dates come from the visitor's clock in Eastern time; check for a leftover ?now= in the URL, and edit holidaysFor() for your own office closures.
  • Framework or booking links go to the wrong page. The script links to /frameworks/ and /contact/. If you renamed those pages, change their URLs in freeframe_wardline_page_urls() in inc/setup.php (in a child theme, filter the inline script).
  • Report dates don't match your real report. Set KEEP_DEMO_CURRENT to false and fill FIXED_REPORTS.
  • Wardline setup says the pages exist, but they are empty. It never overwrites existing pages. Delete (and empty the trash of) the pages with those slugs, or open each page and insert its page pattern from Patterns > Wardline pages.

License#

Split license: the PHP code and block markup are licensed under the GNU GPL, version 2 or later, and the CSS, JavaScript, images and design under the Freeframe Commercial License (unlimited sites for you and your clients; no resale or redistribution as a theme). The full terms, with your licensee details, are in LICENSE.txt and at https://freeframe.dev/license#commercial. Third-party components keep their own licenses. Fonts: Anek Latin, Source Sans 3 and Roboto Mono are licensed under the SIL Open Font License 1.1 (OFL.txt in each folder of assets/fonts/). Wardline, its customers, integrations, subprocessors and people are fictional.

Search documentation

Search the guides and every template's documentation