Redirects
Smeldr treats redirects as first-class content. There are two layers: compile-time rules you declare in code, and a runtime table an agent or operator manages live over MCP while the server runs — no redeploy required for either.
Layer 1 — compile-time rules
Use app.Redirect for individual rules you know at build time:
app.Redirect("/old-path", "/new-path", smeldr.Permanent) // 301 Moved Permanently
app.Redirect("/removed", "", smeldr.Gone) // 410 Gone
smeldr.Permanent vs smeldr.Gone
| Code | Constant | When to use |
|---|---|---|
| 301 | smeldr.Permanent | URL has moved permanently; search engines should follow and update |
| 410 | smeldr.Gone | Content is intentionally removed; 410 de-indexes faster than 404 |
Module prefix rewrite
When you rename a module's entire URL prefix, use the smeldr.Redirects option inside app.Content. A single rule covers every URL under the old prefix:
app.Content(&BlogPost{},
smeldr.At("/articles"),
smeldr.Redirects(smeldr.From("/posts"), "/articles"),
)
/posts/hello → 301 → /articles/hello.
Layer 2 — runtime management
Activate database-backed redirects with one call:
if err := app.Redirects(db); err != nil {
log.Fatal(err)
}
app.Redirects(db) does three things:
1. Creates the smeldr_redirects table if it does not exist. 2. Loads any saved rules into the in-memory store immediately. 3. Enables three MCP redirect tools (Editor role required).
MCP tools
| Tool | Required params | Optional params | What it does |
|---|---|---|---|
create_redirect | from (path) | to, code (301/302/410), is_prefix | Create or update a rule; takes effect immediately |
list_redirects | — | — | List all rules (compile-time and database) |
delete_redirect | from (path) | — | Remove a rule; takes effect immediately |
create_redirect defaults to code: 301. Set code: 410 and omit to for a Gone rule. Set is_prefix: true to match any path that starts with from.
CLI equivalents
smeldr-cli redirect list
smeldr-cli redirect create --from /pricing --to /plans
smeldr-cli redirect create --from /sale --to /offers --code 302
smeldr-cli redirect create --from /old-blog --code 410
smeldr-cli redirect create --from /posts --to /articles --prefix
smeldr-cli redirect delete /pricing
Behaviour guarantees
Chain collapse
Adding A → B and then B → C automatically rewrites the stored A → B into A → C. Every visitor gets a single redirect hop. The maximum collapse depth is 10. Gone destinations are terminal — chains never collapse through a 410.
Longest-match-first for prefix rules
Prefix rules are scanned from most-specific to least-specific.
Zero overhead on real routes
The redirect store is a fallback handler at /. It is only reached when a request matches no other registered route.
Redirect manifest
GET /.well-known/redirects.json exposes the full rule set as JSON. Optionally restrict it:
app.RedirectManifestAuth(smeldr.BearerHMAC(secret, smeldr.Editor))