Normalizes non-standard code-fence language tags across `docs/**` so a strict highlighter (Shiki, used by Fumadocs) won't fail the build on an unrecognized language, and unifies redundant synonym tags onto one canonical form per language. The current renderer (Speed-Highlight) detects the language from the code content, not the fence label, so this drift wasn't visible until now. ## Changes - `hcl` -> `tf` (199 fences, including indented ones nested in numbered/bulleted lists). Shiki ships `hcl` and `terraform` as two distinct grammars (not aliases); every `hcl`-tagged fence in `docs/**` is actually Terraform resource/data/provider syntax, so the more specific `terraform` grammar is correct for all of them. `tf` is Shiki's own alias for that grammar, and it's also what GitHub's own markdown renderer resolves to the same HCL/Terraform highlighting. - `pwsh`/`powershell` -> `ps1`. Both `ps` and `ps1` are registered PowerShell aliases in Shiki, but on GitHub's renderer only `.ps1` is a registered file extension (`.ps` isn't), so `ps1` renders identically to `powershell` there today while bare `ps` would silently lose highlighting. - `env` -> `dotenv` (a dedicated Shiki grammar for `KEY=VALUE` files) - `text`/`output`/`none`/`url` -> `txt`. Same built-in plain-text fallback either way, just shorter. - `Dockerfile` -> `dockerfile` (lowercase) - `bash`/`shell` -> `sh` (732 fences). Shiki and GitHub both alias all three to a single shell grammar; this was already the style guide's stated preference, just not enforced across the existing corpus until now. - `markdown` -> `md` (4 fences). Alias of the same grammar in both Shiki and GitHub. - `jsonc` -> `json` (1 fence). The block has no comments or trailing commas, so it doesn't need the comments-capable grammar. - `ts` -> `tsx` (2 fences, `docs/about/contributing/frontend.md`). Verified the actual content tokenizes identically under both grammars, and a sibling block in the same file already needs `tsx` for real JSX, so unifying to one tag is safe for this file. Documented a caveat: `tsx` mis-tokenizes the legacy angle-bracket type-assertion syntax (`<Type>value`), which is invalid in real `.tsx` files anyway, so use `value as Type` instead. - `yml` -> `yaml` (1 fence) - Updated `docs/.style/style-guide/formatting.md` to document all canonical tags `promql` (2 fences) and `caddyfile` (2 fences) are left as-is. Shiki doesn't bundle a grammar for either, so they need a custom grammar registration when the site adopts Shiki, rather than degrading to `txt`. Tracked as follow-up work under DOCS-118 and [DOCS-544](https://linear.app/codercom/issue/DOCS-544/vendor-a-local-promql-grammar-for-shiki-syntax-highlighting) (promql). Does not touch `offlinedocs/`. Linear: [DOCS-476](https://linear.app/codercom/issue/DOCS-476/normalize-docs-code-fence-languages-de-risk-shikifumadocs) <details> <summary>How the fence tags were verified</summary> Each tag was tested against a real `shiki@latest` highlighter instance (`codeToHtml`/`codeToTokens`) and cross-checked against GitHub's `@wooorm/starry-night` grammar sources (the renderer that actually displays these `.md` files today, in repo browsing and PR diffs), since that's what determines whether brevity is safe before Shiki adoption: ```text FAIL env -- Language `env` is not included in this bundle. FAIL Dockerfile -- Language `Dockerfile` is not included in this bundle. FAIL promql -- Language `promql` is not included in this bundle. FAIL caddyfile -- Language `caddyfile` is not included in this bundle. FAIL pwsh -- Language `pwsh` is not included in this bundle. FAIL output -- Language `output` is not included in this bundle. ``` `hcl` doesn't error in Shiki, since it's a real grammar, but that's exactly the trap: it was silently rendering every fence with the generic HCL grammar instead of the Terraform-specific one. Every `hcl`-tagged fence in `docs/**` was manually checked against `origin/main` and is genuinely Terraform content. For `ts`/`tsx`, tokenizing the actual doc content confirmed identical output under both grammars; a synthetic test with the legacy angle-bracket cast syntax confirmed `tsx` degrades on that specific construct, which the style guide now calls out. The first normalization pass only matched fence tags at column 0 (`^```tag$`), missing tags indented inside numbered/bulleted lists. A follow-up pass caught the remaining occurrences at any indentation level. </details> --- *This PR description and the underlying changes were prepared with Coder Agents assistance.*
13 KiB
Parameters
A template can prompt the user for additional information when creating workspaces with parameters.
The user can set parameters in the dashboard UI and CLI.
You'll likely want to hardcode certain template properties for workspaces, such as security group. But you can let developers specify other properties with parameters like instance size, geographical location, repository URL, etc.
This example lets a developer choose a Docker host for the workspace:
data "coder_parameter" "docker_host" {
name = "Region"
description = "Which region would you like to deploy to?"
icon = "/emojis/1f30f.png"
type = "string"
default = "tcp://100.94.74.63:2375"
option {
name = "Pittsburgh, USA"
value = "tcp://100.94.74.63:2375"
icon = "/emojis/1f1fa-1f1f8.png"
}
option {
name = "Helsinki, Finland"
value = "tcp://100.117.102.81:2375"
icon = "/emojis/1f1eb-1f1ee.png"
}
option {
name = "Sydney, Australia"
value = "tcp://100.127.2.1:2375"
icon = "/emojis/1f1e6-1f1f9.png"
}
}
From there, a template can refer to a parameter's value:
provider "docker" {
host = data.coder_parameter.docker_host.value
}
Types
A Coder parameter can have one of these types:
stringboolnumberlist(string)
To specify a default value for a parameter with the list(string) type, use a
JSON array and the Terraform
jsonencode
function. For example:
data "coder_parameter" "security_groups" {
name = "Security groups"
icon = "/icon/aws.png"
type = "list(string)"
description = "Select appropriate security groups."
mutable = true
default = jsonencode([
"Web Server Security Group",
"Database Security Group",
"Backend Security Group"
])
}
Note
Overriding a
list(string)on the CLI is tricky because:
--parameter "parameter_name=parameter_value"is parsed as CSV.parameter_valueis parsed as JSON.So, to properly specify a
list(string)with the--parameterCLI argument, you will need to take care of both CSV quoting and shell quoting.For the above example, to override the default values of the
security_groupsparameter, you will need to pass the following argument tocoder create:--parameter "\"security_groups=[\"\"DevOps Security Group\"\",\"\"Backend Security Group\"\"]\""Alternatively, you can use
--rich-parameter-fileto work around the above issues. This allows you to specify parameters as YAML. An equivalent parameter file for the above--parameteris provided below:security_groups: - DevOps Security Group - Backend Security Group
Options
A string parameter can provide a set of options to limit the user's choices:
data "coder_parameter" "docker_host" {
name = "Region"
description = "Which region would you like to deploy to?"
type = "string"
default = "tcp://100.94.74.63:2375"
option {
name = "Pittsburgh, USA"
value = "tcp://100.94.74.63:2375"
icon = "/emojis/1f1fa-1f1f8.png"
}
option {
name = "Helsinki, Finland"
value = "tcp://100.117.102.81:2375"
icon = "/emojis/1f1eb-1f1ee.png"
}
option {
name = "Sydney, Australia"
value = "tcp://100.127.2.1:2375"
icon = "/emojis/1f1e6-1f1f9.png"
}
}
Incompatibility in Parameter Options for Workspace Builds
When creating Coder templates, authors have the flexibility to modify parameter options associated with rich parameters. Such modifications can involve adding, substituting, or removing a parameter option. It's important to note that making these changes can lead to discrepancies in parameter values utilized by ongoing workspace builds.
Consequently, workspace users will be prompted to select the new value from a pop-up window or by using the command-line interface. While this additional interactive step might seem like an interruption, it serves a crucial purpose. It prevents workspace users from becoming trapped with outdated template versions, ensuring they can smoothly update their workspace without any hindrances.
Example:
- Bob creates a workspace using the
python-devtemplate. This template has a parameterimage_tag, and Bob selects1.12. - Later, the template author Alice is notified of a critical vulnerability in a
package installed in the
python-devtemplate, which affects the image tag1.12. - Alice remediates this vulnerability, and pushes an updated template version
that replaces option
1.12with1.13for theimage_tagparameter. She then notifies all users of that template to update their workspace immediately. - Bob saves their work, and selects the
Updateoption in the UI. As their workspace uses the now-invalid option1.12, for theimage_tagparameter, they are prompted to select a new value forimage_tag.
Required and optional parameters
A parameter is required if it doesn't have the default property. The user
must provide a value to this parameter before creating a workspace:
data "coder_parameter" "account_name" {
name = "Account name"
description = "Cloud account name"
mutable = true
}
If a parameter contains the default property, Coder will use this value if the
user does not specify any:
data "coder_parameter" "base_image" {
name = "Base image"
description = "Base machine image to download"
default = "ubuntu:latest"
}
Admins can also set the default property to an empty value so that the
parameter field can remain empty:
data "coder_parameter" "dotfiles_url" {
name = "dotfiles URL"
description = "Git repository with dotfiles"
mutable = true
default = ""
}
Mutability
Immutable parameters can only be set in these situations:
- Creating a workspace for the first time.
- Updating a workspace to a new template version. This sets the initial value for required parameters.
The idea is to prevent users from modifying fragile or persistent workspace resources like volumes, regions, and so on.
Example:
data "coder_parameter" "region" {
name = "Region"
description = "Region where the workspace is hosted"
mutable = false
default = "us-east-1"
}
If a required parameter is empty or if the workspace creation page detects an incompatibility between selected parameters, the Create workspace button is disabled until the issues are resolved.
Ephemeral parameters
Ephemeral parameters are introduced to users in order to model specific behaviors in a Coder workspace, such as reverting to a previous image, restoring from a volume snapshot, or building a project without using cache. These parameters are settable when creating, starting, updating, or restarting a workspace but do not persist after the workspace is stopped.
Since these parameters are ephemeral in nature, subsequent builds proceed in the standard manner:
data "coder_parameter" "force_rebuild" {
name = "force_rebuild"
type = "bool"
description = "Rebuild the Docker image rather than use the cached one."
mutable = true
default = false
ephemeral = true
}
Validating parameters
Coder supports parameters with multiple validation modes: min, max, monotonic numbers, and regular expressions.
Number
You can limit a number parameter to min and max boundaries.
You can also specify its monotonicity as increasing or decreasing to verify
the current and new values. Use the monotonic attribute for resources that
can't be shrunk or grown without implications, like disk volume size.
data "coder_parameter" "instances" {
name = "Instances"
type = "number"
description = "Number of compute instances"
validation {
min = 1
max = 8
monotonic = "increasing"
}
}
It is possible to override the default error message for a number parameter,
along with its associated min and/or max properties. The following message
placeholders are available {min}, {max}, and {value}.
data "coder_parameter" "instances" {
name = "Instances"
type = "number"
description = "Number of compute instances"
validation {
min = 1
max = 4
error = "Sorry, we can't provision too many instances - maximum limit: {max}, wanted: {value}."
}
}
Note
As of
terraform-provider-coderv0.19.0,optionscan be specified innumberparameters; this also works with validations such asmonotonic.
String
You can validate a string parameter to match a regular expression. The regex
property requires a corresponding error property.
data "coder_parameter" "project_id" {
name = "Project ID"
description = "Alpha-numeric project ID"
validation {
regex = "^[a-z0-9]+$"
error = "Unfortunately, this isn't a valid project ID"
}
}
Workspace presets
Workspace presets allow you to configure commonly used combinations of parameters into a single option, which makes it easier for developers to pick one that fits their needs.
Use the
coder_workspace_preset
data source to define the preset parameters. After you save the template file,
the presets will be available for all new workspace deployments.
Optional preset fields
In addition to the required name and parameters fields, you can enhance your
workspace presets with optional description and icon fields:
- description: A helpful text description that provides additional context about the preset. This helps users understand what the preset is for and when to use it.
- icon: A visual icon displayed alongside the preset name in the UI. Use
emoji icons with the format
/emojis/{code}.png(e.g.,/emojis/1f1fa-1f1f8.pngfor the US flag emoji 🇺🇸).
For a complete list of all available fields, see the Terraform provider documentation.
Expand for an example
data "coder_workspace_preset" "goland-gpu" {
name = "GoLand with GPU"
description = "Development workspace with GPU acceleration for GoLand IDE"
icon = "/emojis/1f680.png"
parameters = {
"machine_type" = "n1-standard-1"
"attach_gpu" = "true"
"gcp_region" = "europe-west4-c"
"jetbrains_ide" = "GO"
}
}
data "coder_workspace_preset" "pittsburgh" {
name = "Pittsburgh"
description = "Development workspace hosted in United States"
icon = "/emojis/1f1fa-1f1f8.png"
parameters = {
"region" = "us-pittsburgh"
"machine_type" = "n1-standard-2"
}
}
data "coder_parameter" "machine_type" {
name = "machine_type"
display_name = "Machine Type"
type = "string"
default = "n1-standard-2"
}
data "coder_parameter" "attach_gpu" {
name = "attach_gpu"
display_name = "Attach GPU?"
type = "bool"
default = "false"
}
data "coder_parameter" "gcp_region" {
name = "gcp_region"
display_name = "GCP Region"
type = "string"
default = "us-central1-a"
}
data "coder_parameter" "jetbrains_ide" {
name = "jetbrains_ide"
display_name = "JetBrains IDE"
type = "string"
default = "IU"
}
data "coder_parameter" "region" {
name = "region"
display_name = "Region"
type = "string"
default = "us-east-1"
}
Create Autofill
When the template doesn't specify default values, Coder may still autofill parameters in one of two ways:
-
Coder will look for URL query parameters with form
param.<name>=<value>.This feature enables platform teams to create pre-filled template creation links.
-
Coder can populate recently used parameter key-value pairs for the user. This feature helps reduce repetition when filling common parameters such as
dotfiles_urlorregion.To enable this feature, you need to set the
auto-fill-parametersexperiment flag:coder server --experiments=auto-fill-parametersOr set the environment variable,
CODER_EXPERIMENTS=auto-fill-parameters
Dynamic Parameters
Coder v2.24.0 introduces Dynamic Parameters to extend the existing parameter system with conditional form controls, enriched input types, and user identity awareness. This feature allows template authors to create interactive workspace creation forms, meaning more environment customization and fewer templates to maintain.
You can read more in the Dynamic Parameters documentation and try it out in the Parameters Playground.

