{% raw %}
# Consistency rules
These are hard, structural rules, not suggestions. They are derived from the **posts / feed page**, which is the reference implementation: structurally and visually it is the most correct page in the application. Other pages will be refactored to match it; when a new page is built, it follows these rules from the start.
The point of the rules is that the header, breadcrumb, content root, and footer are *shared infrastructure*. A page supplies its content and its stylesheet; it never rebuilds the frame.
## The reference skeleton
This is the shape of the posts page, reduced to its structure. A content page looks like this and nothing else:
```html
{% extends "base.html" %}
{% block extra_head %}
<link rel="stylesheet" href="/static/css/feed.css">
{% endblock %}
{% block content %}
<h1 class="sr-only">Feed</h1>
<div class="feed-layout"> {# exactly one layout container #}
<aside class="sidebar-card"> ... </aside>
<div class="feed-main"> ... </div>
<aside class="feed-right"> ... </aside>
</div>
{% endblock %}
```
The header, breadcrumb, `` wrapper, and footer are all supplied by `base.html`. The template above never appears to contain them, and never should.
## Hard rules
### 1. Extend the base template
Every page is `{% extends "base.html" %}`. Page CSS is added only through `{% block extra_head %}`; page JS only through `{% block extra_js %}`. A page never includes its own ``, ``, or ``, and never links `variables.css` / `base.css` / `components.css` (the base already does).
### 2. The header is shared, never re-implemented
The top nav is `base.html`'s `.topnav`. Pages do not build their own header or navigation bar. The active link is derived from the request path inside `base.html`. If a page needs a page-level toolbar (tabs, filters), that toolbar lives *inside the content*, like the feed's `.feed-nav` strip, below the breadcrumb, not as a second site header.
### 3. Breadcrumbs are mandatory (this is the most-broken rule)
A page **must** pass at least two breadcrumbs (Home plus the current page) through its SEO context:
```python
seo_ctx = list_page_seo(
request,
title="Projects",
breadcrumbs=[{"name": "Home", "url": "/feed"}, {"name": "Projects", "url": "/projects"}],
)
```
This is not only for SEO. The `.breadcrumb` element carries `padding-top: calc(var(--nav-height) + 0.5rem)`, and that padding is **what pushes the content clear of the fixed top nav**. A page that ships no breadcrumbs (or only one) has its first content hidden behind the header. Always supply two or more.
### 4. All content lives in the single content root
`base.html` already wraps the `content` block in `` (`max-width: 1200px`, centred, `padding: 1rem`). Therefore a page:
- puts everything inside one top-level layout container (a grid like `.feed-layout`, or a single column);
- never adds a second centred / `max-width` wrapper inside `.page`;
- never re-declares the maximum content width.
See [Layout](/docs/styles-layout.html) for the approved layout containers.
### 5. Multi-column structure is grid, and it collapses
Side columns are `
Anatomy of a page (what base.html owns vs what the page supplies)
DevPlace · Home Posts News Gists Projectsbase.html: .topnav (fixed)
Home / Projectsbase.html: .breadcrumb (clears the nav)
Your content, inside one layout container.page: block content, inside .page