Archive & Search Templates
How to build custom archive layouts and a custom search results page using the Protuno Theme Builder and the get_posts loop.
Archive templates control the layout of category archives, tag archives, author archives, date archives, and custom taxonomy archives. A Search Results template controls what visitors see after they submit a search query. Both use Protuno's loop system to render lists of matching posts.
Create An Archive Template
- Go to Protuno → Theme Builder
- Click + Add New → Archive (or Search Results for search)
- Drag the Proton widget onto the canvas
- Build your archive layout
- Click Update to save
- Set display conditions
The term Provider In Archive Templates
On taxonomy archive pages (category, tag, custom taxonomy), the term Twig provider resolves to the current archive term:
<header class="archive-header pr-boxed">
<span class="text-label">Category</span>
<h1 class="text-heading-h1">{{ term.name }}</h1>
{% if term.description %}
<p class="archive-description">{{ term.description }}</p>
{% endif %}
<p class="text-body-sm">{{ term.count }} articles</p>
</header>
On author archive pages, use the user provider:
<h1>Posts by {{ user.name }}</h1>
<img src="{{ user.avatar('80') }}" alt="{{ user.name }}">
The Post Loop
Use get_posts with paged: current_page() to render the archive's posts:
<section class="archive-grid pr-boxed">
<div class="pr-grid-3">
{% for post in get_posts({
post_type: 'post',
posts_per_page: 9,
paged: current_page()
}) %}
<article class="pr-blog-card">
<a href="{{ post.link }}">
<img
src="{{ post.thumbnail.src('medium') }}"
alt="{{ post.thumbnail.alt }}"
>
</a>
<div class="card-body">
<span class="text-label">{{ post.categories.name }}</span>
<h2 class="text-heading-h4">{{ post.title }}</h2>
<p>{{ post.excerpt|truncate(100) }}</p>
<a href="{{ post.link }}" class="text-label">Read More →</a>
</div>
</article>
{% endfor %}
</div>
{{ loop_pagination()|raw }}
</section>
current_page() reads the current page number from the URL (?loop_page=N). loop_pagination() renders numbered page navigation links.
Display Conditions For Archives
| Condition | What it covers |
|---|---|
| Post Category (any category) | All category archive pages |
| Post Category → specific term | One specific category's archive |
| Post Tag (any tag) | All tag archive pages |
| Author Archive | All author archive pages |
| Date Archive | Date-based archive pages |
To apply one archive template to all categories and another to a specific category, use two templates:
- Template A: Include → Post Category (any), broad
- Template B: Include → Post Category → "News", specific (wins for the News category)
Search Results Template
The search results template uses request.get('s') to access the search query, and get_posts with the s parameter to fetch matching results:
<section class="search-results pr-boxed">
<header class="search-header">
<h1 class="text-heading-h2">
{% if request.get('s') %}
Results for "{{ request.get('s') }}"
{% else %}
Search
{% endif %}
</h1>
</header>
{% set results = get_posts({
post_type: 'any',
posts_per_page: 10,
s: request.get('s'),
paged: current_page()
}) %}
{% if results %}
<div class="results-list">
{% for post in results %}
<article class="result-item">
<h2 class="text-heading-h4">
<a href="{{ post.link }}">{{ post.title }}</a>
</h2>
<p>{{ post.excerpt|truncate(150) }}</p>
<span class="text-label">{{ post.date|date('F j, Y') }}</span>
</article>
{% endfor %}
</div>
{{ loop_pagination()|raw }}
{% else %}
<p class="no-results">No results found for "{{ request.get('s') }}".</p>
<p>Try different keywords, or browse by <a href="/categories">category</a>.</p>
{% endif %}
</section>
Display condition for search: Include → Search Results.
Tips
Filtering by the current term in loop: On a category archive, pass the current term to get_posts using tax_query. Get the current term slug from term.slug:
{% for post in get_posts({
post_type: 'post',
posts_per_page: 9,
paged: current_page(),
tax_query: [{
taxonomy: 'category',
field: 'slug',
terms: [term.slug]
}]
}) %}
Empty archive state: Add {% if %}...{% else %}...{% endif %} around your loop to show a "no posts" message when the archive is empty.