Shared content
Some passages belong on many pages: install steps, a note about a beta feature, a support link. Write such a passage once, in a file whose name starts with _, and show it wherever it belongs with <import-content>.
Share a passage
Put the passage in its own file:
content/
_install.mdx
guides/
getting-started.mdx
upgrade.mdx Install PureStack with `yarn add purestack`, then start the site with `yarn purestack serve --content ./content`. Then show it in each page, with a path relative to the page:
## Install
<import-content src="../_install.mdx"/> The page shows the passage as if you had written it there. Markdown and components work, and its headings join the page's table of contents.
How shared files work
- They are not pages. A file whose name, or the name of a folder above it, starts with
_is never published on its own, such as_install.mdxor_shared/beta-note.mdx. - They have no frontmatter. The page that shows a passage sets its title, template, and layout.
- Links work from the page. A link inside a passage resolves from the page that shows it. When pages in different folders show the passage, start its links at the site root, such as
/guides/styling/themes/. - They can import too. A shared file can show another shared file, or a file's code, with paths relative to the shared file itself.
- Inside a component, markup rules apply.
<import-content>works inside component markup too, such as aTabPane. There, the passage is read like anything else written inside a component: HTML, components, and code blocks work, but other Markdown, such as**bold**, lists, and[links](./page), stays as written. Write passages meant for components in HTML. - Edits show up. While
purestack serveruns, saving a shared file updates every page that shows it.
Share a header and footer
Headers and footers use directory inheritance rather than <import-content>. Add content/header.mdx to supply the site's header:
<TopBar tone="neutral" variant="surface" /> Add content/footer.mdx for its footer:
<SiteFooter copyright="Acme documentation" /> A page uses the nearest header and the nearest footer found by walking up its source folders. For example, content/guides/header.mdx replaces the root header for pages under guides, while those pages can still inherit the root footer. The two lookups are independent. .rmdx is also supported; keep only one header and one footer per directory across these extensions.
Links in these sections resolve from the header or footer file, unlike links in an imported passage, which resolve from the consuming page. Use a content-root script path when a shared section loads browser code, or set PageScript.sourceRelPath explicitly. Frontmatter layout.showFooter: false hides the footer on one page. Custom templates receive headerHtml and footerHtml and decide where to place them.
Choose a passage, component, or template
| Reuse requirement | Use |
|---|---|
| The same prose on several pages | An underscore-prefixed file and import-content |
| A shared header or footer for a section | header.mdx / footer.mdx in its directory |
| Markup with inputs or slots | A Regor component registered by a plugin |
| A different document shell | A page template |
| Source code shown verbatim | import-codeblock |
When something is wrong
The build stops and names the page and the tag:
Content import "./_instal.mdx" in "guides/upgrade.mdx" does not match any file. Most fixes are one of these:
- A typo or different capitals.
./_Install.mdxdoesn't find_install.mdx. - The file is not shared. Rename it so its name, or a folder above it, starts with
_. A page cannot be imported. - The file has frontmatter. Remove it; the page's frontmatter applies.
- Two files import each other. The message shows the chain, such as
guides/upgrade.mdx → _install.mdx → _requirements.mdx → _install.mdx.