Statiq Charge: Building Static Sites with Statiq & Python
by Marcin Giziński, CIO
In the ever-evolving world of web development, it's easy to get lost in the plethora of frameworks, libraries, and tools available. Yet, there's something to be said for the power and simplicity of static HTML. Let's explore when and why one might choose static HTML over a more complex framework.
No Frameworks Attached
Static HTML remains a powerful tool in the web developer's arsenal, especially for simpler projects. While frameworks offer robust features and scalability, it's essential to evaluate the actual needs of a project before choosing the right approach. Embracing the strengths of static sites, while being aware of their limitations, can lead to a faster, more reliable, and potentially more secure web experience.
When to Use Static HTML
Simple Websites:
For sites that have a handful of pages with mostly static content, such as personal portfolios, blogs, and small business websites.
Performance:
A static page inherently has fewer elements to process, potentially leading to faster load times.
Limited Resources:
When working on a project with minimal budget or manpower, avoiding the learning curve of a framework might be beneficial.
Teaching Beginners:
For newcomers to web development, starting with the basics provides a solid foundation.
Advantages of Static HTML:
Speed:
Static websites, by nature, are faster as there's no database to query or server-side processing needed before sending the page to the user.
Simplicity
No need to manage the complexities or dependencies of a framework.
Reliability
Fewer components mean fewer things can break.
Cost-Effective
Many hosting providers offer low-cost or even free hosting for static sites. Plus, they're less resource-intensive, which can translate to savings.
Version Control
With platforms like GitHub, it's easy to manage versions of static sites and collaborate with others.
Disadvantages of Static HTML
Scalability Issues
For larger sites or web applications, manually managing multiple HTML files can be cumbersome.
Lack of Dynamic Content
To introduce interactivity or real-time data, you'd need to resort to adding JavaScript, which somewhat defeats the "pure static" concept.
No CMS
Non-tech-savvy users might find it challenging to update content without a Content Management System.
Repetitive Tasks
Elements that appear on multiple pages, like headers and footers, must be updated individually unless using a templating system.
Security Implications
While one might assume that static sites are inherently more secure (given the absence of a database or server-side scripts), it's not quite that simple.
Pros:
Fewer Vulnerabilities
No databases or server-side scripts mean fewer avenues for common attacks like SQL injection.
Immutable
Content isn't changed unless the developer explicitly changes and redeploys it.
Cons:
Client-Side Scripts
If you rely on JavaScript for added functionality, vulnerabilities in the code can still pose risks.
Third-Party Integrations
Incorporating third-party tools or plugins can introduce security issues if not properly vetted.
Harness the hiss - Tutorial
Before diving in, it's worth noting this tutorial assumes familiarity with Python basics, including the use of virtual environments
and pip
.
Installation
To get started with Statiq, first, install it using pip:
pip install statiq
Next, within your project directory, create a pages
directory and an initial index.py
file:
mkdir pages
cd pages
touch index.py
Open the newly created index.py
in your preferred editor and add the following content:
# pages/index.py
from statiq import Page
def page():
return Page(
data={
"title": "Hello World"
}
)
Then, create a templates
directory and an index.html
file within it:
mkdir templates
touch templates/index.html
Edit templates/index.html
to include:
{% extends "base.html" %}
{% block content %}
<h1>{{ title }}</h1>
{% endblock %}
Building Your Website
With your pages and templates set up, you're ready to build your website:
statiq build
Congratulations! You've just created a simple static website. The generated code can be found in the build/
directory. To view your website locally, serve it using Python's HTTP server:
python -m http.server --directory build
Navigate to http://localhost:8000
in your web browser, or use the following command to open the site automatically (on Mac and Linux systems):
open http://localhost:8000
Creating Dynamic Pages with Statiq
Dynamic pages in Statiq are generated based on path parameters, offering a way to create content that adapts to the given context, such as blog posts or product pages. This capability allows for a more flexible site structure, where content can be dynamically served based on user interaction or specific URL paths.
Defining Path Parameters
To create a dynamic page, Statiq uses path parameters defined within square brackets in the filename or folder name. Here's how you can structure your project to include dynamic content:
pages/[post].py
: This will generate a page for each post, accessible through a unique slug (e.g.,build/some-post-slug.html
).pages/[category]/index.py
: This sets up a structure for category pages, where each category's main page can be accessed (e.g.,build/some-category/index.html
).
Setting Up Templates
The `templates` folder should mirror the structure of the `pages` folder to ensure each dynamic page is rendered with the correct template. For instance:
templates/index.html
: The main site template.templates/[post].html
: A template for individual posts.templates/[category]/index.html
: A template for category landing pages.
Creating a Page File
Each .py
file that defines a page should contain a page()
method that returns a Page
object. This object includes all the necessary details to render the page, such as title, description, and content. Here's a basic example:
from statiq import Pagedef page() -> Page:
return Page(
data={
"title": "Welcome to Statiq",
"description": "Statiq is a static site generator",
"content": "Hello world!",
}
)
Utilizing Path Parameters
Path parameters are crucial for generating dynamic content. They are defined as a list of dictionaries passed to the Page
object, which then utilizes these parameters to render different content based on the URL.
from statiq import Page
def page() -> Page:
return Page(
data={
"title": "Dynamic Content",
"description": "Example of a dynamic page",
"content": "Content based on path parameters",
},
path_parameters=[
{"post": "some-post-slug"},
{"category": "some-category"}
]
)
Expanding Path Parameters in Data and Head Properties
For routes utilizing path parameters, these parameters are expanded and passed as keyword arguments to the data
and head
properties, allowing for customized rendering based on the URL.
Example with multiple path parameters:
from statiq import Page
def get_data(**kwargs):
post = kwargs.get("post")
# Dynamic data fetching based on the post parameter
return some_data.json()def get_head(**kwargs):
post = kwargs.get("post")
return [
f"<title>{post} - Dynamic Page</title>",
{"tag": "meta", "attributes": {"name": "description", "content": post}}
]
def page() -> Page:
path_parameters = get_path_parameters()
return Page(
data=get_data,
head=get_head,
path_parameters=path_parameters,
)
The template_path
Property
To specify a custom template for a dynamic page, use the template_path
property within the Page
object. If not defined, Statiq defaults to using index.html
.
from statiq import Page
def page() -> Page:
return Page(
data={"title": "Custom Template Page"},
template_path="custom.html",
)
By following these steps, you can leverage Statiq to create dynamic, content-rich pages that respond to user interactions and display content based on specific criteria, enhancing the overall user experience on your static website.
Including Static Content
Incorporating static assets like images, JavaScript, and CSS into your static website is a common requirement. Statiq simplifies this process by efficiently handling the parsing and copying of these files. Let's dive into how you can manage static files in your Statiq project, using `static.png` as an example file.
Setting Up Static File Management
Configure Static Paths
First, you'll need to specify where your static files are located and where they should be copied to. This is done in the config.py
file of your Statiq project. Open or create your `config.py` and add the following properties:
# config.py
STATIC_PATHS = [
{"path": "src"} # Directory where your static files are located
]
STATIC_OUTPUT_PATH = "output" # Destination directory for the static files
Customize File Selection (Optional)
If you want to filter which files are copied based on their type or any other criteria, you can use the optional regex
property. For example, to only include HTML files, your STATIC_PATHS
configuration might look like this:
STATIC_PATHS = [
{
"path": "src",
"regex": r"(.*)\.html$",
}
]
However, if you're including an image file like `static.png`, you don't need to apply such a filter.
Copying Static Files
With your static paths configured, you're now ready to copy these files to the designated output directory. This is done using a simple command:
statiq static copy
This command tells Statiq to process the directories and files specified in STATIC_PATHS
and copy them to the STATIC_OUTPUT_PATH
. For instance, if static.png
is located in your src
directory, it will be copied to the output
directory, maintaining the directory structure.
Example Use Case
Imagine you have a file named `static.png` in your `src/images` folder. To ensure it gets copied to your output directory, make sure your `config.py` file looks something like this:
# config.py
STATIC_PATHS = [
{"path": "src"} # This includes all files within the src directory
]
STATIC_OUTPUT_PATH = "output" # static.png will be copied to output/images
After running statiq static copy
, static.png
will be available in output/images
, ready to be served alongside your static site.
Conclusion
Managing static files in Statiq is straightforward, thanks to its flexible configuration options. By setting up STATIC_PATHS
and STATIC_OUTPUT_PATH
, you can easily include assets like static.png
in your projects, enhancing the visual and functional aspects of your static website. This process, combined with Statiq's efficiency in generating static pages, provides a robust foundation for developing fast, secure, and visually appealing websites.
Sponsored by Folx, Statiq emerges as a response to the Python community's need for a modern static website generator, offering a robust alternative to popular JavaScript solutions like Next.js and Vue.js, and marking a significant step towards enriching the Python ecosystem with cutting-edge web development tools