Astro / Starlight
CodeGloss works with Astro (and Starlight) using the remark plugin in HTML mode. Since Astro renders pages to static HTML, we emit raw <code-gloss> elements and load the runtime via a client-side script.
Install
npm install codeglossConfigure the remark plugin
Add remark-codegloss to your astro.config.mjs with output: 'html'. If you've declared a highlight in codegloss.config.ts (see Syntax Highlighters), thread it through so blocks are pre-highlighted at build:
import starlight from '@astrojs/starlight';
import { defineConfig } from 'astro/config';
import remarkCodegloss from 'codegloss/remark';
import codeglossConfig from './codegloss.config';
export default defineConfig({
integrations: [
starlight({
title: 'My Docs',
head: [
{
tag: 'script',
attrs: { type: 'module', src: '/codegloss.js' },
},
],
sidebar: [
{ label: 'Intro', link: '/intro/' },
],
}),
],
markdown: {
remarkPlugins: [
[
remarkCodegloss,
{ output: 'html', highlight: codeglossConfig.highlight },
],
],
},
});
For plain Astro (without Starlight), add the plugin under the same markdown.remarkPlugins key and load the runtime script in your layout's <head>.
Copy the runtime to public/
Astro serves static assets from public/. Create a prebuild script that copies the CodeGloss runtime there:
// scripts/copy-runtime.mjs
import { copyFile, mkdir, readdir } from 'node:fs/promises';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const here = dirname(fileURLToPath(import.meta.url));
const publicDir = resolve(here, '..', 'public');
await mkdir(publicDir, { recursive: true });
const runtimeEntry = fileURLToPath(import.meta.resolve('codegloss'));
await copyFile(runtimeEntry, resolve(publicDir, 'codegloss.js'));
// Copy any chunk files the runtime imports
const distSrc = dirname(runtimeEntry);
for (const entry of await readdir(distSrc)) {
if (entry.startsWith('chunk-') && entry.endsWith('.js')) {
await copyFile(resolve(distSrc, entry), resolve(publicDir, entry));
}
}
Add it to your build script:
{
"scripts": {
"prebuild": "node ./scripts/copy-runtime.mjs",
"build": "astro build"
}
}
Write annotated code blocks
Use the standard fenced codegloss syntax in any .md or .mdx content file:
```js codegloss fib.js
function fib(n) {
return n < 2 ? n : fib(n - 1) + fib(n - 2);
}
```
```json annotations
{
"annotations": [
{ "id": "a1", "token": "fib", "line": 0, "occurrence": 0,
"title": "Recursion", "text": "Calls itself with smaller inputs." }
]
}
```
The remark plugin transforms these into <code-gloss> HTML elements at build time. The runtime script in the <head> registers the custom element on the client.
Why HTML mode?
Astro processes markdown through remark/rehype and emits static HTML — it doesn't use React or MDX JSX at runtime. The output: 'html' mode tells the plugin to emit raw HTML nodes instead of JSX, which Astro passes through to the final page unchanged.
No CSS import needed
The Web Component bundles its styles via Shadow DOM. There's nothing to add to your global stylesheet.