Complete guide to configuring MintyFlaskSSG, including auto-discovery, local overrides, and theme system setup

Configuration

Introduction

MintyFlaskSSG uses a class-based Flask configuration system with intelligent path auto-discovery. The configuration handles theme resolution, content directories, photo galleries, and Markdown rendering whilst allowing you to override any setting for your specific environment.

This guide covers how to configure your MintyFlaskSSG site, from basic setup through to advanced customisation. You'll learn how the auto-discovery system works, when to override paths explicitly, and how to structure your configuration for different environments.

Why This Matters

Proper configuration is essential for MintyFlaskSSG to locate your themes, content, and assets. The auto-discovery system simplifies setup by finding common directory structures automatically, whilst the override system lets you work with custom layouts or multiple projects.

Key Concepts

Class-Based Configuration: MintyFlaskSSG uses Flask's class-based configuration pattern with a base Config class and environment-specific subclasses.

Auto-Discovery: The system automatically searches for themes, mixins, and data directories in standard locations, reducing manual configuration.

Local Overrides: A config_local.py file lets you override any setting without modifying the base configuration, perfect for development environments.

Three-Layer Template System: Configuration controls the resolution order: current theme → mixins → core theme fallback.


Configuration Files

MintyFlaskSSG uses two configuration files working together:

config.py - Base Configuration

The base configuration file defines default settings and the auto-discovery system. This file contains:

  • Class definitions for different environments (Config, DevelopmentConfig, ProductionConfig, etc.)
  • Auto-discovery logic for themes and data directories
  • Default values for all configuration options
  • Template resolution setup

You should not modify config.py directly unless you're changing system defaults. Instead, use config_local.py for your overrides.

config_local.py - Local Overrides

Create this file to override settings for your specific environment:

# config_local.py
"""Local configuration for your development environment."""

from config import Config


class LocalConfig(Config):
    """Your local development configuration."""

    # Explicit theme paths (prevents auto-discovery from finding wrong location)
    MINTY_THEMES_BASE_DIR = '~/code/flask/minty-flask-themes/minty_flask_themes'
    THEMES_BASE_DIR = "~/code/flask/minty-flask-themes/minty_flask_themes/themes"
    MIXINS_BASE_DIR = "~/code/flask/minty-flask-themes/minty_flask_themes/mixins"

    # Data directory (or set to None for auto-discovery)
    DATA_DIR = "../data"

    # Current theme
    THEME_NAME = 'blog'

The LocalConfig class inherits from Config and overrides specific settings. Python will automatically expand ~ in paths to your home directory.


Path Auto-Discovery

MintyFlaskSSG's auto-discovery system finds themes, mixins, and data directories automatically by searching common locations. This reduces configuration overhead whilst remaining flexible.

How Auto-Discovery Works

When a configuration value is set to None, the system searches a predefined list of locations:

  1. Data Directory (DATA_DIR):

    • project_root/data
    • project_root/../data
    • project_root/../../data
  2. Themes Base Directory (THEMES_BASE_DIR):

    • project_root/themes
    • project_root/../themes
    • project_root/../../themes
    • project_root/../../minty-flask-themes/minty_flask_themes/themes (MintyFlaskThemes location)
  3. Mixins Base Directory (MIXINS_BASE_DIR):

    • project_root/mixins
    • project_root/../mixins

The system uses the first location that exists, logging its choice during startup.

When to Use Auto-Discovery

Auto-discovery works well when:

  • Your directory structure follows standard conventions
  • You have a single MintyFlaskSSG project
  • Themes and data are in predictable locations relative to the app

When to Override Paths

Set explicit paths in config_local.py when:

  • Working with multiple MintyFlaskSSG projects that might conflict
  • Using a custom directory structure
  • Themes or data are in non-standard locations
  • You want absolute certainty about which directories are being used
# Explicit configuration prevents auto-discovery ambiguity
class LocalConfig(Config):
    THEMES_BASE_DIR = "/home/user/my-themes/themes"
    DATA_DIR = "/var/www/site-content"

Core Configuration Options

General Settings

class Config:
    # Site metadata
    SITE_DESCRIPTION = "Your default site description"

    # Content directories (relative to DATA_DIR)
    POSTS_DIR = "articles"        # Blog posts location
    PAGES_DIR = "pages"           # Static pages location

    # Internationalisation
    LANGUAGES_DEFAULT = "en"

    # Flask debugging
    FLASK_DEBUG = True

Theme System Configuration

The theme system requires three main path configurations:

