1<!DOCTYPE html><html lang="en"> <head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"> <title>Astro Data Contract & JSON IR Generator â Frontmatter Core</title><meta name="description" content="Frontmatter Core scans a constrained Astro project and extracts a stable JSON intermediate representation â pages, routes, props and datasets. MIT licensed. Not a CMS."><link rel="canonical" href="https://www.frontmatter.tech/core/"><meta name="robots" content="index,follow"><meta property="og:type" content="website"><meta property="og:title" content="Astro Data Contract & JSON IR Generator â Frontmatter Core"><meta property="og:description" content="Frontmatter Core scans a constrained Astro project and extracts a stable JSON intermediate representation â pages, routes, props and datasets. MIT licensed. Not a CMS."><meta property="og:url" content="https://www.frontmatter.tech/core/"><meta property="og:image" content="https://www.frontmatter.tech/images/og/frontmatter-core-og.png">
1<meta property="og:image:alt" content="Frontmatter Core â Astro data contract and JSON IR"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="Astro Data Contract & JSON IR Generator â Frontmatter Core"><meta name="twitter:description" content="Frontmatter Core scans a constrained Astro project and extracts a stable JSON intermediate representation â pages, routes, props and datasets. MIT licensed. Not a CMS."><meta property="og:logo" content="https://www.frontmatter.tech/images/frontmatter-logo-1024.png"><meta name="theme-color" content="#f5f5f4"><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png"><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png"><link rel="icon" type="image/png" sizes="96x96" href="/favicon-96.png"><link rel="icon" type="image/png" sizes="192x192" href="/icon-192.png"><link rel="icon" type="image/png" sizes="512x512" href="/icon-512.png"><link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon-180.png"><link rel="preload" href="/fonts/InterVariable-Italic.woff2" as="font" type="font/woff2" crossorigin><link rel="preload" href="/fonts/InterVariable.woff2" as="font" type="font/woff2" crossorigin><meta name="twitter:image" content="https://www.frontmatter.tech/images/og/frontmatter-core-og.png">
1<script type="application/ld+json">{"@context":"https://schema.org","@type":"SoftwareApplication","name":"Frontmatter Core","url":"https://www.frontmatter.tech/core/","description":"Frontmatter Core scans a constrained Astro project and extracts a stable JSON intermediate representation â pages, routes, props and datasets. MIT licensed. Not a CMS.","applicationCategory":"DeveloperApplication","operatingSystem":"macOS, Linux, Windows","offers":{"@type":"Offer","price":"0","priceCurrency":"USD"},"author":{"@type":"Person","name":"Alexandre Desane"},"license":"https://opensource.org/licenses/MIT"}</script>
1
1<script src="https://cdn.jsdelivr.net/npm/@polar-sh/[email protected]/dist/embed.global.js" defer data-auto-init></script>
1<script>(function(){const apiKey = "phc_A3wkSkjTaCxwhRMPQQmP8vzVr9CHx5edVdxk3YBJqxDp"; 2const apiHost = "https://us.i.posthog.com"; 3 4 !function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags getFeatureFlag getFeatureFlagPayload reloadFeatureFlags group updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures getActiveMatchingSurveys getSurveys getNextSurveyStep onSessionId".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]); 5 posthog.init(apiKey || '', { 6 api_host: apiHost || '', 7 defaults: '2026-01-30', 8 cookieless_mode: 'always' 9 }); 10})();</script>
10<link rel="stylesheet" href="/_astro/SEO.CI2zskwz.css">
10<script type="module" src="/_astro/page.CDGqskMv.js"></script>
10</head> <body> <div> <header class="top"> <a class="brand" href="/" aria-label="Frontmatter home"> <span class="dot" aria-hidden="true"></span> <span>Frontmatter</span> </a> <nav class="nav" aria-label="Primary"> <a class="navlink" href="/core/" aria-current="page">Core</a> <a class="navlink" href="/solo/">Solo</a> <a class="navlink" href="/studio/">Studio</a> <a class="navlink" href="/guides/">Guides</a> <a class="navlink" href="/docs/">Docs</a> <a class="navlink" href="/about/">About</a> </nav> <button class="nav-burger" id="nav-burger" aria-label="Toggle menu" aria-expanded="false" aria-controls="nav-mobile"> <span class="bar"></span> <span class="bar"></span> <span class="bar"></span> </button> </header> <div class="nav-mobile" id="nav-mobile" aria-hidden="true"> <a class="nav-mobile__link" href="/core/">Core</a> <a class="nav-mobile__link" href="/solo/">Solo</a> <a class="nav-mobile__link" href="/studio/">Studio</a> <a class="nav-mobile__link" href="/guides/">Guides</a> <a class="nav-mobile__link" href="/docs/">Docs</a> <a class="nav-mobile__link" href="/about/">About</a> </div>
10<script type="module">const i=document.getElementById("nav-burger"),e=document.getElementById("nav-mobile");i?.addEventListener("click",()=>{const t=i.getAttribute("aria-expanded")==="true";i.setAttribute("aria-expanded",String(!t)),e?.classList.toggle("is-open",!t),e?.setAttribute("aria-hidden",String(t))});e?.querySelectorAll("a").forEach(t=>t.addEventListener("click",()=>{i?.setAttribute("aria-expanded","false"),e.classList.remove("is-open"),e.setAttribute("aria-hidden","true")}));window.addEventListener("resize",()=>{window.innerWidth>860&&(i?.setAttribute("aria-expanded","false"),e?.classList.remove("is-open"),e?.setAttribute("aria-hidden","true"))});</script>
10 <main class="container"> <div class="hero"> <section class="hero-wrapper"> <p class="hero-eyebrow">Frontmatter Core · MIT</p> <h1 class="logo logo--sentence">Extract a stable data contract from Astro.</h1> <p class="subtitle subtitle--core">Core scans Astro, Markdown and YAML and writes a typed JSON intermediate representation. Solo and Studio consume that IR. Core is not a CMS.</p> <p class="bridge">Build-time only. No runtime. No lock-in.</p> <div class="cta cta--core"> <a href="https://github.com/withfrontmatter/frontmatter-core" class="btn primary" target="_blank" rel="noopener" data-github-cta="repo">View on GitHub</a> <a href="https://github.com/withfrontmatter/frontmatter-core/blob/main/README.md" class="btn" target="_blank" rel="noopener" data-github-cta="readme">README</a> </div> </section> </div> <div class="grid flow"> <section class="block"> <h3>Input</h3> <ul> <li>.astro pages and components</li> <li>.md content files</li> <li>.yaml datasets</li> </ul> </section> <div class="chev" aria-hidden="true"></div> <section class="block"> <h3>Core scanner</h3> <ul class="simple-ul"> <li>Reads the project tree</li> <li>Extracts routes, props, fields</li> <li>Writes a typed JSON IR</li> </ul> </section> <div class="chev" aria-hidden="true"></div> <section class="block"> <h3>Output</h3> <ul> <li>JSON IR</li> <li>Pages, datasets, routes</li> <li>Stable contract for later tools</li> </ul> </section> </div> <section class="block ghost small"> <h2>What the IR contains</h2> <p>The IR is structure, not rendered HTML and not an admin UI. Component props, pages, datasets and routes are represented as data:</p> <pre><code>{ 11 "pages": [ 12 { 13 "route": "/", 14 "layout": "Base", 15 "fields": ["title", "subtitle"] 16 } 17 ], 18 "components": [ 19 { 20 "name": "Hero", 21 "props": ["headline", "sub"] 22 } 23 ], 24 "datasets": ["works", "posts"] 25}</code></pre> </section> <section class="yes-no-list yes-no-list--no"> <p class="yes-no-list__title">What Core does not do</p> <ul> <li>it is not a CMS or visual editor</li> <li>it does not generate Twig, PHP or Grav files</li> <li>it does not create editable content models in a backoffice</li> <li>it does not fetch, store or publish content</li> <li>it adds no runtime to your site</li> </ul> </section> <section class="positioning"> <p><strong>Solo consumes the IR.</strong></p> <p>Frontmatter Solo reads the same intermediate representation and prints Twig or plain PHP templates plus <code class="code">INTEGRATION.md</code>. Core stops at the contract. Solo starts at generation.</p> <p><a href="/solo/">See Frontmatter Solo</a></p> </section> <section class="positioning"> <p><strong>Studio builds on the pipeline.</strong></p> <p>Studio is coming soon. It is planned to sit on Core and Solo to produce a Grav theme, blueprints and an editable data layer. Studio is not released and is not a generic headless CMS.</p> <p><a href="/studio/">Studio waitlist</a></p> </section> <section class="block small soft"> <h3><strong>Open by design.</strong></h3> <p>
25Frontmatter Core is MIT licensed. You can read it, fork it, and build other tools on the same IR. Paid products stay outside the core.</p> <p> <a href="https://github.com/withfrontmatter/frontmatter-core" class="btn primary" style="margin-top:16px;" target="_blank" rel="noopener" data-github-cta="repo-footer">GitHub · MIT</a> </p> </section> </main> </div> <footer class="site-footer"> <div class="site-footer__inner"> <div class="site-footer__brand"> <a href="/" class="site-footer__logo"> <span class="dot" aria-hidden="true"></span> <span>Frontmatter</span> </a> <p class="site-footer__tagline"> 26Frontend-to-backend tools for Astro developers.<br> 27No rewrite. No runtime. No lock-in. 28</p> </div> <div class="site-footer__cols"> <nav class="site-footer__col" aria-label="Products"> <p class="site-footer__col-title">Products</p> <a class="site-footer__link" href="/core/">Core <span class="site-footer__badge">Free</span></a> <a class="site-footer__link" href="/solo/">Solo <span class="site-footer__badge site-footer__badge--paid">$49</span></a> <a class="site-footer__link" href="/solo/twig/">Solo for Twig</a> <a class="site-footer__link" href="/solo/php/">Solo for PHP</a> <a class="site-footer__link" href="/solo/symfony/">Solo for Symfony</a> <a class="site-footer__link" href="/solo/wordpress/">Solo for WordPress</a> <a class="site-footer__link" href="/studio/">Studio · Grav CMS <span class="site-footer__badge">Soon</span></a> </nav> <nav class="site-footer__col" aria-label="Guides"> <p class="site-footer__col-title">Guides</p> <a class="site-footer__link" href="/guides/">Guide hub</a> <a class="site-footer__link" href="/blog/">All notes</a> <a class="site-footer__link" href="/blog/astro-backend-handoff/">Frontend to backend handoff</a> <a class="site-footer__link" href="/blog/astro-twig-handoff/">Astro to Twig templates</a> <a class="site-footer__link" href="/blog/astro-symfony-handoff/">Astro to Symfony</a> <a class="site-footer__link" href="/blog/astro-wordpress-handoff/">Astro to WordPress PHP</a> <a class="site-footer__link" href="/blog/cms-content-modeling/">CMS architecture</a> </nav> <nav class="site-footer__col" aria-label="Docs"> <p class="site-footer__col-title">Docs</p> <a class="site-footer__link" href="/docs/">Overview</a> <a class="site-footer__link" href="/docs/getting-started/">Getting started</a> <a class="site-footer__link" href="/docs/contract/">Solo contract</a> <a class="site-footer__link" href="/docs/data-contract/">Data contract</a> <a class="site-footer__link" href="/docs/errors/">Error codes</a> <a class="site-footer__link" href="/docs/solo-check/">solo-check</a> </nav> <nav class="site-footer__col" aria-label="More"> <p class="site-footer__col-title">More</p> <a class="site-footer__link" href="/about/">About</a> <a class="site-footer__link" href="https://github.com/withfrontmatter" target="_blank" rel="noopener">GitHub</a> <a class="site-footer__link" href="/blog/rss.xml">RSS</a> <a class="site-footer__link" href="/sitemap-index.xml">Sitemap</a> <a class="site-footer__link" href="mailto:[email protected]">[email protected]</a> <a class="site-footer__link" href="https://alxdsn.fr" target="_blank" rel="noopener">Made by Alexandre Desane</a> </nav> <nav class="site-footer__col" aria-label="Legal"> <p class="site-footer__col-title">Legal</p> <a class="site-footer__link" href="/legal/privacy/">Privacy Policy</a> <a class="site-footer__link" href="/legal/terms/">Terms of Use</a> <a class="site-footer__link" href="/legal/refund/">Refund Policy</a> </nav> </div> </div> <div class="site-footer__bottom"> <span>© 2026 Frontmatter</span> <span>·</span> <span>Provided as-is. Support is best-effort.</span> </div> </footer> </body></html>
28<script> 29 document.querySelectorAll('[data-github-cta]').forEach(function(el) { 30 el.addEventListener('click', function() { 31 window.posthog?.capture('github_clicked', { 32 cta: el.getAttribute('data-github-cta'), 33 }); 34 }); 35 }); 36</script>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.