Routing
In Noventa, routing is handled automatically for you. Any HTML file you put inside the /pages folder will be accessible to your visitors as a static page. For example, creating a file at pages/about.html will make it available at the /about URL. In the case of index.html files they will be served at the root of the folder, so a pages/index.html will become /.
Dynamic Routing
While static pages are useful, many applications require dynamic pages that can display content based on a URL parameter (like a user ID or a blog post slug). Noventa supports dynamic routing out of the box.
To create a dynamic route, you can use brackets [] in either the folder name or the filename. The value of this dynamic segment will be made available inside the context of the components for that page, allowing you to fetch and display data accordingly.
Dynamic Folder Segments
You can create a dynamic route by naming a folder with brackets. For example, a page at pages/blog/[slug]/index.html will match routes like /blog/my-first-post or /blog/hello-world. The value of slug (e.g., "my-first-post") will be passed to the components on that page on the request parameter.
Dynamic Filename Segments
Similarly, you can make the filename itself dynamic. A file named pages/users/[id].html will match routes like /users/123 or /users/abc. The value of id will be available in your components.
Accessing Dynamic Parameters
Dynamic route parameters are accessible in your components through request.view_args. Here's how different route patterns map to view_args:
# Route: /users/[id].html
# URL: /users/123
# view_args: {"id": "123"}
# Route: /blog/[year]/[month]/index.html
# URL: /blog/2024/01
# view_args: {"year": "2024", "month": "01"}
# Route: /products/[category]/[slug].html
# URL: /products/electronics/iphone-15
# view_args: {"category": "electronics", "slug": "iphone-15"}
def load_template_context(request, session, db, **props):
# Access the dynamic parameters
category = request.view_args.get("category")
slug = request.view_args.get("slug")
# Use them to fetch data
product = db.query(Product).filter_by(category=category, slug=slug).first()
return {"product": product}
Route Precedence
When multiple routes could match a URL, Noventa follows these precedence rules:
- Exact matches first: Static routes take precedence over dynamic ones
- Dynamic folder precedence: Dynamic folders override static files in the same directory
- Nested routes: More specific nested routes override general ones
Important Note on Precedence
When a dynamic route is present in a folder, it takes precedence over any other static pages within that same folder. For example, if you have both pages/users/[id].html and pages/users/all.html, the dynamic route will always be matched, and the all.html page will not be rendered.