Data Introudction
How the JSON-driven data system works in Astro Docus — write once, reuse everywhere.
Section titled “”What Is the Data System?
Section titled “What Is the Data System?”Astro Docus is built on a simple principle: content lives in JSON, not in code. This is often called a non-hardcoded or JSON-driven approach.
Instead of writing text directly inside .astro components, you store it in .json files under src/data/. Components then import those JSON files and loop through them to render content.
This has three big advantages:
- Easy to update — change text without touching any code.
- Reusable — the same data can feed multiple pages or widgets.
- Safe — non-developers can edit JSON without breaking components.
Where the Data Lives
Section titled “Where the Data Lives”All JSON content lives in one place:
src/data/├── home.json├── configuration/│ ├── blog/│ │ └── blogpage.json│ └── home/│ └── homepage.json├── index_page/│ ├── cms.json│ ├── folder.json│ ├── getstart.json│ ├── hosting.json│ └── services.json├── plan/│ └── data.json└── pricing/ └── pricing.jsonEach folder or file serves a specific purpose. We will walk through them one at a time in separate pages under docs/data/.
How Data Flows Into Pages
Section titled “How Data Flows Into Pages”The flow is always the same:
JSON file → .astro widget → .mdx page → rendered websiteLet’s break it down with a real example.
1. The JSON file
Section titled “1. The JSON file”src/data/index_page/getstart.json contains a list of resources:
{ "resources": [ { "title": "Installation", "image": "/src/assets/install.svg", "text": "Set up Astro Docus on your machine.", "link": "/getstart/installation/" }, { "title": "Configuration", "image": "/src/assets/data.svg", "text": "Configure the main brain of the project.", "link": "/getstart/configuration/" } ]}2. The widget that reads it
Section titled “2. The widget that reads it”src/widget/index_page/getstart.astro imports the JSON and loops through it:
---import Data from '../../data/index_page/getstart.json';import { Picture } from 'astro:assets';---<div class="grid-container"> { Data.resources.map(({ title, image, text, link }) => ( <div class="grid-item"> <a href={link}> <Picture src={image} alt={title} formats={['avif', 'webp']} width="80" height="80" class="img-fluid" decoding="async" /> </a> <h3><a href={link}>{title}</a></h3> <p>{text}</p> </div> ))}</div>What is happening here:
import Data from '...'— loads the JSON file into a variable.Data.resources.map(...)— loops through every item in theresourcesarray.{ title, image, text, link }— destructures each item so we can use its fields directly.<Picture />— Astro’s built-in image component, optimized for performance.
Every field in the JSON maps directly to something rendered on the page.
3. The page that uses the widget
Section titled “3. The page that uses the widget”src/content/docs/getstart/index.mdx imports the widget and displays it:
---title: Get Startdescription: Get Started with Astro Docus templatetableOfContents: falsenext: false---
import Start from '../../../widget/index_page/getstart.astro';import '../../../styles/index_page.css';
## {frontmatter.description}
<Start />What is happening here:
import Start from '...'— loads the widget component.import '.../index_page.css'— loads the styles specific to this page.## {frontmatter.description}— renders the description from the frontmatter as an H2.<Start />— renders the widget, which renders the looped JSON data.
Result: a grid of cards, all generated from one JSON file.
Why This Pattern Matters
Section titled “Why This Pattern Matters”Before — hardcoded
Section titled “Before — hardcoded”Every card would have to be typed manually:
<div class="grid-item"> <a href="/getstart/installation/"> <img src="/src/assets/install.svg" alt="Installation" /> </a> <h3><a href="/getstart/installation/">Installation</a></h3> <p>Set up Astro Docus on your machine.</p></div>
<div class="grid-item"> <a href="/getstart/configuration/"> <img src="/src/assets/data.svg" alt="Configuration" /> </a> <h3><a href="/getstart/configuration/">Configuration</a></h3> <p>Configure the main brain of the project.</p></div>
<!-- ...and so on for every card -->Adding a new card means writing more HTML. Changing a link means hunting it down in multiple places.
After — JSON-driven
Section titled “After — JSON-driven”The same cards come from one array. To add a new card, you add one object to the JSON file:
{ "title": "New Page", "image": "/src/assets/new.svg", "text": "Description here.", "link": "/getstart/new-page/"}That’s it. The widget already knows how to render it.
The Concept of “Index Pages”
Section titled “The Concept of “Index Pages””The folder src/data/index_page/ deserves special attention.
Each JSON file in this folder maps to a documentation index page:
| JSON file | Powers the page |
|---|---|
index_page/getstart.json | /getstart/ |
index_page/cms.json | /cms/ |
index_page/hosting.json | /deploy-hosting/ |
index_page/services.json | /services/ |
index_page/folder.json | Used for folder documentation |
The pattern is:
- You write a page like
src/content/docs/getstart/index.mdx. - That page imports a widget like
src/widget/index_page/getstart.astro. - That widget reads
src/data/index_page/getstart.jsonand loops through the items.
So when you want to add a new card to the Get Started landing page, you only edit getstart.json — nothing else.
This is what we mean by automatic looping from data. The JSON drives the page.
Categories of Data
Section titled “Categories of Data”The src/data/ folder is divided into four conceptual groups. Each will get its own page in this documentation.
| Folder | Purpose |
|---|---|
configuration/ | Site-wide settings for blog and homepage |
index_page/ | Card grids for documentation landing pages |
plan/ | Plan comparison data |
pricing/ | Pricing table data |
Each of these will be explained in detail under docs/data/*.md as we go. This page is only the introduction — the why and the how.
Rules to Remember
Section titled “Rules to Remember”When working with the data system, keep these rules in mind:
- Never hardcode content that already exists in JSON. If a card, price, or menu item is in JSON, edit the JSON.
- Always keep the JSON shape consistent. If a widget expects
title,image,text,link, every object in the array must have those keys. - Import paths are relative. From
src/widget/index_page/getstart.astro, the JSON path is../../data/index_page/getstart.json. - JSON does not allow comments. If you want to leave notes, add a
"_note"field or document it in Markdown. - JSON does not allow trailing commas. One typo can break the whole build.
Quick Recap
Section titled “Quick Recap”JSON file → widget (.astro) → page (.mdx) → rendered site
Example:src/data/index_page/getstart.json → src/widget/index_page/getstart.astro → src/content/docs/getstart/index.mdx → https://yoursite.com/getstart/Once you understand this chain, you understand the entire data system of Astro Docus. Everything else is just variations of this pattern.
👉 Continue to the next page to learn about each JSON file in detail: docs/data/*.md