Topic page
Starter for a new Smol Gardens topic. A topic is two things: an entry in
docs/topics/_configs.ts and a folder next to it. Do both and the topic appears
on /topics — card, tag chips, sidebar entry, and detail route — with no edit
to any component or router.
1. Add the config entry
docs/topics/_configs.ts is the single source of truth. id must match the
folder name you create in step 2.
MyNewTopic: {
id: 'my-new-topic',
title: 'My New Topic',
description: 'One or two sentences. This is what shows on the topic card.',
tags: ['accountability', 'community'],
},
Reusing an existing tag adds the topic to that filter. A brand-new tag creates a
new filter chip automatically — ALL_TAGS is derived from the config.
2. Create the folder
docs/topics/my-new-topic/
├─ my-new-topic.mdx the page shell (below)
├─ _summary.mdx the content partial
└─ assets/
└─ my-new-topic.jpg the topic's image
Each topic owns its image in its own assets/ folder rather than sharing one
out of static/, so a topic folder is self-contained: copy it, rename it, swap
the picture. Webpack fingerprints imported assets, so they cache better than
files served straight from static/ too.
Files starting with _ are partials: Docusaurus does not give them their own
route, so they only ever render where you import them.
my-new-topic.mdx
The shell holds no copy of its own — it reads everything from the config, so the
card and the page can never drift apart. <Banner> renders the green header;
the three tabs match the project-page template in Figma.
---
id: topics-my-new-topic
title: ''
sidebar_label: My New Topic
hide_table_of_contents: true
---
import Banner from '@site/src/components/Banner'
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import configs from '../_configs.ts'
import Summary from './_summary.mdx'
<Banner
title={configs.MyNewTopic.title}
subtitle={configs.MyNewTopic.description}
/>
<Tabs>
<TabItem value="summary" label="Summary" default>
<Summary
title={configs.MyNewTopic.title}
description={configs.MyNewTopic.description}
tags={configs.MyNewTopic.tags}
/>
</TabItem>
<TabItem value="resources" label="Related Resources">
Links and reading for this topic.
</TabItem>
<TabItem value="projects" label="Projects">
Projects that put this topic into practice.
</TabItem>
</Tabs>
Keep title: '' in the frontmatter — <Banner> supplies the page heading, so a
frontmatter title would render a second one above it.
_summary.mdx
Receives whatever the shell passes as props. Write the long-form content here.
<ContentWithMedia> is the two-column row from the project-page template —
copy on the left, a circle-cropped image on the right. Leave src off and it
renders a dashed placeholder circle, so the layout holds before the artwork
exists. Because the crop is circular, pick artwork whose subject sits near the
centre; the corners are always clipped.
import ContentWithMedia from '@site/src/components/ContentWithMedia'
import topicImage from './assets/my-new-topic.jpg'
<ContentWithMedia src={topicImage} alt="Describe the image here">
## {props.title}
<p>{props.description}</p>
</ContentWithMedia>
## Why it matters
Your content.
Import the image rather than writing a path string — webpack then resolves and
fingerprints it, and the build fails loudly if the file is missing instead of
shipping a broken <img>.
Before the artwork exists, drop both props and pass a label instead. The component renders a dashed placeholder circle of the same size, so the layout is already correct:
<ContentWithMedia label="Topic image">
Blank lines around the Markdown inside the component are required — without them MDX treats the block as raw JSX and stops parsing the headings.
3. Add more partials as the page grows
The Related Resources and Projects tabs start as inline placeholder text. Once
either has real content, move it into its own partial and import it — same shape
as _summary.mdx:
import RelatedResources from './_related-resources.mdx'
<TabItem value="resources" label="Related Resources">
<RelatedResources />
</TabItem>
Design reference
The green header, tab row, and content block come from the PAGE - Project Page
template section in the Smol Gardens Figma (node 2213:2590). Key values are
already wired into src/css/custom.css as tokens — --color-bg-banner,
--color-content-default, --radius-medium — so use those rather than new
hex literals.
Checklist
- Entry added to
docs/topics/_configs.ts - Folder name matches the entry's
id -
sidebar_labelset (the shell'stitlestays empty —<Banner>supplies the heading) -
npm run buildpasses with no broken links