Chapter 2
Route Management and URL Architecture
Master the art of designing intuitive, robust, and scalable route architectures using Elder.js. This chapter challenges conventional wisdom on URL management, guiding you through advanced techniques that maximize flexibility, optimize SEO, and facilitate maintainable content structures for even the most complex multilingual or legacy site needs.
2.1 Declarative Route Definitions
Elder.js employs a declarative approach to route configuration that enhances clarity, maintainability, and alignment with modern web architecture patterns. This method enables developers to define both static and dynamic routes concisely while seamlessly integrating with Elder.js's data pipeline, build system, and plugin architecture.
At the core of Elder.js's routing system is the routes directory, where each route is defined as a JavaScript module exporting a route configuration object. The declarative route definition encapsulates metadata, URL patterns, data-fetching strategies, and lifecycle hooks, all aimed at facilitating predictable and efficient static site generation.
A typical route definition consists of the following properties:
- pattern: A URL pattern string or regular expression specifying paths handled by the route.
- all: An asynchronous generator function yielding all route parameters for dynamic routes.
- data: A function that receives route parameters and context, returning an object that populates the data pipeline.
- prerender: A boolean indicating whether the route should be prerendered.
The following example illustrates a basic static route definition for an about page:
module.exports = { pattern: '^/about/?$', data: () => ({ title: 'About Us', description: 'Information about our company' }), prerender: true, }; Here, pattern uses a regular expression to match exactly the URL path /about. The data function returns a static object that will be incorporated into the templating context during rendering. Enabling prerender ensures Elder.js will generate a fully static HTML page for this route during the build process.
Dynamic routes extend this paradigm by parameterizing segments of the path and iterating over possible values. This is facilitated by the all function, which asynchronously yields parameter objects defining all concrete route instances to generate. For example, a blog post route indexed by a slug may be declared as:
module.exports = { pattern: '^/blog/(?<slug>[a-z0-9-]+)/?$', all: async () => { const posts = await fetchPostsFromAPI(); return posts.map(post => ({ slug: post.slug })); }, data: async ({ slug }) => { const post = await fetchPostDetails(slug); if (!post) { return { status: 404 }; } return { ...