Markdown Plugin
Markdown Plugin
Designer Agent Kit — documentation written for AI agents, readable by humans.
The @jay-framework/markdown plugin renders markdown content as HTML in jay-html pages. It provides three headless components.
Components
markdown-pages — Directory to pages
Scans a directory of .md files and provides page data. Each file becomes a routable page.
<script
type="application/jay-headless"
plugin="@jay-framework/markdown"
contract="markdown-pages"
key="post"
>
contentDir: ./content
</script>
The component provides these ViewState fields (all slow phase):
{post.title}— title from frontmatter{post.content}— rendered HTML{post.description}— description from frontmatter{post.date}— ISO date string{post.tags}— array with{name}field (use with forEach){post.frontmatter}— full frontmatter as JSON string
SEO head tags (<title>, <meta description>, og:title, etc.) are injected automatically from frontmatter.
Images in markdown
Images referenced in markdown files () are handled automatically:
Default (zero-config): Images alongside .md files in the content directory are copied to the project's public/ folder and URLs are rewritten to serve them as static assets. No props needed.
CDN hosting (with mediaMap): For optimized delivery, provide a mediaMap prop pointing to a YAML file that maps filenames to CDN URLs:
<script type="application/jay-headless" ...>
contentDir: ./content
mediaMap: ./media-map.yaml
</script>
The mapping file supports srcset for responsive images:
# media-map.yaml — generated by an upload script
'diagram.png':
src: 'https://cdn.example.com/w_800/diagram.webp'
width: 800
height: 600
srcset:
- url: 'https://cdn.example.com/w_400/diagram.webp'
width: 400
- url: 'https://cdn.example.com/w_800/diagram.webp'
width: 800
- url: 'https://cdn.example.com/w_1200/diagram.webp'
width: 1200
Mapped images render with srcset, sizes, width, height, and loading="lazy". Unmapped images fall back to the default local serving. The mapping file is typically generated by an external upload script — not hand-written.
markdown-content — Static inline renderer
Renders a markdown string at build time. Use for static content embedded in a page.
<jay:markdown-content markdown="{myMarkdownField}">
<div class="md">{html}</div>
</jay:markdown-content>
markdown-live — Dynamic renderer
Renders markdown that can change at request time or on the client. Ships the parser to the browser.
<jay:markdown-live markdown="{dynamicContent}">
<div class="md">{html}</div>
</jay:markdown-live>
Markdown File Format
---
title: Getting Started
date: 2026-07-15
description: A guide to getting started
author: Jane Doe
tags: [tutorial, beginner]
---
# Getting Started
Your content here with **bold**, _italic_, and [links](https://example.com).
Frontmatter Fields
| Field | Purpose | Auto-injected as |
|---|---|---|
title |
Page title | <title>, og:title |
description |
SEO description | <meta description>, og:description |
date |
Publish date | article:published_time |
author |
Author name | <meta author> |
image |
Cover image | og:image |
canonical |
Canonical URL | <link canonical> |
Any other field (e.g., category: guides) becomes <meta name="category" content="guides">.
Code Highlighting
Code fences are highlighted with CSS classes. Supported languages: JavaScript/TypeScript, HTML, CSS, YAML, JSON, Bash, Python.
```typescript
const hello = 'world';
```
Output structure
<pre class="md-code">
<code class="language-typescript">
<span class="token keyword">const</span> hello = <span class="token string">'world'</span>;
</code>
</pre>
CSS classes
| Class | Element | Purpose |
|---|---|---|
.md-code |
<pre> |
Code block container |
.language-{lang} |
<code> |
Language identifier (e.g., .language-typescript) |
Token classes (inside <code>)
| Class | Colors in default theme | Used for |
|---|---|---|
.token.keyword |
#8b5cf6 (purple) |
const, function, if, return, import, def, class |
.token.string |
#059669 (green) |
'hello', "world", `template` |
.token.comment |
#94a3b8 (gray, italic) |
// comment, /* block */, # comment |
.token.number |
#d97706 (amber) |
42, 3.14, 16px |
.token.function |
#2563eb (blue) |
greet(, console.log( |
.token.operator |
#64748b (slate) |
=, +, =>, && |
.token.punctuation |
#94a3b8 (gray) |
{}, (), ;, , |
.token.tag |
#dc2626 (red) |
HTML tags: <div, </span |
.token.attribute |
#d97706 (amber) |
HTML attributes: class=, href= |
Mermaid Diagrams
Mermaid fences are rendered to SVG on the server (via beautiful-mermaid). On the client (markdown-live), they output as source text for optional client-side rendering.
<div class="md-mermaid"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 263.77 116.9" width="263.77" height="116.9">
<style>
svg {
/* Derived from --bg and --fg (overridable via --line, --accent, etc.) */
--_text: var(--fg);
--_text-sec: var(--muted, color-mix(in srgb, var(--fg) 60%, var(--bg)));
--_text-muted: var(--muted, color-mix(in srgb, var(--fg) 40%, var(--bg)));
--_text-faint: color-mix(in srgb, var(--fg) 25%, var(--bg));
--_line: var(--line, color-mix(in srgb, var(--fg) 50%, var(--bg)));
--_arrow: var(--accent, color-mix(in srgb, var(--fg) 85%, var(--bg)));
--_node-fill: var(--surface, color-mix(in srgb, var(--fg) 3%, var(--bg)));
--_node-stroke: var(--border, color-mix(in srgb, var(--fg) 20%, var(--bg)));
--_group-fill: var(--bg);
--_group-hdr: color-mix(in srgb, var(--fg) 5%, var(--bg));
--_inner-stroke: color-mix(in srgb, var(--fg) 12%, var(--bg));
--_key-badge: color-mix(in srgb, var(--fg) 10%, var(--bg));
}
</style>
<defs>
<marker id="arrowhead" markerWidth="8" markerHeight="5" refX="7" refY="2.5" orient="auto">
<polygon points="0 0, 8 2.5, 0 5" fill="var(--_arrow)" stroke="var(--_arrow)" stroke-width="0.75" stroke-linejoin="round" />
</marker>
<marker id="arrowhead-start" markerWidth="8" markerHeight="5" refX="1" refY="2.5" orient="auto-start-reverse">
<polygon points="8 0, 0 2.5, 8 5" fill="var(--_arrow)" stroke="var(--_arrow)" stroke-width="0.75" stroke-linejoin="round" />
</marker>
</defs>
<polyline class="edge" data-from="A" data-to="B" data-style="solid" data-arrow-start="false" data-arrow-end="true" points="110.108,58.45 158.108,58.45" fill="none" stroke="var(--_line)" stroke-width="1" marker-end="url(#arrowhead)" />
<g class="node" data-id="A" data-label="Start" data-shape="rectangle">
<rect x="40" y="40" width="70.108" height="36.900000000000006" rx="0" ry="0" fill="var(--_node-fill)" stroke="var(--_node-stroke)" stroke-width="0.75" />
<text x="75.054" y="58.45" text-anchor="middle" font-size="13" font-weight="500" fill="var(--_text)" dy="4.55">Start</text>
</g>
<g class="node" data-id="B" data-label="End" data-shape="rectangle">
<rect x="158.108" y="40" width="65.662" height="36.900000000000006" rx="0" ry="0" fill="var(--_node-fill)" stroke="var(--_node-stroke)" stroke-width="0.75" />
<text x="190.93900000000002" y="58.45" text-anchor="middle" font-size="13" font-weight="500" fill="var(--_text)" dy="4.55">End</text>
</g>
</svg></div>
Output structure
Server (markdown-pages, markdown-content):
<div class="md-mermaid">
<svg>...</svg>
</div>
Client fallback (markdown-live):
<div class="md-mermaid">
<pre class="md-mermaid-source">
graph LR
A[Start] --> B[End]</pre
>
</div>
CSS classes
| Class | Element | Purpose |
|---|---|---|
.md-mermaid |
<div> |
Mermaid diagram container (centered, with margin) |
.md-mermaid svg |
<svg> |
The rendered SVG diagram (max-width: 100%) |
.md-mermaid-source |
<pre> |
Raw mermaid source (client fallback only) |
.md-mermaid-error |
<pre> |
Error message when rendering fails |
Theming mermaid diagrams
SVG diagrams use CSS custom properties for all colors. Set --bg and --fg on .md-mermaid svg to control the color scheme:
.md-mermaid svg {
--bg: var(--color-surface);
--fg: var(--color-text);
font-family: inherit;
}
The SVG internally derives all colors from --bg and --fg:
| Variable | Derived from | Controls |
|---|---|---|
--_text |
--fg |
Node labels, actor names |
--_line |
--fg 50% + --bg |
Edges, lifelines |
--_arrow |
--fg 85% + --bg |
Arrow heads |
--_node-fill |
--fg 3% + --bg |
Node backgrounds |
--_node-stroke |
--fg 20% + --bg |
Node borders |
--_group-fill |
--bg |
Subgraph backgrounds |
Override individual variables for fine control:
.md-mermaid svg {
--bg: #0a0a0a;
--fg: #e4e4e7;
--accent: #8b5cf6; /* arrow color */
--surface: #1a1a2e; /* node fill */
--border: #333; /* node stroke */
}
Theme CSS
Import a theme in your project CSS:
@import '@jay-framework/markdown/themes/markdown-blog.css';
Available themes:
markdown-default.css— clean, neutralmarkdown-docs.css— documentation style (narrower, tighter)markdown-blog.css— blog style (wider body text, generous spacing)
Override via CSS custom properties:
.md {
--md-color-link: var(--accent);
--md-color-heading: var(--text-primary);
--md-color-code-bg: var(--bg-secondary);
}
About this document
This page is part of the Jay Stack Agent Kit — documentation generated from the framework source and written primarily for AI agents. The language and structure are optimized for machine consumption — expect precise, specification-style prose rather than narrative documentation. Learn more about the Agent Kit →