Skip to content

Page templates & display data

A Port60 template can own several independent presentation surfaces. Each surface is opt in and the platform keeps responsibility for data fetching, transactions, identity and consent.

Manifest declaration What the template owns Required file
supports.layout: true Header, navigation and footer around every public page layout.liquid
supports.pages: ["home", "about"] The section based body of the named page One renderer in sections/ for each supported section type
supports.pageTemplates: ["events", "course", "articles", "article"] A documented platform data view, with the route specific ownership described below The corresponding file in pages/
Capability flags such as supports.worship A documented optional context used by the declared surface The renderer that consumes the context

These declarations do not imply one another. A page template requires layout because its body is inserted into the layout content slot. A template may own layout without owning any page template, and it may support only some section based pages.

Route or view Template owned body when declared Platform owned body
/ Home sections when supports.pages contains home Built in home renderers
/about About sections when supports.pages contains about Built in about renderers
/events pages/events.liquid when supports.pageTemplates contains events Built in event listing
Event detail Never Detail, RSVP and ticket purchase
/courses Never Course listing
Course detail pages/course.liquid when supports.pageTemplates contains course Built in detail when not declared, with enrolment still handled by an island
/articles and /articles/all pages/articles.liquid when declared Built in editorial front page and archive
/articles/{slug} pages/article.liquid when declared Built in article detail when not declared; engagement and comments remain islands
Donations, services, members and prayer times Never in contract v1 Platform body inside the template layout

The platform always owns the document head, consent controls, identity flows and transactional behaviour. Your layout supplies the visible chrome around these bodies.

{ "supports": { "pageTemplates": ["events"] } }

Ship pages/events.liquid with that declaration. The platform fetches the data, renders your markup with the documented context, then inserts the result into your layout. Without the declaration, the platform body renders inside the same layout.

A page template receives the page’s documented context objects. See Render context. It never receives internal API responses. The events listing receives events, a stable view containing fields such as name, times, venue, mode, availability and priceFrom. Article listings receive articles and categories. Article details receive article, categories and moreArticles.

Two habits are important:

  • Branch on nullable fields. description, venueName, imageUrl and priceFrom are null when absent.
  • Use detailHref for links. Routing belongs to the platform, so templates must not construct detail URLs.
{% for e in events %}
<article>
<h3><a href="{{ e.detailHref }}">{{ e.name }}</a></h3>
<p>{{ e.startsAt | date: "%A %-d %B, %H:%M" }}{% if e.venueName %} · {{ e.venueName }}{% endif %}</p>
{% if e.soldOut %}<span>Sold out</span>{% elsif e.priceFrom %}<span>from £{{ e.priceFrom }}</span>{% endif %}
</article>
{% endfor %}

The conformance validator renders each page template against its fixture states. Publication fails when a supported state cannot render.

The four page templates deliberately own different views:

  • events owns the event listing. Event details and every RSVP or ticket transaction remain platform owned.
  • course owns a course detail presentation. The course listing remains platform owned, and the enrolment action is provided by the course_enrol island.
  • articles owns the article front page and archive listings. Use the supplied href values for articles and category filters.
  • article owns the article detail presentation. The sanitised article.bodyHtml is the only article field intended for | raw; place article_engagement and article_comments for the platform-owned interactive parts.

This is a display contract, not a route takeover. The manifest reference and generated context reference are the source of truth as new views are introduced additively.