Web TippsUse custom web fonts in Google Sheets charts(08.09.2026 um 17:05 Uhr)
Web TippsIntroducing the new 1Password App for Google Chat(08.09.2026 um 18:02 Uhr)
Web TippsUse custom web fonts in Google Sheets charts(08.09.2026 um 17:05 Uhr)
Web TippsIntroducing the new 1Password App for Google Chat(08.09.2026 um 18:02 Uhr)

🔧 Programmierung 🕛 vor 2 Jahren 13 Min Lesezeit
0

Astro Markdoc: Readable, Declarative MDX Alternative

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




🚀 Using Markdoc with Astro



Markdown is a popular choice for authoring on content-rich websites. MDX offers extensions, providing access to React components, for example, within the content source. In this post, we see why you might reach for Astro Markdoc, instead of Markdown or MDX for your content site. We see how you can integrate Markdoc into an Astro documentation or content site, making full use of your favourite Astro features, such as underlying framework flexibility and Content Collections with front matter validation.






Why use Markdoc?



Markdoc, created at Stripe, is a declarative alternative, to MDX. Like MDX, it offers power and flexibility for customizing your content. Where Markdoc excels is in defining component attributes in a schema. This simplifies the tooling and makes writing content, rather than writing code, the focus. As well as reducing template complexity, Markdoc brings the benefits of validation and machine-readable markup.






What does Astro bring to the Party?



The Astro Markdoc integration abstracts away parts of the Markdoc configuration, letting you focus on business logic. Astro also offers flexibility. We will see a code block syntax highlighting example, adding sample code to a documentation site. Initially, we let Astro and Markdoc handle creating beautiful code samples for the site. Then, we see how we can take more control, adding our own Astro component to render the coding blocks using an alternative code highlighting package.



.






Markdoc Astro Integration



To start, run this command from your project folder to fire up the Astro Markdoc integration:




CODE
pnpm astro add markdoc






This will add the necessary packages to your project, and also update the config in astro.config.mjs. The updated Astro config file should look something like the example below. Remember to create a work-in-progress git feature branch before starting out here!




CODE
import { defineConfig } from 'astro/config';

import markdoc from '@astrojs/markdoc';

// https://astro.build/config
export default defineConfig({
integrations: [markdoc()],
});









Markdoc Config



Because we want to tap into code syntax highlighting in our generated content, we will add a markdoc.config.mjs file to the project root directory with the following content:




CODE
import { defineMarkdocConfig } from '@astrojs/markdoc/config';
import shiki from '@astrojs/markdoc/shiki';

export default defineMarkdocConfig({
extends: [
shiki({
theme: 'one-dark-pro',
}),
],
});






I opted for Shiki syntax highlighting here, and Astro Markdoc also supports in the Shiki GitHub repo. We will switch to starry-night highlighting later, so don’t invest too much time in finding the perfect theme yet!






🖋️ First Markdoc Post



Next, create a collection folder in your project. This has to be within the src/content folder. I went for a code collection, and added content for this collection to a new src/content/code directory. Note that Markdoc files normally have a .mdoc extension. Paste this markup into your new content source file (src/content/code/hello-world.mdoc, for example) to get started:




CODE
---
{
'title': 'Markdoc Introduction with 🚀 Astro and starry-night Code Highlighting',
'description': 'Astro Markdoc 📚 trying Stripe’s customizable, readable, declarative Markdown extension designed for 🖋️ creating documentation content.',
'date': '2023-11-02',
}
---

# {% $frontmatter.title %}

![Vincent Van Gogh’s Starry Night](/starry-night.jpg)

## Markdoc Features

Some principal Markdoc features are:

-
syntax for nodes is similar to Markdown so nothing to learn for creating headings, bold or italic text, links, images or lists;
- templates accept tags, which you can map to Astro components when you need more control; and
- front matter metadata is accessible within your Markdoc templates as variables, this might be a document title.

Unlike Markdown, Markdoc **does not accept HTML** within template files by default. The Astro configuration _does_ let you override this, though.

## 🖥️ Fenced Code Block Examples

### CSS

```css
.box {
border: solid 5px red;
}
```

### Elixir

```elixir
"hello" <> " world"
```

### JavaScript

```javascript
console_log('Hello world!');
```

### Python

```python
print('Hello world!')
```

### Rust

```rust
println!("Hello world!");
```






You will see this is not too different to Markdown, so I won’t go into too much detail here. If you are not familiar with Markdown, then the , which gives you more flexibility, using your Astro components in the markup, though we stick to the basics here.





Astro Content Collection Schema



Content Collection schema, is a way to define which fields we want in the front matter for each markup file. The schema is optional, though useful because Astro can let you know if you forget to add a field that is required by your schema. For that reason, I added a schema file at src/content/config.ts:




CODE
import { defineCollection, z } from 'astro:content';

const codeCollection = defineCollection({
type: 'content',
schema: () =>
z.object({
title: z.string(),
description: z.string().optional(),
date: z.string(),
}),
});

export const collections = {
code: codeCollection,
};






