## What
Fixes three classes of invalid inline HTML in hand-written docs, all of
which
render incorrectly (or only render by accident) today. Found via a
systematic,
markdown-aware audit of every `.md` under `docs/` (ignores code blocks,
inline
code, comments, and autolinks), so this is a complete sweep of the
hand-written
surface, not a spot fix.
## Changes
1. **`<kdb>` → `<kbd>` (72 tags).** The keyboard element is `<kbd>`;
`<kdb>` is
a typo that is not a real element, so renderers drop/mangle it and the
keystrokes lose their styling. Corrected across the IDE access guides
(`cursor.md`, `windsurf.md`, `antigravity.md`). The correct `<kbd>` is
already used in the JetBrains Gateway guide.
2. **Unclosed `<div class="tabs">` in `docs/admin/users/idp-sync.md`.**
The
"Provider-Specific Guides" section opened a `.tabs` container (rendered
as
the `DocsTabs` component) that was never closed, so the wrapper leaked
over
the rest of the page. Added the missing `</div>` before `## Next Steps`,
matching the three other tab sections in the same file.
3. **`<Image>` → `<img>` (6 tags).** `<Image>` is not a registered docs
component — it renders only because the HTML5 parser rewrites the legacy
`<image>` tag to `<img>`. Converted to lowercase `<img>` for correctness
and
clarity; rendering is unchanged. (`organizations.md`, `idp-sync.md`,
`add-envbuilder.md`.)
## Scope / what is intentionally not here
- **Generated reference docs.** The audit also found swallowed
placeholders in
generated pages (`<server>` in `reference/api/{chats,schemas}.md`;
`<glob>`/`<host>` in `agent-firewall`; `<region>` in `server`). Those
are
fixed at the generator source (codersdk comments / CLI flag help) and
tracked
in DOCS-551.
- **`<b>Resource<b>`** in the generated audit-logs table was fixed
separately in
#27293 (merged) and is not duplicated here.
- **`<children></children>`** is an intentional, renderer-implemented
docs
component (child-page card grid) with no HTML equivalent, so it is left
as-is.
It is well-formed; a follow-up CI checker will still verify its
open/close
balance.
A follow-up adds CI enforcement so invalid inline HTML can't regress.
<details>
<summary>Verification</summary>
Run against the changed files:
- `markdownlint-cli2` — 0 errors
- `markdown-table-formatter --check` — no changes needed
- `typos --config .github/workflows/typos.toml` — clean
- Re-running the audit scanner: hand-written `unclosed`, `<kdb>`, and
capitalized-component findings all drop to 0 (only the generated-doc
placeholders tracked in DOCS-551 remain).
</details>
## Linear
DOCS-581:
https://linear.app/codercom/issue/DOCS-581/audit-and-fix-all-invalid-html-across-the-docs
> This PR was created with AI assistance (Coder Agents).
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.*
Add `--no-wildcard` (`CODER_CONFIGSSH_NO_WILDCARD`) to `coder
config-ssh` that generates an individual `Host` entry per workspace
instead of a single wildcard block (`Host *.coder`).
The wildcard approach cannot be enumerated by third-party SSH clients,
the VS Code Remote-SSH sidebar, or scripts that parse `~/.ssh/config` to
discover hosts. With `--no-wildcard`, each workspace gets its own entry
so those tools work without Coder-specific extensions.
The flag is persisted in the config section header so re-running without
it prompts the user about the option change. Workspaces are fetched with
pagination before writing so the diff shows actual hostnames.
## Manual testing
**Unit tests (no server needed):**
```sh
go test ./cli/ -run TestSSHConfigOptions_writeToBuffer -v
go test ./cli/ -run TestConfigSSH_NoWildcard -v
```
**End-to-end with a dev server:**
1. Build: `go build -o ./coder .`
2. Start dev server in a separate terminal: `./scripts/develop.sh`
3. Log in: `./coder login http://localhost:3000`
4. Create two workspaces
5. Run both variants into temp files:
```sh
./coder config-ssh --no-wildcard --hostname-suffix coder --ssh-config-file /tmp/test-ssh-config --yes
./coder config-ssh --hostname-suffix coder --ssh-config-file /tmp/test-ssh-config-wildcard --yes
diff /tmp/test-ssh-config-wildcard /tmp/test-ssh-config
```
<details>
<summary>Output: <code>--no-wildcard</code></summary>
```
# ------------START-CODER-----------
# This section is managed by coder. DO NOT EDIT.
#
# You should not hand-edit this section unless you are removing it, all
# changes will be lost when running "coder config-ssh".
#
# Last config-ssh options:
# :hostname-suffix=coder
# :no-wildcard=true
#
Host coder.myworkspace
ConnectTimeout=0
StrictHostKeyChecking=no
UserKnownHostsFile=/dev/null
LogLevel ERROR
ProxyCommand <coder> --global-config <config> ssh --stdio --ssh-host-prefix coder. %h
Host coder.myworkspace2
ConnectTimeout=0
StrictHostKeyChecking=no
UserKnownHostsFile=/dev/null
LogLevel ERROR
ProxyCommand <coder> --global-config <config> ssh --stdio --ssh-host-prefix coder. %h
Host myworkspace.coder
ConnectTimeout=0
StrictHostKeyChecking=no
UserKnownHostsFile=/dev/null
LogLevel ERROR
Match host myworkspace.coder !exec "<coder> connect exists %h"
ProxyCommand <coder> --global-config <config> ssh --stdio --hostname-suffix coder %h
Host myworkspace2.coder
ConnectTimeout=0
StrictHostKeyChecking=no
UserKnownHostsFile=/dev/null
LogLevel ERROR
Match host myworkspace2.coder !exec "<coder> connect exists %h"
ProxyCommand <coder> --global-config <config> ssh --stdio --hostname-suffix coder %h
# ------------END-CODER------------
```
</details>
<details>
<summary>Output: wildcard (default)</summary>
```
# ------------START-CODER-----------
# This section is managed by coder. DO NOT EDIT.
#
# You should not hand-edit this section unless you are removing it, all
# changes will be lost when running "coder config-ssh".
#
# Last config-ssh options:
# :hostname-suffix=coder
#
Host coder.*
ConnectTimeout=0
StrictHostKeyChecking=no
UserKnownHostsFile=/dev/null
LogLevel ERROR
ProxyCommand <coder> --global-config <config> ssh --stdio --ssh-host-prefix coder. %h
Host *.coder
ConnectTimeout=0
StrictHostKeyChecking=no
UserKnownHostsFile=/dev/null
LogLevel ERROR
Match host *.coder !exec "<coder> connect exists %h"
ProxyCommand <coder> --global-config <config> ssh --stdio --hostname-suffix coder %h
# ------------END-CODER------------
```
</details>
<details>
<summary>diff wildcard → --no-wildcard</summary>
```diff
8a9
> # :no-wildcard=true
10c11
< Host coder.*
---
> Host coder.myworkspace
17c18
< Host *.coder
---
> Host coder.myworkspace2
21a23
> ProxyCommand <coder> ssh --stdio --ssh-host-prefix coder. %h
23c25,31
< Match host *.coder !exec "<coder> connect exists %h"
---
> Host myworkspace.coder
> ConnectTimeout=0
> StrictHostKeyChecking=no
> UserKnownHostsFile=/dev/null
> LogLevel ERROR
>
> Match host myworkspace.coder !exec "<coder> connect exists %h"
```
</details>
Closes https://github.com/coder/coder/issues/17153 (Phase 1: CLI flag)
This pull-request follows up #22060
Felt wrong to only make use of Geist when there is a Monospace variant
here too. Felt best we default to this as the default font as its inline
with the rest of the application. This also updates the lower line for
Workspace Statistics 🙂
Closes#21130
Adds documentation for Google Antigravity IDE integration, following the
same pattern as Cursor and Windsurf (dedicated page for desktop IDEs).
**Changes:**
- `docs/user-guides/workspace-access/antigravity.md` — New dedicated
page with install guide, Coder extension setup, and template
configuration example using the [Antigravity registry
module](https://registry.coder.com/modules/coder/antigravity)
- `docs/user-guides/workspace-access/index.md` — Added Antigravity IDE
section alongside Cursor and Windsurf
- `docs/manifest.json` — Added sidebar navigation entry after Windsurf
Antigravity uses the `antigravity://` protocol (added in #20873) and the
built-in `/icon/antigravity.svg` icon (added in #21068). The [registry
module](https://registry.coder.com/modules/coder/antigravity) wraps
`vscode-desktop-core` with `protocol = "antigravity"`.
Created on behalf of @matifali
Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
Remove the warning about JetBrains Toolbox not persisting log level
configuration between restarts.
As of JetBrains Toolbox 3.2, log level configuration now persists
between restarts, making this warning outdated.
Created on behalf of @matifali
Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
I just added support for rendering GFM alerts inside of numbered lists
in coder.com (see https://github.com/coder/coder.com/pull/328), and
noticed that these plain blockquotes should probably be alerts.
This should cover all the missing alerts. I found them by searching for
the regex `^\s*>\s` within docs/**/*.md
Is `[!NOTE]` the correct type for these? Or do we want to use
tip/important/etc?
- @mtojek CONTRIBUTING.md
- @johnstcn support-bundle.md
- @matifali gateway.md
As part of an information architecture overhaul, this PR reorganizes the
About section and adds a Support section (but not content to it yet)
[preview](https://coder.com/docs/@docs-ia-about/about)
this PR is intentionally limited in scope so that we can ship meaningful
changes faster and followup PRs should include:
- [ ] edit + overhaul the About page
- [ ] decide on the `start` directory
- [ ] ~screenshots page updates~ (this should happen July or later)
redirects PR: https://github.com/coder/coder.com/pull/944
---------
Co-authored-by: EdwardAngert <17991901+EdwardAngert@users.noreply.github.com>
fixes https://github.com/coder/internal/issues/627
Adds docs for `coder://` URLs for Windows Remote Desktop (RDP).
Note that we might want to hold of merging since the URI handling is
unreleased in Coder Desktop for Windows.