Navigation
The shell around the pages comes from the content.
Top navigation
Each top-level folder with an index page is a section, linked from the top navigation by its index page's title, in navigation order. The nav option adds links after the sections. A link to the page being read, or to a section holding it, is marked current.
Logo and icon
public/logo.svg is the logo, public/logo-dark.svg replaces it in the dark theme, and public/favicon.svg is the site icon.
Badge
A site with several versions shows the selected version's label beside the title.
Footer
_footer.md in a version's content directory is that version's footer. MarkupKit routes no file whose name starts with _, so the footer has no URL of its own:
Each heading starts a column, and each item in the list below it is a link. A paragraph after the lists is the copyright line. Anything else in the file fails the build with the file's path.
In the footer and the nav option, an href starting with / is a page path in the version being read, so /components/ opens that version's components. Other links stay as written.
Sidebars
Each top-level folder of a version is a section with its own sidebar, generated from the folder's pages; a page at the version's root shows every page. Folders, order and navigation front matter shape every sidebar.
Set sidebarNavigation: 'sections' in the site configuration to keep every category linked while listing pages only beneath the current category. A category link opens its index page, or its first page in navigation order if it has no index. Descendant pages form a flat list; there are no disclosure toggles. The links and the current category's list render before JavaScript and update when navigating to another category. The default tree mode uses the nested folders described below.
Group overviews
A route group can have an overview page while its child URLs stay flat. Give one non-index page inside the group navigation: overview in its front matter. Markupress uses that page as the category link and leaves it out of the sub-link list. Its title and content remain ordinary page content. Each group can have one overview; a folder's existing index already serves that role.
Folders
A folder is a page: its index page (index.md, or 01.index.md with a number prefix) is the folder's entry, at the folder's URL, and its front matter is the folder's metadata. A generated sidebar is MarkupKit's navigation tree, rendered by <mk-nav>: each folder below the section is a labelled group, a native <details> that collapses without JavaScript, nested as deep as the folders go, and its summary links to the index page.
---
title: Forms # labels the folder in the sidebar, breadcrumbs and pager
description: Form controls.
order: 3 # places the folder among its siblings like a 03. folder prefix
navigation: collapsed # starts the group closed, except on the pages inside it
---
# Forms
Form controls.Forms
Form controls.
A group starts open unless its index page says navigation: collapsed, and a group holding the current page always starts open. A folder without an index page is labelled by its name. To group pages under a label with no folder URL of its own, use an MarkupKit route group: a folder named in parentheses, such as 03.(Getting started)/, labels and orders its pages and adds no URL segment. Navigation, breadcrumbs and the previous/next links follow the same order.
Generated index
An index page with front matter and an empty body lists its folder: below its title as the heading, each page and folder directly inside it links to that page with its description, in navigation order. A route group's pages appear in its place, and hidden pages stay out. The list comes from MarkupKit's navigation tree, so it follows every page added, renamed or reordered.
Outline
A page with headings in its outline range (h2 and h3 by default) shows them in an "On this page" outline beside the content on wide screens. The links are plain fragment links. A small controller (markupress/controllers/outline.js, also exported) marks the heading being read with aria-current="location", using an IntersectionObserver; without JavaScript only that marking is missing.
Narrow screens
Below 769px the sidebar is a drawer: a native popover, closed until the Navigation button opens it, and it opens without JavaScript. Escape or a tap outside closes it, and following a link in it closes it.
Not found
A 404.md in the default version's content directory is the site's not-found page (MarkupKit's not-found page, R7). It renders in the shell for every unmatched path, including those under /v/<id>/, with status 404 in dev and preview, and build writes it to 404.html. It is no page of its version, so it has no URL of its own and no sidebar entry.
Edit link and last updated
Each page in the shell ends with an "Edit this page" link and the date its file last changed, above the previous/next links.
Edit link
The editLink option is a URL ending in /, and each page's link is that URL followed by the page file's path in the project. For a site at examples/site/ in a GitHub repository:
{ "editLink": "https://github.com/threadlabs-studio/markupress/edit/main/examples/site/" }docs/01.guide/01.authoring.md links to …/edit/main/examples/site/docs/01.guide/01.authoring.md, and a snapshot's page to its file in versions/<id>/. A page's own editLink front matter takes its place, and editLink: false shows none.
Last updated
A page's date is the author date of the last commit that touched its file, as YYYY-MM-DD in a <time> element. It needs no configuration: one git log call reads the dates of every page when a build or development server starts. Outside a git checkout, or for a file with no commit yet, the page shows no date. A shallow clone dates every file by its oldest fetched commit, so a CI build that shows dates fetches the full history (fetch-depth: 0 in actions/checkout).