Learn how to use and compose theme mixins to add features to your site

Understanding Mixins

Mixins are self-contained feature packages that you can add to your MintyFlask site. Think of them as building blocks that provide specific functionality—like blog posts, photo galleries, or contact forms—without requiring you to write everything from scratch.

What Are Mixins?

A mixin is a collection of templates, styles, and scripts organised around a specific feature. For example, the blog mixin provides everything you need to run a blog: post listings, category pages, tag filtering, and archive views.

Each mixin is independent and can be combined with others, giving you the flexibility to build exactly the site you need.

Key Characteristics

Self-Contained
Each mixin includes its own templates, CSS, and JavaScript. You don't need to hunt for dependencies or worry about missing files.

Reusable
Once a mixin is created, it can be used across multiple themes and projects. You might use the same blog mixin for a personal blog and a corporate news section.

Composable
Mixins work together seamlessly. You can combine a blog mixin with a photos mixin to create a travel blog with integrated photo galleries.

Theme-Independent
Mixins provide functionality without enforcing specific styling. Your theme controls the visual appearance whilst the mixin handles the features.

Available Mixins

MintyFlaskThemes currently includes these mixins:

Blog Mixin

The blog mixin provides comprehensive blogging functionality:

  • Post Management: Individual post pages with metadata, reading time, and navigation
  • Organisation: Categories and tags for content taxonomy
  • Archives: Date-based browsing by year and month
  • Listings: Flexible post listing layouts (list or grid views)
  • Special Views: Draft posts and review queues for content workflow
  • Navigation: Blog-specific navigation components

Quick Start:

