Using Search V1 in your templates
So recently we've added a new search engine; You can read here how to enable it on your site.
After that you can create a fairly easy search page.
In this blog I will show you how to use this using a simple form get request.
- Using dedicated 'search' posttype with only index.
- Using request object to read url query params.
- Using search_results tag
- Using a couple of includes
- Using translate filter for UI translations.
- Singular result
- Plurar result
- Using simple form tag to send simple get request at Plate
- Using paginate tag

Features
This implementation includes several advanced features:
- Post Type Filtering: Users can filter results by content type (articles, pages, job postings)
- Pagination: Results are paginated with configurable posts per page
- Rich Result Cards Each result shows title, excerpt, and content type
- Translation Support All UI elements use translation keys
- Clean URLs: Uses GET parameters for search queries and filters
Implementation
Let's look at how to implement a search page using the actual theme structure:
theme/
├── posts/
│ └── search/
│ └── index.plate
└── includes/
└── modules/
└── search/
├── search_form.plate
├── search_index.plate
└── search_card.plate
The Main Search Page
Create a search page template at `theme/posts/search/index.plate`:
{%- content_for search -%}
<div class="search-index-page plate--container">
<search>
{% include 'includes/modules/search/search_form' %}
</search>
{% include 'includes/modules/search/search_index' %}
</div>
{% render_content %}
{%- endcontent_for -%}
Advanced Search Form with Filters
The search form (`includes/modules/search/search_form.plate`) includes post type filtering:
<form action="{{ site.search.index.url }}" method="get" class="search-form {{ classes }}">
<div class="search-form-input-wrapper">
<label for="search_form_input" class="search-form-input-label">
{{ "search.search_what" | translate }}
</label>
<input
class="search-form-input"
id="search_form_input"
type="search"
name="q"
value="{{ request.query_object.q | escape }}"
placeholder="{{ "search.search_placeholder" | translate }}"
>
{% assign filters = 'article,page,job_posting' | split: ',' %}
<fieldset>
<legend>Filters</legend>
{% for filter in filters %}
<input
type="checkbox"
id="posttype_{{ filter }}"
name="searchPostTypes[]"
value="{{ filter }}"
{% if request.query_object.searchPostTypes contains filter %}checked{% endif %}
>
<label for="posttype_{{ filter }}">
{{ filter | prepend: 'post_type.' | translate }}
</label>
{% endfor %}
</fieldset>
<button type="submit" class="search-form-button" title="{{ "search.search" | translate }}">
<span>{{ "search.search" | translate }}</span>
</button>
</div>
</form>
Search Results with Pagination
The search index (`includes/modules/search/search_index.plate`) handles results display and pagination:
<div class="search-index-page-results">
{%- assign search_string = request.query_object.q | escape -%}
{%- assign searchPostTypes = false -%}
{% if request.query_object.searchPostTypes != blank %}
{%- assign searchPostTypes = request.query_object.searchPostTypes -%}
{% endif %}
{%- capture searchFilters -%}
[
{%- if searchPostTypes != false -%}
{
"field": "post.content_type_name",
"operator": "in",
"value": [{%- for filter in searchPostTypes -%}
"{{filter}}"{% unless forloop.last %},{% endunless %}
{%- endfor -%}]
}
{%- endif -%}
]
{%- endcapture -%}
{% search_results search_string, filters: searchFilters %}
{%- if search_results != blank -%}
{% if search_results.size == 1 %}
<p class="filtered-results-item">
<span class="count">{{ search_results.size }}</span>
{{ "search.results_found_singular" | translate }}
</p>
{% else %}
<p class="filtered-results-item">
<span class="count">{{ search_results.size }}</span>
{{ "search.results_found_plural" | translate }}
</p>
{% endif %}
{%- assign postsPerPage = site.search.index.posts_per_page | default: site.posts_per_page | times: 1 -%}
{% paginate object_array: search_results, per_page: postsPerPage, window_size: 5 %}
{% for p in paginate.items %}
{% include 'includes/modules/search/search_card', search_card: p %}
{% endfor %}
{% if search_results.size != 0 %}
{%- include 'includes/modules/search/search_pagination_buttons' -%}
{% endif %}
{% endpaginate %}
{% else %}
{% if request.query_object.q != blank %}
<div class="no-results">
<h2>{{ "search.no_results" | translate }}</h2>
<p>{{ "search.try_again" | translate }}</p>
</div>
{% endif %}
{%- endif -%}
{% endsearch_results %}
</div>
Search Result Card
Each search result is displayed using a card template (`includes/modules/search/search_card.plate`):
<a href="{{ search_card.url }}" class="search-card {% if item.image != blank %}has-image{% endif %}">
<div class="search-card-content">
<h2>{{ search_card.title | strip_html }}</h2>
{% if search_card.index_text != blank %}
<div class="index-text paragraph">
{{ search_card.index_text }}
</div>
{% endif %}
<p>{{ search_card.content_type.name | prepend: 'post_type.' | translate }}</p>
</div>
</a>
Required Translations
Make sure to add these translations to your language files:
search:
search_what: "Search"
search_placeholder: "Enter your search terms..."
search: "Search"
results_found_singular: "result found"
results_found_plural: "results found"
no_results: "No results found"
try_again: "Please try different search terms"
post_type:
article: "Article"
page: "Page"
job_posting: "Job Posting"
Bonus: SCSS Styling the Pagination
Add these styles for the pagination, which includes WCAG-compliant touch targets and proper visual styling. Here is an example scss file:
.search-pagination {
display: flex;
color: black;
.list-pagination {
margin: 2rem auto;
display: flex;
flex-wrap: wrap;
gap: 0;
justify-content: center;
}
.pagination__item {
display: flex;
align-items: center;
justify-content: center;
position: relative;
a,
button {
@include buttonReset;
text-decoration: none;
color: inherit;
// WCAG-compliant touch target size
width: 4.8rem;
height: 4.8rem;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
z-index: 1;
position: relative;
span {
font-weight: 600;
font-size: 2rem;
line-height: 1;
font-family: sans-serif;
}
&::before {
z-index: -1;
content: '';
display: flex;
position: absolute;
width: 90%;
height: 90%;
border-radius: 50%;
background-color: lightgray;
outline: none;
transition: all .3s ease-in-out;
}
&[disabled] {
opacity: 0.5;
cursor: initial;
}
&:not([disabled]) {
cursor: pointer;
&:focus-visible,
&:hover {
color: white;
&::before {
background-color: black;
}
}
}
}
&--active {
a,
button {
font-size: 2.2rem;
font-weight: 700;
color: white;
&::before {
background-color: black;
}
}
}
}
}
Conclusion
This implementation provides a clean and user-friendly search experience with:- Responsive search form- Clear results display- Proper handling of no results- Internationalization support- Clean separation of concerns using includes.
Remember to customize the styling to match your theme's design system. You can also extend the search functionality by adding filters, categories, or other advanced features using the new search engine capabilities.