This also generates TypeScript types under the hood, for your content front matter metadata. Add another Markdoc file to your collection folder, just so you can try listing all content in the next section.






📝 Getting a List of Markdoc Content



Typically, each Markdoc file will be a separate page on your generated site, and you will need a list of all content pages, often on the home page. We create that list here.



To get all Markdoc files in the collection:




  1. import getCollection from astro:content;

  2. call getCollection, providing your collection name as an argument; and

  3. render the array generated.



We follow these steps in src/pages/index.astro, below:




CODE
---
import { getCollection } from 'astro:content';
import BaseLayout from '~layouts/BaseLayout.astro';

const { href: url } = Astro.url;
const codeEntries = await getCollection('code');
---

<BaseLayout
title="Markdoc Introduction Home Page"
description="Markdoc Introduction: see code examples and some basic Markdoc usage"
{url}
>
<main>
<h1>Markdoc Introduction Home Page</h1>
<p>Pages that use the Markdoc template:</p>
<ul>
{
codeEntries
.sort(
({ data: { date: dateA } }, { data: { date: dateB } }) =>
new Date(dateB).valueOf() - new Date(dateA).valueOf(),
)
.map(({ data: { title }, slug }) => (
<li>
<a href={`/${slug}`}>{title}</a>
</li>
))
}
</ul>
</main>
</BaseLayout>






Go to http://localhost:4321 in your browser to check the list of pages gets created, as expected.






🍪 Creating an Astro Markdoc Template



Astro template files generate site pages from a content collection. The path of the page is determined by the name you give your template and some metadata from the source.



Here, we want the generated page path to come from the slug of the Markdoc source (its path within the Content Collection). To make this work, we:




  1. name the template src/pages/[...slug].astro; and

  2. call getStaticPaths in the template file, returning params.slug to let Astro know how to map a Markdoc file to a page slug.



You can see this in action in src/pages/[...slug].astro, below:




CODE
---
import { getCollection } from 'astro:content';
import BaseLayout from '~layouts/BaseLayout.astro';

export async function getStaticPaths() {
const codeEntries = await getCollection('code');
return codeEntries.map((entry) => ({
params: { slug: entry.slug },
props: { entry },
}));
}

const { entry } = Astro.props;
const { href: url } = Astro.url;
const { data } = entry;
const { description, title } = data;
const { Content } = await entry.render();
---

<BaseLayout {url} {title} {description}>
<main>
<Content frontmatter={data} />
</main>
</BaseLayout>






Another interesting part is how we access Markdoc source front matter in the template. The bottom part of the file renders the content from the Markdoc source. You can see in line 22, we have a frontmatter prop on the Content element. This is important for making Markdoc variables within the source work. Remember, we had a variable in the source, which referenced the front matter title. We pass data into the frontmatter prop for that reason.



Moving up the file, you can see data comes from entry (line 15), which, itself, comes from Astro.props (line 13). We create the props object in the getStaticPaths function call (line 9). You will see a similar pattern for sourcing title and description, passed to the layout template in line 20.



Open up one of your content pages in a browser. Hopefully you see the code blocks with highlighting provided by the One Dark Theme, with Shiki. In the next section, we see how you can use starry-night to highlight the code blocks. We will generate a similar look to GitHub and also, automatically switch between light and dark syntax highlighting; based on the user theme dark/light preference.






✨ starry-night Syntax Highlighting



Next, we will see how you do not have to accept defaults for rendering nodes, and can instead use your own Astro components. You can see a full list of for more details on how it works. Some interesting points to note in the starry-night setup here are:




  • starry-night gives you a lot of control over adding accessible themes. In line 9, we imported @wooorm/starry-night/style/both which provides the CSS needed to show a light or dark theme depending on the user’s browser preference. Other options include light, dark, and then, more for more.

  • Calling starryNight.highlight generates Hypertext and



    . There are quite a few extensions you might consider including:




    • creating custom Astro components for rendering headings or other nodes;

    • adding Markdoc tags for increased flexibility; and

    • coding up your custom components in your favourite framework, using the Astro component as a gateway. Pass through the necessary props to the framework component.



    I do hope you have found this post useful! Let me know how you use what you have learned here. Also, let me know about any possible improvements to the content above.






    🙏🏽 Astro Markdoc: Feedback



    Have you found the post useful? Would you prefer to see posts on another topic instead? Get in touch with ideas for new posts. Also, if you like my writing style, get in touch if I can write some posts for your company site on a consultancy basis. Read on to find ways to get in touch, further below. If you want to support posts similar to this one and can spare a few dollars, euros or pounds, please on X, Element Matrix room. Also, see as well as with our latest projects.

    Vollständiger Original-Bericht
    Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
    ↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
3 Quellen
Use custom web fonts in Google Sheets charts
2 Quellen
Introducing the new 1Password App for Google Chat
1 Quelle
Context-aware access controls are available for Gemini Enterprise in the Admin console
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Astro Markdoc: Readable, Declarative MDX Alternative

Thematisch verwandte Begriffe: Astro, Markdoc, Readable, Declarative · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...