CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-frozen-flask

Freezes a Flask application into a set of static files.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

configuration.mddocs/

Configuration and Customization

Comprehensive configuration system for controlling build behavior, file handling, error processing, and output customization. Frozen-Flask automatically sets sensible defaults on your Flask application's configuration.

Configuration Options

All configuration options are set on the Flask app's config object and prefixed with FREEZER_.

Build Output

Control where and how static files are generated.

# Build destination directory (relative to app.root_path)
app.config['FREEZER_DESTINATION'] = 'build'  # default

# Files to ignore in destination directory
app.config['FREEZER_DESTINATION_IGNORE'] = []  # default

# Remove files from previous build not in current build
app.config['FREEZER_REMOVE_EXTRA_FILES'] = True  # default

URL and Path Handling

Configuration for URL generation and path processing.

# Base URL for the site (affects url_for calls)
app.config['FREEZER_BASE_URL'] = None  # default

# Use relative URLs in templates
app.config['FREEZER_RELATIVE_URLS'] = False  # default

Static File Processing

Control static file discovery and processing.

# Static files to ignore during freezing
app.config['FREEZER_STATIC_IGNORE'] = []  # default

MIME Type Handling

Configuration for content type processing and validation.

# Default MIME type for files with unknown extensions
app.config['FREEZER_DEFAULT_MIMETYPE'] = 'application/octet-stream'  # default

# Skip MIME type mismatch warnings
app.config['FREEZER_IGNORE_MIMETYPE_WARNINGS'] = False  # default

Error Handling

Control how errors and edge cases are processed.

# Ignore 404 responses (useful during development)
app.config['FREEZER_IGNORE_404_NOT_FOUND'] = False  # default

# How to handle redirects: 'follow' or 'ignore'
app.config['FREEZER_REDIRECT_POLICY'] = 'follow'  # default

Performance Optimization

Settings for build performance and incremental updates.

# Skip files that haven't changed (boolean or callable)
app.config['FREEZER_SKIP_EXISTING'] = False  # default

Usage Examples

Basic Configuration

from flask import Flask
from flask_frozen import Freezer

app = Flask(__name__)

# Configure build destination
app.config['FREEZER_DESTINATION'] = 'dist'
app.config['FREEZER_REMOVE_EXTRA_FILES'] = True

freezer = Freezer(app)

Production Build Configuration

# Production build with relative URLs for CDN deployment
app.config.update({
    'FREEZER_DESTINATION': 'public',
    'FREEZER_RELATIVE_URLS': True,
    'FREEZER_BASE_URL': 'https://mysite.com/subpath/',
    'FREEZER_REMOVE_EXTRA_FILES': True,
    'FREEZER_IGNORE_MIMETYPE_WARNINGS': True,
})

Development Configuration

# Development build with lenient error handling
app.config.update({
    'FREEZER_DESTINATION': 'dev-build',
    'FREEZER_IGNORE_404_NOT_FOUND': True,
    'FREEZER_REDIRECT_POLICY': 'ignore',
    'FREEZER_REMOVE_EXTRA_FILES': False,
})

Custom File Ignoring

# Ignore specific files and patterns
app.config.update({
    'FREEZER_DESTINATION_IGNORE': [
        '.DS_Store',
        '*.log',
        'temp/*',
        'draft-*',
    ],
    'FREEZER_STATIC_IGNORE': [
        '*.scss',
        '*.coffee',
        'src/*',
        'node_modules/*',
    ],
})

Incremental Build Configuration

# Skip unchanged files for faster rebuilds
def should_skip_file(url, filepath):
    # Custom logic for determining if file should be skipped
    import os
    from datetime import datetime, timedelta
    
    if not os.path.exists(filepath):
        return False
    
    # Skip if modified less than 1 hour ago
    mtime = datetime.fromtimestamp(os.path.getmtime(filepath))
    return datetime.now() - mtime < timedelta(hours=1)

app.config['FREEZER_SKIP_EXISTING'] = should_skip_file

Advanced Configuration Patterns

Environment-Based Configuration

import os

class Config:
    FREEZER_DESTINATION = 'build'
    FREEZER_REMOVE_EXTRA_FILES = True

class DevelopmentConfig(Config):
    FREEZER_IGNORE_404_NOT_FOUND = True
    FREEZER_REDIRECT_POLICY = 'ignore'

class ProductionConfig(Config):
    FREEZER_DESTINATION = 'public'
    FREEZER_RELATIVE_URLS = True
    FREEZER_IGNORE_MIMETYPE_WARNINGS = True
    FREEZER_BASE_URL = os.environ.get('SITE_BASE_URL', 'https://example.com')

# Apply configuration based on environment
if app.config.get('ENV') == 'production':
    app.config.from_object(ProductionConfig)
else:
    app.config.from_object(DevelopmentConfig)

CDN Configuration

# Configuration for deploying to CDN with relative URLs
app.config.update({
    'FREEZER_RELATIVE_URLS': True,
    'FREEZER_BASE_URL': 'https://cdn.example.com/mysite/',
    'FREEZER_DESTINATION': 'cdn-build',
    'FREEZER_STATIC_IGNORE': [
        '*.map',  # Ignore source maps
        'dev/*',  # Ignore dev-only assets
    ],
})

Multi-Site Configuration

# Configuration for building multiple site variants
def configure_for_site(site_name):
    site_configs = {
        'main': {
            'FREEZER_DESTINATION': 'build/main',
            'FREEZER_BASE_URL': 'https://example.com',
        },
        'blog': {
            'FREEZER_DESTINATION': 'build/blog',
            'FREEZER_BASE_URL': 'https://blog.example.com',
        },
        'docs': {
            'FREEZER_DESTINATION': 'build/docs',
            'FREEZER_BASE_URL': 'https://docs.example.com',
            'FREEZER_RELATIVE_URLS': True,
        },
    }
    
    app.config.update(site_configs[site_name])

# Build different site variants
for site in ['main', 'blog', 'docs']:
    configure_for_site(site)
    freezer.freeze()

Configuration Validation

Frozen-Flask validates configuration automatically, but you can add custom validation:

def validate_freezer_config():
    """Validate Frozen-Flask configuration"""
    config = app.config
    
    # Ensure destination is set
    assert config.get('FREEZER_DESTINATION'), "FREEZER_DESTINATION must be set"
    
    # Validate redirect policy
    policy = config.get('FREEZER_REDIRECT_POLICY', 'follow')
    assert policy in ['follow', 'ignore'], f"Invalid redirect policy: {policy}"
    
    # Warn about potentially problematic settings
    if config.get('FREEZER_RELATIVE_URLS') and not config.get('FREEZER_BASE_URL'):
        import warnings
        warnings.warn("FREEZER_RELATIVE_URLS is True but FREEZER_BASE_URL is not set")

# Validate before freezing
validate_freezer_config()
freezer.freeze()

Install with Tessl CLI

npx tessl i tessl/pypi-frozen-flask

docs

configuration.md

core-freezing.md

index.md

url-generation.md

utilities.md

tile.json