class Config:
    # Set to None for auto-discovery
    MINTY_THEMES_BASE_DIR = None  # MintyFlaskThemes root
    THEMES_BASE_DIR = None        # Themes directory
    MIXINS_BASE_DIR = None        # Mixins directory (optional)

    # Active theme
    THEME_NAME = "blog"

    # Core fallback theme
    CORE_THEME_NAME = "_core"

MINTY_THEMES_BASE_DIR: Root of the MintyFlaskThemes package (typically minty_flask_themes/)

THEMES_BASE_DIR: Directory containing theme folders (typically minty_flask_themes/themes/)

MIXINS_BASE_DIR: Directory containing mixin folders (typically minty_flask_themes/mixins/)

THEME_NAME: The currently active theme, determines which theme templates load first

CORE_THEME_NAME: The fallback core theme, typically _core, provides base templates

Data Directory Configuration

class Config:
    # Main data directory (auto-discover if None)
    DATA_DIR = None

    # Site configuration YAML
    SITE_YAML_FILEPATH = None  # Auto-discovers to DATA_DIR/yaml/site.yaml

When DATA_DIR is set (either explicitly or via auto-discovery), the system automatically derives related paths:

  • SITE_YAML_FILEPATH{DATA_DIR}/yaml/site.yaml
  • FLATPAGES_ROOT{DATA_DIR}/markdown
  • PHOTOS_LIBRARY_ROOT{DATA_DIR}/photos/photos_original
  • PHOTOS_OUTPUT_DIR{DATA_DIR}/photos/photos_processed

You can override any of these individually if needed:

class LocalConfig(Config):
    DATA_DIR = "../data"
    FLATPAGES_ROOT = "../content/markdown"  # Override default

Flask-FlatPages Configuration

MintyFlaskSSG uses Flask-FlatPages for Markdown content rendering:

class Config:
    # Content root (auto-discovers to DATA_DIR/markdown)
    FLATPAGES_ROOT = None

    # File extension for content files
    FLATPAGES_EXTENSION = '.md'

    # Auto-reload in development
    FLATPAGES_AUTO_RELOAD = True

    # HTML renderer (custom photo-enhanced renderer)
    FLATPAGES_HTML_RENDERER = 'app.extensions.photo_enhanced_renderer'

    # Markdown extensions
    FLATPAGES_MARKDOWN_EXTENSIONS = [
        'meta', 'tables', 'fenced_code', 'codehilite', 'toc',
        'attr_list', 'def_list', 'abbr', 'footnotes',
        'admonition', 'smarty', 'sane_lists',
        'app.extensions.markdown.admonition'  # Custom extension
    ]

    # Extension-specific configuration
    FLATPAGES_MARKDOWN_EXTENSION_CONFIGS = {
        'codehilite': {
            'css_class': 'highlight',
            'linenums': False
        },
        'toc': {
            'anchorlink': True
        }
    }

Photo Gallery Configuration

class Config:
    # Photo directories (auto-discover if None)
    PHOTOS_LIBRARY_ROOT = None  # Original photos
    PHOTOS_OUTPUT_DIR = None    # Processed photos

    # Photo hover overlay behaviour
    PHOTOS_SHOW_HOVER_INFO = False      # Show info overlay on hover
    PHOTOS_SHOW_INFO_TOGGLE = False     # Show toggle button
    PHOTOS_INFO_DEFAULT_STATE = False   # Default toggle state

Pagination Settings

class Config:
    PER_PAGE = 10              # Items per page
    LINK_SIZE = "sm"           # Pagination link size
    SHOW_SINGLE_PAGE = False   # Hide pagination on single page

Reading Time Calculation

class Config:
    READING_SPEED_WPM = 225  # Words per minute for reading time estimates

Configuration Patterns

Pattern: Development Configuration

Standard development setup with auto-discovery:

# config_local.py
from config import Config

class LocalConfig(Config):
    """Development configuration with auto-discovery."""

    # Let auto-discovery find everything
    DATA_DIR = None
    THEMES_BASE_DIR = None
    MIXINS_BASE_DIR = None

    # Just specify which theme to use
    THEME_NAME = 'blog'

    # Enable auto-reload
    FLATPAGES_AUTO_RELOAD = True

Pattern: Explicit Path Configuration

Development setup with explicit paths (multiple projects):

# config_local.py
from config import Config

