Skip to main content

Static Assets

Framefox provides a robust system for managing static assets like CSS files, JavaScript, images, fonts, and other files that don’t change during runtime. The asset() function handles asset URLs with automatic versioning for cache management.

Static File Location

All static assets are stored in the public/ directory of your project:
my-project/
├── public/
│   ├── css/
│   │   ├── app.css
│   │   ├── dashboard.css
│   │   └── auth.css
│   ├── js/
│   │   ├── app.js
│   │   ├── charts.js
│   │   └── forms.js
│   ├── images/
│   │   ├── logo.png
│   │   ├── hero.jpg
│   │   └── icons/
│   │       ├── user.svg
│   │       └── settings.svg
│   ├── fonts/
│   │   ├── roboto.woff2
│   │   └── opensans.woff2
│   └── downloads/
│       └── user-guide.pdf
├── templates/
├── src/
└── main.py

The asset() Function

The asset() function generates URLs for static files with automatic versioning.

Syntax

{{ asset('path/to/file.ext', versioning=True) }}

Parameters

  • path (str): Path relative to the public/ directory
  • versioning (bool, optional): Enable/disable versioning (default: True)

How It Works

  1. Takes a file path relative to public/
  2. Generates the full URL using the base_url setting
  3. Adds a version query parameter based on file modification time
  4. Returns the complete URL

CSS Assets

Loading Stylesheets

<!-- templates/base.html -->
<!DOCTYPE html>
<html>
<head>
    <title>My App</title>
    
    <!-- Main application styles -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
    
    <!-- Additional stylesheets -->
    {% block stylesheets %}{% endblock %}
</head>
<body>
    {% block content %}{% endblock %}
</body>
</html>

Page-Specific Stylesheets

<!-- templates/user/index.html -->
{% extends "base.html" %}

{% block stylesheets %}
    <link href="{{ asset('css/users.css') }}" rel="stylesheet">
    <link href="{{ asset('css/tables.css') }}" rel="stylesheet">
{% endblock %}

{% block content %}
    <h1>Users</h1>
    <!-- Content here -->
{% endblock %}

Organizing CSS Files

public/css/
├── app.css          # Main application styles
├── components/
│   ├── buttons.css  # Button styles
│   ├── forms.css    # Form styles
│   └── cards.css    # Card styles
├── pages/
│   ├── home.css     # Home page styles
│   ├── dashboard.css # Dashboard styles
│   └── auth.css     # Authentication pages
└── vendor/
    └── external.css  # Third-party CSS
Load organized CSS:
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<link href="{{ asset('css/components/buttons.css') }}" rel="stylesheet">
<link href="{{ asset('css/pages/dashboard.css') }}" rel="stylesheet">

JavaScript Assets

Loading Scripts

<!-- templates/base.html -->
<!DOCTYPE html>
<html>
<head>
    <title>My App</title>
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
    {% block content %}{% endblock %}
    
    <!-- Main application JavaScript -->
    <script src="{{ asset('js/app.js') }}"></script>
    
    <!-- Additional scripts -->
    {% block scripts %}{% endblock %}
</body>
</html>

Page-Specific JavaScript

<!-- templates/dashboard/index.html -->
{% extends "base.html" %}

{% block scripts %}
    <!-- Chart library -->
    <script src="{{ asset('js/charts.js') }}"></script>
    
    <!-- Dashboard-specific code -->
    <script src="{{ asset('js/dashboard.js') }}"></script>
{% endblock %}

Organizing JavaScript Files

public/js/
├── app.js           # Main application code
├── components/
│   ├── modal.js     # Modal functionality
│   ├── dropdown.js  # Dropdown functionality
│   └── tooltip.js   # Tooltip functionality
├── pages/
│   ├── dashboard.js # Dashboard logic
│   ├── users.js     # User management
│   └── forms.js     # Form handling
└── vendor/
    ├── jquery.min.js
    └── chart.min.js

Image Assets

Basic Images

<!-- Logo -->
<img src="{{ asset('images/logo.png') }}" alt="Company Logo">

<!-- Hero image -->
<img src="{{ asset('images/hero-banner.jpg') }}" 
     alt="Hero Banner" 
     class="hero-image">

<!-- User avatar -->
<img src="{{ asset('images/avatars/default.png') }}" 
     alt="User Avatar" 
     class="avatar">

Responsive Images

<picture>
    <source media="(min-width: 1200px)" 
            srcset="{{ asset('images/hero-large.jpg') }}">
    <source media="(min-width: 768px)" 
            srcset="{{ asset('images/hero-medium.jpg') }}">
    <img src="{{ asset('images/hero-small.jpg') }}" 
         alt="Hero Image">
</picture>

Background Images in CSS

In your CSS files, use relative paths:
/* public/css/app.css */
.hero {
    background-image: url('../images/hero.jpg');
}

.icon-user {
    background-image: url('../images/icons/user.svg');
}

Dynamic User Images

{% for user in users %}
    <div class="user-card">
        {% if user.avatar %}
            <img src="{{ asset('images/users/' ~ user.avatar) }}" 
                 alt="{{ user.name }}">
        {% else %}
            <img src="{{ asset('images/default-avatar.png') }}" 
                 alt="Default Avatar">
        {% endif %}
        <h3>{{ user.name }}</h3>
    </div>
{% endfor %}

Other Asset Types

Fonts

