Recipes
This is a collection of Astro Content use cases, which are real world examples
extracted from this current website.
Create navigation sidebars for pages and headings sections
👈 Here is a walkthrough for creating those handy navigation helpers you can see
on both sides of the current page. 👉
This will demonstrate how Astro Content think about declarative
content modeling until its final usage, in your templates,
where the contextual, imperative logic is done.
Define an entity schema for your pages
Entity will be named "docs " with entry name "page ".
We will defined two front matter properties for the main.md
file,
title
and order
:
Create page entries
For example for one named "install ", with the previously defined front matter:
From: 📄 /docs/content/docs/install/main.md
---
title : Installation
order : 2
---
## Method 1: Add to Astro project with _CLI_
With `yarn` , `npm` or `pnpm` , run this in your **existing** Astro project:
```sh
# If you want a fresh start ——v
# pnpm create astro && cd ./my-astro-site
pnpm astro add astro-content
pnpm content setup
(Truncated…)
Will all that set, Astro Content will stream these typings for you in the background:
type Docs = {
cli ?: Page | undefined ;
conventions ?: Page | undefined ;
development ?: Page | undefined ;
... 7 more ...;
workInProgress ?: Page | undefined ;
}
interface Page {
main : MarkdownFile & {
frontmatter ?: {
title ?: string ;
order ?: number ;
[ k : string ] : unknown ;
};
};
}
Create the navigation component
Before we import our sidebar widgets in our pages, let's create an Astro component
for this task.
It will show its passed property, either pages or current page headings , as lists.
From: 📄 /docs/src/components/TreeNavigation.astro
---
import { type MarkdownHeading } from 'astro' ;
/* ·········································································· */
import { type Docs } from '/content' ;
import { Link } from 'astro-link' ;
import './TreeNavigation.scss' ;
/* —————————————————————————————————————————————————————————————————————————— */
interface Props {
pages ?: Docs ;
currentPage ?: string ;
headings ?: MarkdownHeading [];
}
const { pages , headings , currentPage } = Astro.props as Props ;
---
< nav class = "component-tree-navigation" >
< ul >
{
pages
? Object. entries (pages)
?. sort (([, prev ], [, cur ]) =>
(prev?.main?.frontmatter?.order || 0 ) <
(cur?.main?.frontmatter?.order || 1 )
? - 1
: 1 ,
)
. map (([ key , page ]) => (
< li >
< Link
class : list ={ [ 'unstyled' , currentPage === key && 'current' ] }
href ={ `docs/${ key }` }
>
{ page?.main?.frontmatter?.title }
</ Link >
</ li >
))
: headings?. map (( heading ) => (
< li >
< Link class = "unstyled" href ={ `#${ heading . slug }` } >
{ heading.text }
</ Link >
</ li >
))
}
</ ul >
</ nav >
Import the component in an Astro page
We can now import our sidebar widgets like this:
From: 📄 /docs/src/pages/docs/[page].astro
---
import { get } from '/content' ;
/* ·········································································· */
import Layout from '../../layouts/Default.astro' ;
import DocPage from '../../modules/DocPage.astro' ;
/* —————————————————————————————————————————————————————————————————————————— */
export async function getStaticPaths () {
const files = await get (Astro. glob ( '/content/docs/**/*.{md,mdx,yaml}' ));
return (
files.docs &&
Object. entries (files.docs). map (([ key ]) => ({ params: { page: key } }))
);
}
/* —————————————————————————————————————————————————————————————————————————— */
const content = await get (Astro. glob ( '/content/**/*.{md,mdx,yaml}' ), {
// NOTE: Ignore this. Used for collecting + building Web GUI static data.
editMode: import . meta .env. PROD ,
});
---
< Layout >
< DocPage docs = { content.docs } />
</ Layout >
From: 📄 /docs/src/modules/DocPage.astro
---
import { type Docs, type DocSectionEntryNames } from '/content' ;
/* ·········································································· */
import { Link } from 'astro-link' ;
import TreeNavigation from '../components/TreeNavigation.astro' ;
import PrevNextNavigation from '../components/PrevNextNavigation.astro' ;
import './DocPage.scss' ;
/* —————————————————————————————————————————————————————————————————————————— */
const { docs } = Astro.props as { docs : Docs };
const { page } = Astro.params as unknown as { page : DocSectionEntryNames };
/* ·········································································· */
const Main = docs?.[page]?.main?.Content;
---
< main class = "module-doc-page" >
< div class = "navigations" >
< div >
< h2 >Sections</ h2 >
< TreeNavigation pages = { docs } currentPage = { page } />
</ div >
< div class = "this-page" >
< h2 >On this page</ h2 >
< TreeNavigation headings = { docs?.[page]?.main?. getHeadings () } />
</ div >
</ div >
< article class = "article-body" >
{ Main && < Main components ={ { a: Link } } /> }
< PrevNextNavigation pages = { docs } currentPage = { page } />
</ article >
</ main >
⬅︎ Import
Reports ➡︎