plain.pages
Serve static pages, markdown, and assets from templates/pages directories.
Overview
The plain.pages package automatically discovers and serves static pages from templates/pages
directories in your app and installed packages. Pages can be HTML, Markdown, redirects, or static assets, with support for frontmatter variables and template rendering.
# app/templates/pages/about.md
---
title: About Us
---
# About Our Company
We build great software.
This creates a page at /about/
that renders the markdown content with the title "About Us".
Pages are discovered from:
{package}/templates/pages/
for each installed packageapp/templates/pages/
in your main application
The file path determines the URL:
index.html
orindex.md
→/
about.html
orabout.md
→/about/
docs/getting-started.md
→/docs/getting-started/
styles.css
→/styles.css
(served as static asset)
Page types
HTML pages
HTML files are rendered as templates with access to the standard template context:
<!-- app/templates/pages/features.html -->
---
title: Features
---
<h1>{{ page.title }}</h1>
<p>Current user: {{ request.user }}</p>
Markdown pages
Markdown files (.md
) are automatically converted to HTML:
<!-- app/templates/pages/guide.md -->
---
title: User Guide
template_name: custom-page.html
---
# User Guide
This is **markdown** content with [links](/other-page/).
Redirect pages
Files with .redirect
extension create redirects:
# app/templates/pages/old-url.redirect
---
url: /new-url/
temporary: false
---
Assets
Any file that isn't HTML, Markdown, or a redirect is served as a static asset:
app/templates/pages/
├── favicon.ico
├── robots.txt
├── images/
│ └── logo.png
└── docs/
└── guide.pdf
These are served at their exact paths: /favicon.ico
, /images/logo.png
, etc.
Template pages
Files containing .template.
in their name are skipped and not served as pages. Use these for shared template fragments:
app/templates/pages/
├── base.template.html # Not served
└── index.html # Served at /
Frontmatter
Pages support YAML frontmatter for configuration:
---
title: Custom Title
template_name: my-template.html
render_plain: true
custom_var: value
---
Available frontmatter options:
title
: Page title (defaults to filename)template_name
: Custom template to userender_plain
: Skip template rendering (for markdown)url
: Redirect URL (for .redirect files)temporary
: Redirect type (for .redirect files)- Any custom variables accessible via
page.vars
Custom views
The package provides view classes you can extend:
from plain.pages.views import PageView
class CustomPageView(PageView):
def get_template_context(self):
context = super().get_template_context()
context["extra_data"] = self.get_extra_data()
return context
The main view classes are:
PageView
: Renders HTML and Markdown pagesPageRedirectView
: Handles redirectsPageAssetView
: Serves static assets
Installation
Install the plain.pages
package from PyPI:
uv add plain.pages