<!-- In templates -->
<style>
    @font-face {
        font-family: 'CustomFont';
        src: url('{{ asset('fonts/custom-font.woff2') }}') format('woff2'),
             url('{{ asset('fonts/custom-font.woff') }}') format('woff');
    }
</style>
Or in CSS:
/* public/css/fonts.css */
@font-face {
    font-family: 'CustomFont';
    src: url('../fonts/custom-font.woff2') format('woff2');
}

Downloadable Files

<a href="{{ asset('downloads/user-guide.pdf') }}" download>
    Download User Guide
</a>

<a href="{{ asset('downloads/report.xlsx') }}" download>
    Download Report
</a>

Favicons

<!-- templates/base.html -->
<head>
    <link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}">
    <link rel="icon" type="image/png" sizes="32x32" 
          href="{{ asset('images/favicon-32x32.png') }}">
    <link rel="apple-touch-icon" sizes="180x180" 
          href="{{ asset('images/apple-touch-icon.png') }}">
</head>

Asset Versioning

Automatic Cache Busting

When versioning is enabled (default), asset URLs include a version parameter:
<link href="/css/app.css?v=a3f8b9c2" rel="stylesheet">

How Versioning Works

  1. File exists: MD5 hash of modification timestamp
    File modified: 1709654321
    Hash: md5("1709654321") = "a3f8b9c2..."
    URL: /css/app.css?v=a3f8b9c2
    
  2. File not found: Current timestamp
    URL: /css/app.css?v=1709654400
    

Disabling Versioning

<!-- No version parameter -->
<link href="{{ asset('css/external.css', versioning=False) }}" rel="stylesheet">

<!-- Output: /css/external.css -->
Use this for:
  • External CDN assets
  • Files that should never cache-bust
  • Development/testing scenarios

Benefits of Versioning

  • Automatic updates: Browsers fetch new versions when files change
  • Optimal caching: Unchanged files remain cached
  • No manual intervention: Version updates automatically
  • CDN compatible: Works with content delivery networks

Configuration

Configure asset settings in config/settings.yaml:
# Base URL for asset generation
base_url: "http://localhost:8000"

# Public directory path
public_path: "public"
For production:
base_url: "https://www.example.com"
public_path: "/var/www/app/public"

Best Practices

1. Organize Assets by Type

public/
├── css/
├── js/
├── images/
├── fonts/
└── downloads/

2. Use Descriptive Names

Good:
- dashboard-chart.js
- user-profile-header.css
- icon-settings.svg

Avoid:
- script1.js
- style.css
- img.png

3. Optimize Images

  • Use appropriate formats (JPEG for photos, PNG for graphics, SVG for icons)
  • Compress images before deployment
  • Consider using responsive images for different screen sizes

4. Minimize HTTP Requests

<!-- Instead of multiple small CSS files -->
<link href="{{ asset('css/component1.css') }}" rel="stylesheet">
<link href="{{ asset('css/component2.css') }}" rel="stylesheet">
<link href="{{ asset('css/component3.css') }}" rel="stylesheet">

<!-- Combine into one file -->
<link href="{{ asset('css/components.min.css') }}" rel="stylesheet">

5. Load Scripts at the End

<!DOCTYPE html>
<html>
<head>
    <!-- CSS in head for faster rendering -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
    {% block content %}{% endblock %}
    
    <!-- Scripts at end for faster page load -->
    <script src="{{ asset('js/app.js') }}"></script>
    {% block scripts %}{% endblock %}
</body>
</html>
<!-- Use CDN for common libraries -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>

<!-- Use asset() for your custom code -->
<script src="{{ asset('js/app.js') }}"></script>

Complete Example

<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}My App{% endblock %}</title>
    
    <!-- Favicon -->
    <link rel="icon" href="{{ asset('favicon.ico') }}">
    
    <!-- Fonts -->
    <link href="{{ asset('fonts/fonts.css') }}" rel="stylesheet">
    
    <!-- CSS -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
    {% block stylesheets %}{% endblock %}
</head>
<body>
    <header>
        <img src="{{ asset('images/logo.png') }}" alt="Logo" class="logo">
        <nav>
            <a href="{{ url_for('home') }}">Home</a>
            {% if current_user %}
                <img src="{{ asset('images/avatars/' ~ current_user.avatar) }}" 
                     alt="{{ current_user.name }}" 
                     class="avatar-small">
            {% endif %}
        </nav>
    </header>
    
    <main>
        {% block content %}{% endblock %}
    </main>
    
    <footer>
        <p>&copy; 2024 My App</p>
    </footer>
    
    <!-- JavaScript -->
    <script src="{{ asset('js/app.js') }}"></script>
    {% block scripts %}{% endblock %}
</body>
</html>
<!-- templates/dashboard/index.html -->
{% extends "base.html" %}

{% block title %}Dashboard{% endblock %}

{% block stylesheets %}
    <link href="{{ asset('css/dashboard.css') }}" rel="stylesheet">
    <link href="{{ asset('css/charts.css') }}" rel="stylesheet">
{% endblock %}

{% block content %}
    <div class="dashboard">
        <img src="{{ asset('images/dashboard-hero.jpg') }}" alt="Dashboard" class="hero">
        
        <div class="stats">
            <!-- Dashboard content -->
        </div>
    </div>
{% endblock %}

{% block scripts %}
    <script src="{{ asset('js/charts.js') }}"></script>
    <script src="{{ asset('js/dashboard.js') }}"></script>
{% endblock %}

Next Steps

Build docs developers (and LLMs) love