Languages, URLs and Parameters¶
Ekit allows you to build monolingual or multilingual websites without duplicating templates.
The displayed language, page, and content are automatically determined from the URL.
This document explains the URL model, language handling, and content parameters used by Ekit.
URL structure¶
Ekit uses a clean and SEO-friendly routing system based on path segments.
/[lang]/[view]/[slug]?param=value
lang(optional): language code (en,fr,de, …)view: page name (template)slug(optional): identifies a specific recordparam=value(optional): query parameters for filtering or dynamic behavior
Examples¶
URLs always start with a leading
/.
This keeps routes explicit, predictable, and aligned with standard web routing conventions.
Routing rules¶
- The language segment is optional
- If present, the first segment defines the active language — only when it is one of the project's languages
- The first page segment maps to the current view
- If no view is present,
indexis used by default - The second page segment is used as the slug
- Query parameters are optional and used for filtering or additional behavior
Route resolution¶
Example URL:
/fr/blog/my-article
Resolved parameters:
params = { lang: "fr", view: "blog", slug: "my-article" }
Language detection¶
The language is automatically inferred from the first URL segment.
- If the first segment matches a configured language → it is used
- Otherwise → the project’s default language is applied, and the first segment is read as the page name
This allows: - monolingual projects without configuration - shared templates across multiple languages
Language examples¶
| URL | Language | View | Slug |
|---|---|---|---|
| /fr/blog/ | fr | blog | — |
| /fr/blog/post/ | fr | blog | post |
| /blog/post/ | defaultLang | blog | post (multilingual site: redirected to /en/blog/post/, see below) |
| / | defaultLang | index | — |
| /de/blog/ (German not in the project) | defaultLang | de |
— → 404, no page named de |
Unknown language codes¶
If the first segment looks like a language but is not one of the project's languages:
/it/blog
it is read as a page name. Unless your site has a page called it, the address returns a 404. A language removed from a project therefore makes its old addresses return 404, which is what search engines expect.
Canonical addresses (redirects)¶
On a multilingual site, each page has one official address: /{language}/{page}/{slug}/, in lowercase and with a trailing slash. On the public address of the site, any other form of an existing page is redirected (301) to it, query string included:
| Requested | Redirected to |
|---|---|
/blog |
/en/blog/ (default language) |
/en/blog |
/en/blog/ |
/EN/blog/ |
/en/blog/ |
/en/index |
/en/ |
/en/blog/my-article/anything |
/en/blog/my-article/ |
/blog?utm_source=x |
/en/blog/?utm_source=x |
Visitors and search engines always land on the same address, so a page is never indexed twice. The Studio preview and single-language sites are not affected. An address that matches no page is not redirected: it returns a 404 directly.
Links in your templates
Write internal links with the language and the trailing slash (/{{lang}}/blog/): they are served directly, without a redirect.
The <base> tag in the layout (recommended)¶
To ensure correct navigation between pages and languages, define a base URL in your layout.
In layouts/layout.hbs, inside the <head> section:
This guarantees consistent navigation and prevents malformed URLs when mixing relative and root-relative links.
Linking pages and languages¶
Always use root-relative links (starting with /).
Language switcher example¶
langs holds the project's languages (for example ["en", "fr"]). Build the switcher from it, so it only shows languages that exist, and hide it when the project has a single language:
{{#if langs.[1]}}
<ul>
{{#each langs}}
<li><a href="/{{this}}/" {{#if (eq this @root.lang)}}aria-current="true"{{/if}}>{{upper this}}</a></li>
{{/each}}
</ul>
{{/if}}
Linking to a page¶
Linking to a specific content (slug)¶
URL parameters (query string)¶
Query parameters can be used for filtering or dynamic behavior.
They are available in templates via the query object.
Handlebars example¶
Recommended pattern: slug-based content¶
Ekit uses slug-based routing as the primary way to identify content.
Example:
/fr/blog/my-article
In your datasource:
UID support (optional)¶
You can still use a uid when needed (internal or legacy usage).
datasources: article: from: blog uid: "{{query.uid}}"
Example:
/blog?uid=123
However, using slugs is recommended for:
- SEO
- readability
- clean URLs
In templates¶
Routing values are accessible in templates:
Best practices¶
- Use the path for navigation (
lang,view,slug) - Use the query string for filtering or optional flags
- Prefer slug over uid for content identification
- Keep templates simple and data-driven
- Use a single view for list and detail pages when possible
Summary¶
- Ekit uses clean, SEO-friendly URLs
- Language is inferred automatically
- Routing is based on
lang / view / slug - Slugs are the primary way to identify content
- Query parameters are optional and complementary
- Templates are shared across all languages
This model keeps projects simple, scalable, and easy to maintain.