class LocalConfig(Config):
    """Development with explicit paths."""

    # Explicit paths prevent ambiguity
    MINTY_THEMES_BASE_DIR = '~/code/flask/minty-flask-themes/minty_flask_themes'
    THEMES_BASE_DIR = "~/code/flask/minty-flask-themes/minty_flask_themes/themes"
    MIXINS_BASE_DIR = "~/code/flask/minty-flask-themes/minty_flask_themes/mixins"

    # Project-specific data directory
    DATA_DIR = "../data"

    # Active theme
    THEME_NAME = 'minimal'

Pattern: Production Configuration

For deployment or static site generation:

# config_production.py
from config import Config

class ProductionConfig(Config):
    """Production configuration."""

    DEBUG = False
    FLASK_DEBUG = False

    # Explicit paths for production
    THEMES_BASE_DIR = "/var/www/themes"
    DATA_DIR = "/var/www/site-data"

    # Disable auto-reload
    FLATPAGES_AUTO_RELOAD = False

    # Production theme
    THEME_NAME = 'blog'

Pattern: Custom Content Structure

Override content directory paths:

# config_local.py
from config import Config

class LocalConfig(Config):
    """Custom content structure."""

    DATA_DIR = "../content"

    # Override default paths
    POSTS_DIR = "blog-posts"           # Instead of "articles"
    PAGES_DIR = "static-content"       # Instead of "pages"
    FLATPAGES_ROOT = "../content/md"   # Custom markdown location

Pattern: Photo Gallery Only

Configure for a photo gallery site:

# config_local.py
from config import Config

class LocalConfig(Config):
    """Photo gallery focused configuration."""

    DATA_DIR = "../photos-data"

    # Photo-specific settings
    PHOTOS_LIBRARY_ROOT = "/mnt/photo-archive/originals"
    PHOTOS_OUTPUT_DIR = "../photos-data/processed"

    # Enable hover info and toggle
    PHOTOS_SHOW_HOVER_INFO = True
    PHOTOS_SHOW_INFO_TOGGLE = True
    PHOTOS_INFO_DEFAULT_STATE = False

    # Photo gallery theme
    THEME_NAME = 'gallery'

Configuration Profiles

MintyFlaskSSG includes several pre-built logging profiles for different use cases. These are handled by run.py and selected using the --config flag when running the application.

Available Profiles

The logging profiles are defined in run.py and control subsystem logging levels:

development - Standard development with INFO-level logging (default)

production - Production deployment with minimal logging

photos - DEBUG-level logging for photo subsystem only

blog - DEBUG-level logging for blog subsystem only

routes - DEBUG-level logging for route resolution only

quiet - WARNING-level logging for clean output

all - DEBUG-level logging for all subsystems

Using Configuration Profiles

Select a profile when starting the application:

# Standard development
python run.py

# Debug photo processing
python run.py --config photos

# Debug blog functionality
python run.py --config blog

# Full debug output
python run.py --config all

# Production mode
python run.py --config production

See the "Running the Application" guide for complete details on configuration profiles.


Environment Detection

MintyFlaskSSG sets the ENVIRONMENT configuration key based on the selected profile:

# Set automatically in Config.init_app()
environment = os.environ.get('ENVIRONMENT', 'development')
app.config['ENVIRONMENT'] = environment
app.config['SHOW_DEV_NOTES'] = (environment == 'development')

The SHOW_DEV_NOTES flag controls whether development notes render in templates. Production configuration sets ENVIRONMENT = 'production', hiding dev notes automatically.


Template Resolution

Configuration controls MintyFlaskSSG's three-layer template resolution system. During initialisation, the system builds a template directory list in priority order:

  1. Current Theme (highest priority): {THEMES_BASE_DIR}/{THEME_NAME}/templates
  2. Mixins (middle priority): {MIXINS_BASE_DIR}/*/templates
  3. Core Theme (fallback): {THEMES_BASE_DIR}/{CORE_THEME_NAME}/templates

When you request a template, Jinja2 searches these directories in order, using the first match found. This allows themes to override mixin templates, and mixins to override core templates.

Theme Resolution Example

With this configuration:

THEMES_BASE_DIR = "/themes"
THEME_NAME = "blog"
CORE_THEME_NAME = "_core"

A request for page.html searches:

  1. /themes/blog/templates/page.html ← Custom theme version
  2. /themes/blog/templates/mixins/*/page.html ← Mixin versions
  3. /themes/_core/templates/page.html ← Core fallback

Explicit Theme References

Templates can reference specific themes using prefix notation:

