Skip to content

Docs Index Page

Once you finish writing your documentation, you may want to make your index pages (the landing page of each docs folder) more visually appealing.

Instead of a plain list of links, you can render a grid of cards, each with an icon, a title, a short description, and a link.

This is entirely optional. If your docs work fine without it, you can skip this page entirely. But if you want a polished, professional look for folders like /getstart/, /cms/, or /deploy-hosting/, this is how to do it.


The pattern is the same as everywhere else in Astro Docus:

JSON file → index.mdx → card grid

You create one JSON file per docs folder, name it to match the folder, and then render it inside that folder’s index.mdx.

Docs folderJSON file
src/content/docs/getstart/src/data/index_page/getstart.json
src/content/docs/cms/src/data/index_page/cms.json
src/content/docs/deploy-hosting/src/data/index_page/hosting.json
src/content/docs/services/src/data/index_page/services.json

The name must match. If your docs folder is getstart, your JSON file must be getstart.json.


Inside src/data/index_page/, create a new file named after your docs folder.

Example — src/data/index_page/getstart.json:

{
"resources": [
{
"title": "Download Source",
"image": "/src/assets/download.svg",
"text": "Get source code from Gumroad after purchase. Unlimited sites.",
"link": "/getstart/download/"
},
{
"title": "Installation",
"image": "/src/assets/ins.svg",
"text": "Run npm install and npm run dev. Works on localhost:4321.",
"link": "/getstart/installation/"
},
{
"title": "Configuration",
"image": "/src/assets/cof.svg",
"text": "Edit astro.config.mjs for title, logo and sidebar.",
"link": "/getstart/configuration/"
}
]
}
FieldPurpose
resourcesThe array name — must be exactly resources
titleCard title, also used as image alt text
imagePath to the icon or image (/src/assets/...)
textShort description shown under the title
linkWhere the card links to

Every object in the array must have all four keys. Missing keys cause the card to render incorrectly.

Use small SVG icons from src/assets/ for best results. Recommended size: 80×80 pixels.

Common icons available in the template:

  • download.svg
  • ins.svg (installation)
  • cof.svg (configuration)
  • data.svg
  • deploy.svg
  • article.svg
  • blo.svg (blog)
  • wd.svg (widget)
  • gits.svg (GitHub)
  • hiost.svg (hosting)

You can also add your own icons to src/assets/ and reference them.


Open the index.mdx for the folder you want to enhance. For example, src/content/docs/getstart/index.mdx.

Replace its content with:

---
title: Get Start
description: Get Started with Astro Docus template
tableOfContents: false
next: false
---
import Data from '../../../data/index_page/getstart.json';
import '../../../styles/index_page.css';
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>

Frontmatter:

title: Get Start
description: Get Started with Astro Docus template
tableOfContents: false
next: false
  • title — page title
  • description — meta description
  • tableOfContents: false — hide the right-side TOC (card grids don’t need it)
  • next: false — hide the “Next page” link at the bottom

Imports:

import Data from '../../../data/index_page/getstart.json';
import '../../../styles/index_page.css';
import { Picture } from 'astro:assets';
  • Data — the JSON file you created
  • index_page.css — the stylesheet that styles the grid
  • Picture — Astro’s image optimization component

The grid:

<div class="grid-container">
{ Data.resources.map(({ title, image, text, link }) => (
...
))}
</div>
  • .grid-container — a CSS grid defined in index_page.css
  • Data.resources.map(...) — loops through every card
  • { title, image, text, link } — destructures each card’s fields
  • Each card renders as <div class="grid-item">

The card grid relies on classes defined in src/styles/index_page.css:

  • .grid-container — the outer grid
  • .grid-item — each individual card

If the cards look unstyled (all stacked vertically, no spacing), the CSS import is missing. Make sure this line is present:

import '../../../styles/index_page.css';

You can also add your own styles by editing src/styles/index_page.css.


For reference, index_page.css typically contains something like:

.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 1.5rem;
margin: 2rem 0;
}
.grid-item {
padding: 1.5rem;
border: 1px solid var(--bs-border-color);
border-radius: 12px;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.grid-item:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
}
.grid-item h3 {
font-size: 1.1rem;
margin-top: 1rem;
}
.grid-item p {
font-size: 0.95rem;
opacity: 0.8;
}

You can adjust minmax(220px, 1fr) to control how many cards fit per row. For example:

  • minmax(180px, 1fr) → more, smaller cards per row
  • minmax(280px, 1fr) → fewer, larger cards

{
"resources": [
{
"title": "Download",
"image": "/src/assets/download.svg",
"text": "Get the source code from Gumroad after purchase.",
"link": "/getstart/download/"
},
{
"title": "Installation",
"image": "/src/assets/ins.svg",
"text": "Install dependencies and run locally on port 4321.",
"link": "/getstart/installation/"
},
{
"title": "Configuration",
"image": "/src/assets/cof.svg",
"text": "Edit astro.config.mjs for title, logo and sidebar.",
"link": "/getstart/configuration/"
},
{
"title": "Folder Structure",
"image": "/src/assets/geal.svg",
"text": "Overview of src, data, content and pages folders.",
"link": "/getstart/structure/"
}
]
}
---
title: Get Start
description: Get Started with Astro Docus template
tableOfContents: false
next: false
---
import Data from '../../../data/index_page/getstart.json';
import '../../../styles/index_page.css';
import { Picture } from 'astro:assets';
## {frontmatter.description}
<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>

Result: /getstart/ shows a grid of four cards.


  1. Open your JSON file.
  2. Add a new object to the resources array with all four fields.
  3. Save.
  1. Delete the object from the array.
  2. Save.
  1. Cut and paste objects within the array.
  2. Save. The order in the array is the order on the page.

Reusing One JSON File for Multiple Folders

Section titled “Reusing One JSON File for Multiple Folders”

You can point multiple index.mdx files at the same JSON file if you want identical card layouts:

import Data from '../../../data/index_page/getstart.json';

Just change the path. This is useful for template examples or shared content.

However, the convention in Astro Docus is one JSON file per folder, named after the folder. This keeps things predictable.


Use index page cards when:

  • Your docs folder has multiple sub-pages and you want a visual overview.
  • You want the index to feel like a hub rather than a list.
  • You have icons for each sub-page.

Skip this when:

  • The folder has only one or two pages.
  • Your docs are linear and best shown as a list.
  • You don’t have matching icons.

  1. JSON filename must match the docs folder name. getstart/ → getstart.json.
  2. The array must be named resources. The map() call depends on it.
  3. Every card needs all four keys — title, image, text, link.
  4. Use /src/assets/... paths for images so Astro can optimize them.
  5. Import the CSS — without index_page.css, the grid looks broken.
  6. Set tableOfContents: false and next: false in frontmatter for a cleaner index.

src/data/index_page/getstart.json
│
▼
src/content/docs/getstart/index.mdx
│
▼
/getstart/ → grid of cards

Three steps:

  1. Create src/data/index_page/<folder>.json with a resources array.
  2. Import it in src/content/docs/<folder>/index.mdx.
  3. Loop with .map() inside a .grid-container.

Optional but powerful. When applied consistently, every docs folder becomes a polished, navigable hub.