{# Import blog components in your template #}
{% from "blog-components.html" import blog_post_list, post_card_actions %}

{# Display a list of posts #}
{{ blog_post_list(posts, layout='grid', columns=3) }}

Photos Mixin

Using Mixins in Your Theme

Basic Integration

To use a mixin in your theme, you need to:

  1. Import the components you want to use
  2. Call the macros where you need them
  3. Pass the required data from your Flask routes

Here's a practical example using the blog mixin:

{# themes/your-theme/templates/blog/index.html #}
{% extends "base.html" %}
{% from "blog-components.html" import blog_post_list %}

{% block content %}
<div class="container">
    <h1>Latest Articles</h1>

    {# Display posts in a 2-column grid #}
    {{ blog_post_list(
        posts=posts,
        layout='grid',
        columns=2,
        show_excerpt=true,
        show_meta=true
    ) }}
</div>
{% endblock %}

Template Resolution

MintyFlaskThemes uses a three-layer system to find templates:

1. Your Theme      (themes/your-theme/templates/)
   ↓ if not found
2. Mixin Layer     (mixins/blog/templates/)
   ↓ if not found
3. Core Layer      (themes/_core/templates/)

This means you can:

  • Use mixin templates as-is for quick setup
  • Override specific templates in your theme when you need customisation
  • Fall back to core templates for essential functionality

Example:

{# Your theme can override the default post layout #}
{# themes/your-theme/templates/pages/post-single.html #}
{% extends "layouts/single.html" %}

{# Add custom styling for your brand #}
{% block article_class %}blog-post our-brand-style{% endblock %}

Importing Mixin Components

Mixins expose their functionality through macros defined in component files. Here's how to import and use them:

{# Import specific macros you need #}
{% from "blog-components.html" import
    blog_post_list,
    post_metadata_enhanced,
    post_tag_cloud
%}

{# Use them in your templates #}
<article class="post">
    <header>
        {{ post_metadata_enhanced(post, show_reading_time=true) }}
    </header>

    <div class="content">
        {{ post.html | safe }}
    </div>

    <footer>
        {{ post_tag_cloud(post, style='badges') }}
    </footer>
</article>

Configuration Options

Most mixin macros accept parameters that let you customise their behaviour:

{# Minimal configuration #}
{{ blog_post_list(posts) }}

{# Fully customised #}
{{ blog_post_list(
    posts=recent_posts,
    layout='grid',              # 'list' or 'grid'
    columns=3,                  # Grid columns (2 or 3)
    show_excerpt=true,          # Display post summaries
    show_meta=true,             # Show date, category, etc.
    show_featured_image=true,   # Display post images
    limit=6                     # Maximum posts to display
) }}

Combining Multiple Mixins

One of the most powerful features of the mixin system is composition. You can combine multiple mixins to create rich, feature-packed sites.

Example: Blog + Photos

{# themes/travel-blog/templates/home.html #}
{% extends "base.html" %}

{# Import from multiple mixins #}
{% from "blog-components.html" import blog_post_list %}
{% from "gallery-components.html" import gallery_featured %}

{% block content %}
{# Hero section with featured gallery #}
<section class="hero">
    {{ gallery_featured(gallery=latest_photos, limit=5) }}
</section>

{# Blog posts below #}
<section class="recent-posts">
    <h2>Recent Adventures</h2>
    {{ blog_post_list(posts=recent_posts, layout='grid', columns=3) }}
</section>
{% endblock %}

Data Flow

When combining mixins, your Flask routes provide the data:

# app/routes/main.py
from flask import Blueprint, render_template

main_bp = Blueprint('main', __name__)

@main_bp.route('/')
def home():
    # Fetch data for both mixins
    recent_posts = get_recent_posts(limit=6)
    latest_photos = get_latest_gallery()

    # Pass to template
    return render_template('home.html',
        recent_posts=recent_posts,
        latest_photos=latest_photos
    )

Customising Mixin Behaviour

Overriding Templates

If you need to customise how a mixin renders, you can override its templates in your theme:

themes/your-theme/templates/
├── pages/
│   └── post-single.html       # Overrides blog mixin's post layout
├── partials/
│   └── post-card.html          # Overrides blog mixin's card component
└── base.html                   # Your theme's base layout

The template resolution system will use your override first, falling back to the mixin's original if you don't provide one.

Extending Mixin Templates

You can also extend mixin templates to add functionality whilst keeping the original structure:

{# themes/your-theme/templates/pages/post-single.html #}
{% extends "mixins/blog/templates/pages/post-single.html" %}

{# Add a new block for social sharing #}
{% block post_footer %}
    {{ super() }}  {# Keep original footer content #}

    <div class="social-sharing">
        {# Your custom social sharing buttons #}
    </div>
{% endblock %}

Custom Styling

Each mixin includes its own CSS, but you can override styles in your theme:

/* themes/your-theme/static/css/custom.css */

/* Override blog mixin's card styling */
.card-base.card-intent-content {
  border-radius: 12px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

/* Customise post metadata appearance */
.post-metadata {
  font-family: "Your Custom Font", sans-serif;
  color: var(--brand-primary);
}

Best Practises

Choose the Right Level of Customisation

Use mixin defaults when:

  • You're prototyping quickly
  • The default styling fits your needs
  • You want to focus on content first

Override selectively when:

  • You need specific brand styling
  • Certain components need different behaviour
  • You're refining the user experience

Create custom mixins when:

  • You need completely unique functionality
  • You're building reusable features for multiple projects
  • You want to share components with the community

Keep Mixins Focused

When working with mixins, maintain clear separation:

{# Good: Each mixin handles its own domain #}
{% from "blog-components.html" import blog_post_list %}
{% from "gallery-components.html" import gallery_grid %}

{# Avoid: Mixing concerns #}
{# Don't try to make blog components handle gallery data #}

Document Your Overrides

If you override mixin templates, document why:

{# themes/your-theme/templates/pages/post-single.html #}
{#
 # Custom Post Layout
 #
 # Overrides: mixins/blog/templates/pages/post-single.html
 # Reason: Add custom social sharing and newsletter signup
 # Modified: 2025-11-24
 #}
{% extends "layouts/single.html" %}
...

Creating Custom Mixins

Whilst this user guide focuses on using existing mixins, you might eventually want to create your own. Custom mixins follow the same structure and patterns as the built-in ones.

Quick Preview:

A basic mixin structure looks like this:

mixins/your-feature/
├── templates/
│   ├── your-feature-components.html    # Macro definitions
│   ├── layouts/                        # Page layouts
│   └── partials/                       # Reusable fragments
├── static/
│   ├── css/
│   │   └── your-feature.css
│   └── js/
│       └── your-feature.js
└── README.md                            # Documentation

Next Steps

Now that you understand mixins, explore these related topics:

Common Questions

Q: Can I use multiple versions of the same mixin?
A: No, the template resolution system will always use the first match it finds. If you need different behaviours, create theme-level overrides or customise via parameters.

Q: Do mixins slow down my site?
A: No. Mixins are resolved at template render time, just like any other Jinja2 template. Flask's built-in template caching keeps performance high.

Q: Can I disable a mixin I'm not using?
A: Yes. Simply remove it from your Flask app's template loader configuration. If you're not importing from a mixin, it has no impact on your site.

Q: How do I know what parameters a macro accepts?
A: Each mixin includes documentation comments in its component files. You can also refer to the API Reference for complete parameter lists.

Q: Can I contribute my own mixin?
A: Absolutely! See the Contributing Guide for information on sharing your mixins with the community.