diff --git a/docs/advanced/architecture.md b/docs/advanced/architecture.md
index 9e98483d9..4de02121d 100644
--- a/docs/advanced/architecture.md
+++ b/docs/advanced/architecture.md
@@ -89,3 +89,25 @@ Each community plugin repository contains:
- `package.json` — Declares dependencies on `@quartz-community/types` and `@quartz-community/utils`
The architecture and design of the plugin system was intentionally left pretty vague here as this is described in much more depth in the guide on [[making plugins|creating plugins]].
+
+## Page Frames
+
+Page frames control the inner HTML structure of each page. While the outer shell (``, `
`, ``, `#quartz-root`) is always the same (required for [[SPA Routing]]), the frame determines how layout slots are arranged inside the page.
+
+The frame system lives in `quartz/components/frames/` and consists of:
+
+- `types.ts` — Defines the `PageFrame` and `PageFrameProps` interfaces
+- `DefaultFrame.tsx` — Three-column layout (left sidebar, center, right sidebar, footer)
+- `FullWidthFrame.tsx` — No sidebars, single center column
+- `MinimalFrame.tsx` — No sidebars, no header/beforeBody, just content and footer
+- `index.ts` — Registry and `resolveFrame()` function
+
+The rendering pipeline in `quartz/components/renderPage.tsx` delegates to the resolved frame's `render()` function. Frame resolution happens in the `PageTypeDispatcher` emitter (`quartz/plugins/pageTypes/dispatcher.ts`) using this priority:
+
+1. YAML config: `layout.byPageType..template`
+2. Page type plugin: `frame` property
+3. Fallback: `"default"`
+
+The active frame name is set as a `data-frame` attribute on the `.page` element, enabling frame-specific CSS overrides in `quartz/styles/base.scss`.
+
+See [[layout#Page Frames]] for user-facing documentation and [[making plugins#Page Types]] for how to set frames in page type plugins.
diff --git a/docs/advanced/making plugins.md b/docs/advanced/making plugins.md
index d8bcfc5cb..8d546c20e 100644
--- a/docs/advanced/making plugins.md
+++ b/docs/advanced/making plugins.md
@@ -349,24 +349,30 @@ export const ContentPage: QuartzEmitterPlugin = () => {
}
```
-### Page Types
-
-Page types define how a category of pages is rendered. They are configured in the `pageTypes` array in `quartz.config.yaml`.
+Page types define how a category of pages is rendered. They are the primary way to add support for new file types or virtual pages in Quartz.
```ts
-export type QuartzPageTypePluginInstance = {
+export interface QuartzPageTypePluginInstance {
name: string
- pageType: string // e.g. "content", "folder", "tag"
- getQuartzComponents(ctx: BuildCtx): QuartzComponent[]
- emit(
- ctx: BuildCtx,
- content: ProcessedContent[],
- resources: StaticResources,
- layout: FullPageLayout,
- ): Promise | AsyncGenerator
+ priority?: number
+ fileExtensions?: string[]
+ match: PageMatcher
+ generate?: PageGenerator
+ layout: string
+ frame?: string
+ body: QuartzComponentConstructor
}
```
+- `name`: A unique identifier for this page type.
+- `priority`: Controls matching order when multiple page types could match a slug. Higher priority page types are checked first. Default: `0`.
+- `fileExtensions`: Array of file extensions this page type handles (e.g. `[".canvas"]`, `[".base"]`). Content files (`.md`) are handled by the default content page type.
+- `match`: A function that determines whether a given slug/file should be rendered by this page type.
+- `generate`: An optional function that produces virtual pages (pages not backed by files on disk, such as folder listings or tag indices).
+- `layout`: The layout configuration key (e.g. `"content"`, `"folder"`, `"tag"`). This determines which `byPageType` entry in `quartz.config.yaml` provides the layout overrides for this page type.
+- `frame`: The [[layout#Page Frames|page frame]] to use for this page type. Controls the overall HTML structure (e.g. `"default"`, `"full-width"`, `"minimal"`). If not set, defaults to `"default"`. Can be overridden per-page-type via `layout.byPageType..template` in `quartz.config.yaml`.
+- `body`: The Quartz component constructor that renders the page body content.
+
## Building and Testing
```shell
diff --git a/docs/configuration.md b/docs/configuration.md
index 420570c71..650851b49 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -99,7 +99,18 @@ Plugins are categorized by their type (transformer, filter, emitter, pageType) b
- [[tags/plugin/transformer|Transformers]] **map** over content (e.g. parsing frontmatter, generating a description)
- [[tags/plugin/filter|Filters]] **filter** content (e.g. filtering out drafts)
- [[tags/plugin/emitter|Emitters]] **reduce** over content (e.g. creating an RSS feed or pages that list all files with a specific tag)
-- **Page Types** define how different types of pages are rendered (content pages, folder listings, tag listings)
+- **Page Types** define how different types of pages are rendered (content pages, folder listings, tag listings). Each page type can use a different [[layout#Page Frames|page frame]] to control its overall HTML structure.
+
+The `layout.byPageType` section in `quartz.config.yaml` can also set a `template` field to override the page frame for a specific page type:
+
+```yaml title="quartz.config.yaml"
+layout:
+ byPageType:
+ canvas:
+ template: minimal # Override the page frame for canvas pages
+```
+
+See [[layout#Page Frames]] for details on available frames and how frame resolution works.
### Internal vs External Plugins
diff --git a/docs/layout.md b/docs/layout.md
index 293f3274a..78a781da8 100644
--- a/docs/layout.md
+++ b/docs/layout.md
@@ -7,7 +7,7 @@ Certain emitters may also output [HTML](https://developer.mozilla.org/en-US/docs
In v5, the layout is defined in `quartz.config.yaml` using a `defaults` + `byPageType` structure.
- `defaults` contains layout components shared across ALL page types (head, header, afterBody, footer).
-- `byPageType` contains per-page-type overrides (content, folder, tag, 404) for beforeBody, left, and right sections.
+- `byPageType` contains per-page-type overrides (content, folder, tag, 404) for beforeBody, left, right sections, and optionally a `template` to control the page's [[#Page Frames|page frame]].
Each page is composed of multiple different sections which contain `QuartzComponents`. The following code snippet lists all of the valid sections that you can add components to:
@@ -136,6 +136,47 @@ Community component plugins are installed via `npx quartz plugin add github:quar
You can also checkout the guide on [[creating components]] if you're interested in further customizing the behaviour of Quartz.
+### Page Frames
+
+Page frames control the overall HTML structure of a page — specifically, how the layout slots (sidebars, header, content, footer) are arranged inside the page shell. Different page types can use different frames to produce fundamentally different layouts.
+
+Quartz ships with three built-in frames:
+
+| Frame | Description | Used by |
+| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
+| `default` | Three-column layout with left sidebar, center content (header, beforeBody, content, afterBody), right sidebar, and footer. This is the standard Quartz layout. | ContentPage, FolderPage, TagPage, BasesPage |
+| `full-width` | No sidebars. Single center column spanning the full width with header, content, afterBody, and footer. | CanvasPage |
+| `minimal` | No sidebars, no header or beforeBody chrome. Only content and footer. | NotFoundPage (404) |
+
+#### How frames are resolved
+
+Each page type can declare a default frame in its plugin source code via the `frame` property. The resolution order is:
+
+1. **YAML config override**: `layout.byPageType..template` in `quartz.config.yaml`
+2. **Plugin declaration**: The `frame` property set in the page type plugin's source code
+3. **Fallback**: `"default"`
+
+For example, to override canvas pages to use the minimal frame:
+
+```yaml title="quartz.config.yaml"
+layout:
+ byPageType:
+ canvas:
+ template: minimal
+```
+
+#### Custom frames
+
+You can create custom frames by adding a new `.tsx` file in `quartz/components/frames/` that implements the `PageFrame` interface, then registering it in `quartz/components/frames/index.ts`. See the [[advanced/architecture|architecture overview]] for the full `PageFrame` interface.
+
+Frames are applied as a `data-frame` attribute on the `.page` element, which you can target in CSS:
+
+```scss
+.page[data-frame="my-frame"] > #quartz-body {
+ /* custom grid layout */
+}
+```
+
### Layout breakpoints
Quartz has different layouts depending on the width the screen viewing the website.
diff --git a/docs/plugins/BasesPage.md b/docs/plugins/BasesPage.md
index dc8493b7f..e195fe524 100644
--- a/docs/plugins/BasesPage.md
+++ b/docs/plugins/BasesPage.md
@@ -5,7 +5,7 @@ tags:
- plugin/component
---
-This plugin provides support for [Obsidian Bases](https://obsidian.md/changelog/2025-04-15-desktop-v1.8.0/) (`.base` files) in Quartz. It reads `.base` files from your vault, resolves matching notes based on the query definition, and renders them as interactive database-like views with support for tables, lists, cards, and maps.
+This plugin provides support for [Obsidian Bases](https://obsidian.md/changelog/2025-04-15-desktop-v1.8.0/) (`.base` files) in Quartz. It reads `.base` files from your vault, resolves matching notes based on the query definition, and renders them as interactive database-like views with support for tables, lists, cards, and maps. It uses the `default` [[layout#Page Frames|page frame]] (three-column layout with sidebars).
> [!note]
> For information on how to add, remove or configure plugins, see the [[configuration#Plugins|Configuration]] page.
diff --git a/docs/plugins/CanvasPage.md b/docs/plugins/CanvasPage.md
index e393b0d5d..e9307ca3a 100644
--- a/docs/plugins/CanvasPage.md
+++ b/docs/plugins/CanvasPage.md
@@ -4,7 +4,7 @@ tags:
- plugin/pageType
---
-This plugin is a page type plugin that renders [JSON Canvas](https://jsoncanvas.org) (`.canvas`) files as interactive, pannable and zoomable canvas pages. It supports the full [JSON Canvas 1.0 spec](https://jsoncanvas.org/spec/1.0/), including text nodes with Markdown rendering, file nodes that link to other pages in your vault, link nodes for external URLs, and group nodes for visual organization. Edges between nodes are rendered as SVG paths with optional labels, arrow markers, and colors.
+This plugin is a page type plugin that renders [JSON Canvas](https://jsoncanvas.org) (`.canvas`) files as interactive, pannable and zoomable canvas pages. It uses the `full-width` [[layout#Page Frames|page frame]] (no sidebars, single column spanning the full width) to give the canvas maximum screen space. It supports the full [JSON Canvas 1.0 spec](https://jsoncanvas.org/spec/1.0/), including text nodes with Markdown rendering, file nodes that link to other pages in your vault, link nodes for external URLs, and group nodes for visual organization. Edges between nodes are rendered as SVG paths with optional labels, arrow markers, and colors.
> [!note]
> For information on how to add, remove or configure plugins, see the [[configuration#Plugins|Configuration]] page.
diff --git a/docs/plugins/ContentPage.md b/docs/plugins/ContentPage.md
index 0ff2d7d01..7e71d20ae 100644
--- a/docs/plugins/ContentPage.md
+++ b/docs/plugins/ContentPage.md
@@ -4,7 +4,7 @@ tags:
- plugin/pageType
---
-This plugin is a page type plugin for the Quartz framework. It generates the HTML pages for each piece of Markdown content. It emits the full-page [[layout]], including headers, footers, and body content, among others. It is now configured in the `pageTypes` section of `quartz.config.yaml`.
+This plugin is a page type plugin for the Quartz framework. It generates the HTML pages for each piece of Markdown content. It emits the full-page [[layout]], including headers, footers, and body content, among others. It uses the `default` [[layout#Page Frames|page frame]] (three-column layout with sidebars). It is now configured in the `pageTypes` section of `quartz.config.yaml`.
> [!note]
> For information on how to add, remove or configure plugins, see the [[configuration#Plugins|Configuration]] page.
diff --git a/docs/plugins/FolderPage.md b/docs/plugins/FolderPage.md
index 9763131c4..dda680047 100644
--- a/docs/plugins/FolderPage.md
+++ b/docs/plugins/FolderPage.md
@@ -4,7 +4,7 @@ tags:
- plugin/pageType
---
-This plugin is a page type plugin that generates index pages for folders, creating a listing page for each folder that contains multiple content files. See [[folder and tag listings]] for more information.
+This plugin is a page type plugin that generates index pages for folders, creating a listing page for each folder that contains multiple content files. It uses the `default` [[layout#Page Frames|page frame]] (three-column layout with sidebars). See [[folder and tag listings]] for more information.
Example: [[advanced/|Advanced]]
diff --git a/docs/plugins/NotFoundPage.md b/docs/plugins/NotFoundPage.md
index 7ce612572..1e0294083 100644
--- a/docs/plugins/NotFoundPage.md
+++ b/docs/plugins/NotFoundPage.md
@@ -4,7 +4,7 @@ tags:
- plugin/pageType
---
-This plugin emits a 404 (Not Found) page for broken or non-existent URLs.
+This plugin emits a 404 (Not Found) page for broken or non-existent URLs. It uses the `minimal` [[layout#Page Frames|page frame]] (no sidebars, no header or beforeBody chrome — only content and footer) to present a clean error page.
> [!note]
> For information on how to add, remove or configure plugins, see the [[configuration#Plugins|Configuration]] page.
@@ -14,5 +14,4 @@ This plugin has no configuration options.
## API
- Category: Page Type
-- Function name: `Plugin.PageTypes.NotFoundPageType()`.
-- Source: [`quartz/plugins/emitters/404.tsx`](https://github.com/jackyzha0/quartz/blob/v5/quartz/plugins/emitters/404.tsx).
+- Source: [`quartz/plugins/pageTypes/404.ts`](https://github.com/jackyzha0/quartz/blob/v5/quartz/plugins/pageTypes/404.ts)
diff --git a/docs/plugins/TagPage.md b/docs/plugins/TagPage.md
index 1cad85fb0..6560c23f6 100644
--- a/docs/plugins/TagPage.md
+++ b/docs/plugins/TagPage.md
@@ -4,7 +4,7 @@ tags:
- plugin/pageType
---
-This plugin is a page type plugin that emits dedicated pages for each tag used in the content. See [[folder and tag listings]] for more information.
+This plugin is a page type plugin that emits dedicated pages for each tag used in the content. It uses the `default` [[layout#Page Frames|page frame]] (three-column layout with sidebars). See [[folder and tag listings]] for more information.
> [!note]
> For information on how to add, remove or configure plugins, see the [[configuration#Plugins|Configuration]] page.