{# Always use core base template #}
{% extends "_core/base.html" %}

{# Use blog theme header #}
{% include "blog/components/header.html" %}

The ThemeAwareLoader class handles these prefixed references, making cross-theme template composition possible.


Logging Configuration

MintyFlaskSSG configures Python logging in Config.init_app():

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s %(levelname)-5s [%(name)s] %(message)s',
    datefmt='%H:%M:%S'
)

# Subsystem logging levels
logging.getLogger('app.photos').setLevel(logging.WARNING)
logging.getLogger('app.blog').setLevel(logging.INFO)
logging.getLogger('app.home').setLevel(logging.INFO)
logging.getLogger('werkzeug').setLevel(logging.WARNING)

Override these in your configuration class:

class LocalConfig(Config):
    @staticmethod
    def init_app(app):
        Config.init_app(app)
        # Enable detailed photo logging
        import logging
        logging.getLogger('app.photos').setLevel(logging.DEBUG)

Note

**Profile-Based Logging**

Logging levels are managed through run.py's apply_logging_profile() function rather than config classes. This approach allows dynamic logging configuration without reloading the entire config, which would reset resolved paths.

The --config flag selects a logging profile:

python run.py --config photos  # DEBUG logging for photos only

Config classes like PhotosDebugConfig are no longer needed—profiles handle this more efficiently.

Best Practices

Configuration Management

Do:

✓ Create config_local.py for development overrides
✓ Use auto-discovery for standard directory layouts
✓ Set explicit paths when working with multiple projects
✓ Document why you override default values
✓ Use environment-specific configuration classes

Don't:

✗ Modify config.py directly for local changes
✗ Commit config_local.py to version control
✗ Hardcode absolute paths that won't work on other machines
✗ Override paths unnecessarily when auto-discovery works
✗ Use development configuration in production

Path Configuration

Do:

✓ Use ~ for home directory in paths (auto-expands)
✓ Use relative paths where possible (../data)
✓ Check logs to see which paths auto-discovery selected
✓ Test path resolution in development before deploying
✓ Use Path.expanduser().resolve() for path validation

Don't:

✗ Use absolute paths like /home/username/projects/...
✗ Assume auto-discovery will find non-standard structures
✗ Mix Windows and Unix path separators
✗ Forget to create directories that configuration references
✗ Use paths with spaces without proper quoting

Theme Configuration

Do:

✓ Keep THEME_NAME and CORE_THEME_NAME in sync with available themes
✓ Verify theme directories exist before running
✓ Use consistent theme naming conventions
✓ Test template resolution with debug configuration
✓ Document theme dependencies in your configuration

Don't:

✗ Reference non-existent themes (causes template errors)
✗ Change CORE_THEME_NAME unless you have a custom core
✗ Assume themes are portable without checking paths
✗ Mix theme versions with incompatible template structures
✗ Deploy with development themes


Troubleshooting

Problem: Themes Not Found

Symptoms:

  • Application starts but templates fail to load
  • Logs show "Theme templates not found" warnings
  • Template resolution falls back to core only

Diagnosis: Check the startup logs for theme path resolution:

WARNING: Theme templates not found: /path/to/themes/blog/templates

Solution: Set explicit THEMES_BASE_DIR in config_local.py:

class LocalConfig(Config):
    THEMES_BASE_DIR = "~/code/flask/minty-flask-themes/minty_flask_themes/themes"

Problem: Wrong Theme Directory Selected

Symptoms:

  • Auto-discovery finds themes in unexpected location
  • Multiple MintyFlaskSSG projects interfere with each other
  • Templates from wrong project load

Diagnosis: Check startup logs for auto-discovery selection:

INFO: Found themes directory at fallback location: ../../other-project/themes

Solution: Use explicit paths to prevent auto-discovery ambiguity:

class LocalConfig(Config):
    MINTY_THEMES_BASE_DIR = '~/code/flask/this-project/minty_flask_themes'
    THEMES_BASE_DIR = "~/code/flask/this-project/minty_flask_themes/themes"

Problem: Data Directory Not Found

Symptoms:

  • Content pages return 404
  • Photo galleries are empty
  • YAML configuration files not loading

Diagnosis: Check if DATA_DIR auto-discovery succeeded:

INFO: Data directory found: ../data

Solution: Create the expected directory structure or set explicit path:

mkdir -p ../data/markdown
mkdir -p ../data/photos
mkdir -p ../data/yaml

Or configure explicitly:

class LocalConfig(Config):
    DATA_DIR = "/path/to/content"

Problem: Configuration Changes Not Applied

Symptoms:

  • Modified config_local.py but changes not reflected
  • Still using default values

Diagnosis: Check if config_local.py is being imported and LocalConfig class exists.

Solution: Ensure your config_local.py follows this structure:

from config import Config

class LocalConfig(Config):
    # Your overrides here
    THEME_NAME = 'blog'

Restart the application to reload configuration.

Problem: Template Resolution Issues

Symptoms:

  • Templates loading from unexpected themes
  • Mixin templates not found
  • Core templates used when theme templates should apply

Diagnosis: Run with route debugging:

python run.py --config routes

Check template resolution order in logs.

Solution: Verify your template hierarchy configuration:

class LocalConfig(Config):
    THEMES_BASE_DIR = "/correct/path/themes"
    MIXINS_BASE_DIR = "/correct/path/mixins"
    THEME_NAME = "blog"  # Must exist in THEMES_BASE_DIR
    CORE_THEME_NAME = "_core"  # Must exist in THEMES_BASE_DIR

Common Use Cases

Use Case 1: Fresh Installation

You're setting up MintyFlaskSSG for the first time with standard directory structure:

# config_local.py - Minimal configuration
from config import Config

class LocalConfig(Config):
    # Let auto-discovery handle everything
    THEME_NAME = 'blog'

Start the application and check logs to verify auto-discovery:

python run.py --config all

Look for successful path detection messages.

Use Case 2: Multiple Projects

You're working on several MintyFlaskSSG sites simultaneously:

# config_local.py - Explicit paths prevent conflicts
from config import Config

class LocalConfig(Config):
    # Project-specific theme location
    MINTY_THEMES_BASE_DIR = '~/code/flask/project-a/themes-package'
    THEMES_BASE_DIR = "~/code/flask/project-a/themes-package/themes"

    # Project-specific data
    DATA_DIR = "~/code/flask/project-a/content"

    THEME_NAME = 'blog'

Use Case 3: Shared Theme Library

Your themes are in a separate shared repository:

# config_local.py - Point to shared themes
from config import Config

class LocalConfig(Config):
    # Shared theme library
    THEMES_BASE_DIR = "~/code/themes-library/themes"
    MIXINS_BASE_DIR = "~/code/themes-library/mixins"

    # Project-specific content
    DATA_DIR = "../site-content"

    THEME_NAME = 'corporate'

Use Case 4: Custom Content Structure

Your content doesn't follow the default layout:

# config_local.py - Custom paths
from config import Config

class LocalConfig(Config):
    DATA_DIR = "../content"

    # Custom content locations
    FLATPAGES_ROOT = "../content/pages"
    POSTS_DIR = "posts"
    PAGES_DIR = "docs"

    # Photos in separate location
    PHOTOS_LIBRARY_ROOT = "/mnt/photos/library"
    PHOTOS_OUTPUT_DIR = "../content/processed-photos"

    THEME_NAME = 'docs'

Configuration Checklist

Initial Setup

For New Installation:

  • Create config_local.py from template
  • Set THEME_NAME to desired theme
  • Verify theme exists in themes directory
  • Test auto-discovery with python run.py --config all
  • Check startup logs for path detection messages
  • Verify content loads correctly

For Custom Structure:

  • Set explicit THEMES_BASE_DIR path
  • Set explicit DATA_DIR path
  • Override content directory paths if needed
  • Create required directory structure
  • Test path resolution
  • Verify all content types load

Pre-Deployment

Before Going Live:

  • Create production configuration class
  • Set DEBUG = False and FLASK_DEBUG = False
  • Use explicit paths (no auto-discovery)
  • Set FLATPAGES_AUTO_RELOAD = False
  • Verify ENVIRONMENT = 'production'
  • Test with production configuration locally
  • Check logs are at WARNING level
  • Generate static site if not using dynamic Flask

Conclusion

MintyFlaskSSG's configuration system balances simplicity and flexibility. Auto-discovery reduces setup overhead for standard layouts, whilst explicit configuration provides precise control for complex deployments.

Key takeaways:

  1. Use config_local.py for overrides: Never modify config.py directly; create local configuration to preserve upgrade path.

  2. Auto-discovery is your friend: Let the system find standard directories automatically unless you have specific requirements.

  3. Explicit beats ambiguous: When working with multiple projects or custom structures, set paths explicitly to avoid conflicts.

  4. Test before deploying: Use debug configurations during development to verify path resolution and template loading.

  5. Profiles over classes: Use logging profiles via --config flag rather than creating separate config classes—it's more flexible and maintains resolved paths.

Start with minimal configuration and add overrides only when needed. The logging output will guide you if path resolution fails or templates don't load correctly.