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.*
6.7 KiB
Reusing template code
To reuse code across different Coder templates, such as common scripts or resource definitions, we suggest using Terraform Modules.
You can store these modules externally from your Coder deployment, like in a git repository or a Terraform registry. This example shows how to reference a module from your template:
data "coder_workspace" "me" {}
module "coder-base" {
source = "github.com/my-organization/coder-base"
# Modules take in variables and can provision infrastructure
vpc_name = "devex-3"
subnet_tags = { "name": data.coder_workspace.me.name }
code_server_version = 4.14.1
}
resource "coder_agent" "dev" {
# Modules can provide outputs, such as helper scripts
startup_script=<<EOF
#!/bin/sh
${module.coder-base.code_server_install_command}
EOF
}
Learn more about creating modules and module sources in the Terraform documentation.
Coder modules
Coder publishes plenty of modules that can be used to simplify some common tasks across templates. Some of the modules we publish are,
For a full list of available modules please check Coder module registry.
Offline installations
In offline and restricted deployments, there are three ways to fetch modules.
- Artifactory Remote Terraform Repository (Recommended)
- Artifactory Local Repository (manual publishing)
- Private git repository
Artifactory Remote Terraform Repository (Recommended)
Configure Artifactory as a Remote Terraform Repository that proxies and caches the Coder registry. This approach provides automatic updates and requires no manual synchronization.
See Mirror the Coder Registry with JFrog Artifactory for complete setup instructions.
Artifactory Local Repository
Air-gapped users can clone the coder/registry repo and publish a local terraform module repository to resolve modules via Artifactory.
-
Create a local-terraform-repository with name
coder-modules-local -
Create a virtual repository with name
tf -
Follow the below instructions to publish coder modules to Artifactory
git clone https://github.com/coder/registry cd registry/registry/coder/modules jf tfc jf tf p --namespace="coder" --provider="coder" --tag="1.0.0" -
Generate a token with access to the
tfrepo and set anENVvariableTF_TOKEN_example.jfrog.io="XXXXXXXXXXXXXXX"on the Coder provisioner. -
Create a file
.terraformrcwith following content and mount at/home/coder/.terraformrcwithin the Coder provisioner.provider_installation { direct { exclude = ["registry.terraform.io/*/*"] } network_mirror { url = "https://example.jfrog.io/artifactory/api/terraform/tf/providers/" } } -
Update module source as:
module "module-name" { source = "https://example.jfrog.io/tf__coder/module-name/coder" version = "1.0.0" agent_id = coder_agent.example.id ... }Replace
example.jfrog.iowith your Artifactory URL
Based on the instructions here.
Example template
We have an example template here that uses our JFrog Docker template as the underlying module.
Private git repository
If you are importing a module from a private git repository, the Coder server or provisioner needs git credentials. Since this token will only be used for cloning your repositories with modules, it is best to create a token with access limited to the repository and no extra permissions. In GitHub, you can generate a fine-grained token with read only access to the necessary repos.
If you are running Coder on a VM, make sure that you have git installed and
the coder user has access to the following files:
# /home/coder/.gitconfig
[credential]
helper = store
# /home/coder/.git-credentials
# GitHub example:
https://your-github-username:your-github-pat@github.com
If you are running Coder on Docker or Kubernetes, git is pre-installed in the
Coder image. However, you still need to mount credentials. This can be done via
a Docker volume mount or Kubernetes secrets.
Passing git credentials in Kubernetes
First, create a .gitconfig and .git-credentials file on your local machine.
You might want to do this in a temporary directory to avoid conflicting with
your own git credentials.
Next, create the secret in Kubernetes. Be sure to do this in the same namespace that Coder is installed in.
export NAMESPACE=coder
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: git-secrets
namespace: $NAMESPACE
type: Opaque
data:
.gitconfig: $(cat .gitconfig | base64 | tr -d '\n')
.git-credentials: $(cat .git-credentials | base64 | tr -d '\n')
EOF
Then, modify Coder's Helm values to mount the secret.
coder:
volumes:
- name: git-secrets
secret:
secretName: git-secrets
volumeMounts:
- name: git-secrets
mountPath: "/home/coder/.gitconfig"
subPath: .gitconfig
readOnly: true
- name: git-secrets
mountPath: "/home/coder/.git-credentials"
subPath: .git-credentials
readOnly: true