Learn the essentials of MintyFlask's template resolution system in 5 minutes

Template Resolution Quick Start

What You Need to Know

MintyFlask templates are organised in layers: Themes (your site's look), Mixins (reusable features), and Core (the foundation). The template resolution system automatically finds the right template across these layers.

90% of the time, you'll use two simple patterns:

  1. resolve_base_template() → for extending core layouts
  2. Simple extends → for extending mixin layouts

That's it. Let's see how they work.

The Two Essential Patterns

Pattern 1: Extending Core Layouts

Use resolve_base_template() when extending fundamental layouts like base.html or single.html:

{# themes/blog/templates/pages/about.html #}
{% extends resolve_base_template('base.html') %}

{% block content %}
<h1>About Us</h1>
<p>Your content here...</p>
{% endblock %}

What happens: MintyFlask looks for base.html in your theme first, then falls back to the core theme automatically.

Pattern 2: Extending Mixin Layouts

Use simple extends when extending layouts from mixins:

{# themes/blog/templates/pages/category.html #}
{% extends "layouts/post-list.html" %}

{% set page_title = "Category: " + category %}
{% set page_description = "Articles in this category" %}

What happens: Flask searches its template path (theme → mixins → core) and uses the first match.

Three Common Scenarios

Creating a New Page

{# themes/blog/templates/pages/contact.html #}
{% extends resolve_base_template('base.html') %}

{% block content %}
<div class="contact-page">
    <h1>Contact Us</h1>
    {# Your page content #}
</div>
{% endblock %}

Using a Blog Mixin Layout

{# themes/blog/templates/pages/tag.html #}
{% extends "layouts/post-list.html" %}

{# Configure the layout #}
{% set page_title = "Posts tagged: " + tag %}
{% set pagination_endpoint = 'blog_bp.tag_view' %}
{% set pagination_params = {'tag': tag} %}

Including Partials

{# In any template #}
{% include "partials/post-card.html" %}
{% from "blog-components.html" import blog_post_list with context %}

Quick Decision Guide

Which pattern should I use?

Are you extending a core layout (base.html, single.html)?
├─ YES → Use resolve_base_template()
└─ NO → Are you extending a mixin layout?
    ├─ YES → Use simple extends "layouts/..."
    └─ NO → Use simple include or import

Common Gotchas

Import Context

If your macro uses Flask functions (url_for, config, etc.), add with context:

{# Wrong - macro can't access url_for #}
{% from "blog-components.html" import blog_post_list %}

{# Correct #}
{% from "blog-components.html" import blog_post_list with context %}

Template Names

Avoid naming collisions by using descriptive names:

❌ mixins/blog/templates/layouts/list.html
❌ mixins/docs/templates/layouts/list.html

✅ mixins/blog/templates/layouts/post-list.html
✅ mixins/docs/templates/layouts/docs-list.html

File Organisation

Where do templates go?

themes/blog/templates/
├── pages/              # Your page templates (URL endpoints)
└── layouts/            # Theme-specific layout overrides (rare)

mixins/blog/templates/
├── layouts/            # Reusable layouts ← extend these
├── partials/           # Reusable components ← include these
└── blog-components.html # Macros ← import from these

themes/_core/templates/
├── base.html           # Main layout ← extend this with resolve_base_template()
└── layouts/            # Core layouts ← extend these with resolve_base_template()

Your First Template

Let's create a simple "Our Team" page:

{# themes/blog/templates/pages/team.html #}
{% extends resolve_base_template('base.html') %}

{% block content %}
<div class="team-page">
    <h1>Our Team</h1>

    <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
        {% for member in team_members %}
        <div class="card-base card-intent-content card-size-md">
            <div class="card-body">
                <h2 class="card-title">{{ member.name }}</h2>
                <p class="card-description">{{ member.role }}</p>
            </div>
        </div>
        {% endfor %}
    </div>
</div>
{% endblock %}

Flask route:

@main_bp.route('/team')
def team():
    team_members = [
        {'name': 'Alice', 'role': 'Developer'},
        {'name': 'Bob', 'role': 'Designer'},
    ]
    return render_template('pages/team.html', team_members=team_members)

Next Steps

You now know enough to create pages and use mixin layouts. For more details:

Summary

Remember these two patterns:

  1. resolve_base_template('base.html') - for core layouts
  2. extends "layouts/post-list.html" - for mixin layouts

That covers 90% of what you'll need. When in doubt, check if you're extending from core or from a mixin, and choose the appropriate pattern.