How many redirects you need
The number of redirects required depends on whether the product is versioned.- Unversioned products
- Versioned products
For unversioned products (e.g., HCP cloud products), add one redirect:This single redirect ensures requests to the old URL re-route to the new URL.
Redirect file location
Each docset has its ownredirects.jsonc file:
content/vault/v1.20.x/redirects.jsonc.
Only the most recent redirect file matters. The developer.hashicorp.com platform compiles redirects only from the most recent redirect file. You must carry forward (perpetuate) any backfacing redirects into each new docset, or the new version will forget how to handle them.
Definitions
| Term | Definition |
|---|---|
| Docset | A collection of docs for a specific product and version. For example, vault/docs/v1.20.x lives under content/vault/1.20.x/. |
| Containing docset | The docset associated with a specific redirect definition file. |
| Standard redirect | Redirects an unversioned URL that no longer exists in the containing docset to a different URL in the same docset. |
| Versioned redirect | Redirects an unversioned URL to a different URL in another docset (a different version). |
| Backfacing redirect | Redirects invalid versioned URLs that use valid paths from the containing docset to appropriate URLs in other docsets. |
Slug types
Three types of slugs can be used in redirect source paths.Placeholders
Placeholders
Placeholders match exactly one path segment.
- Source definition:
:<name> - Destination use:
:<name>
/path/:slug matches path/subpath but not path, path/, or path/subpath/another.Wildcards
Wildcards
Wildcards match the root path (with or without a trailing slash) and all subpaths.
- Source definition:
:<name>* - Destination use:
:<name>*
/path/:slug* matches path, path/, path/subpath, and path/subpath/another.Named path parameters
Named path parameters
Named parameters match a pattern or non-capture group. They can match a single path segment, multiple segments, or all subpaths.
- Source definition:
:<name>(<pattern or non-capture group>) - Destination use:
:<name>
/path/:slug(1\.(?:9|1[0-5])\.x) matches path/1.9.x through path/1.15.x.Special characters in patterns
| Character | Description |
|---|---|
( and ) | Wraps parameter definitions and non-capture groups |
[ and ] | Wraps single-character ranges |
- | Defines a single-character range (numbers or letters) |
\ | Indicates a predefined character class |
$ | Matches a pattern to the end of a string |
. | Matches any single character |
* | Matches a pattern zero or more times |
+ | Matches a pattern one or more times |
? | Matches a pattern zero or one times |
{ min, max } | Matches a pattern min or more times, up to an optional max |
: | Starts a parameter definition |
?: | Starts a non-capture group |
?! | Starts a negative look-ahead non-capture group |
| | Separates alternatives in a non-capture group |
\\. For example, escape the . in version strings as \\..
Predefined character classes
| Notation | Matches |
|---|---|
\d | Single digits (0–9) |
\D | Non-digits |
\w | Any word character (alphanumeric and underscore) |
\W | Non-word characters including most special characters |
\s | Whitespace characters |
\S | Non-whitespace characters |
Example redirects
Basic redirects
Pattern matching
Versioned redirects
In this example, you want to movestate.mdx to a new concepts/ directory, changing the URL from /terraform/state to /terraform/concepts/state in Terraform v1.10.x and above.
Three redirects are required to cover all user scenarios:
Non-capture groups
Negative look-ahead
Redirect alldocs/agent/ paths except docs/agent/autoauth/ to /agent-and-proxy/agent/:
Limitations and gotchas
- Only the most recent redirect file is used. The platform compiles redirects only from the most recent redirect file. You must perpetuate backfacing redirects into every new docset.
- You cannot split redirects across multiple files. All redirects for a docset must live in a single
redirects.jsoncfile. - Non-capture groups for subpaths require a trailing slash. A source like
/path/:slug(.*)works for/path/path1and/path/but not for/path(no trailing slash). Use/path:slug(/?.*)to capture both forms.