Prosefly

Guides

Expressive Code

Add Prosefly file icons and language labels to Expressive Code frames.

@prosefly/astro-components/expressive-code is an independent Expressive Code plugin. It does not register astro-expressive-code and is not included by proseflyComponents(). Add it to the plugins option of your own astro-expressive-code integration.

Standalone setup

Install both packages in an Astro project that uses MDX or Markdown code blocks:

Terminal window
pnpm add @prosefly/astro-components astro-expressive-code

Register the plugin with astro-expressive-code:

astro.config.ts
import { defineConfig } from 'astro/config';
import astroExpressiveCode from 'astro-expressive-code';
import { expressiveCodeHeaderIcons } from '@prosefly/astro-components/expressive-code';
export default defineConfig({
integrations: [
astroExpressiveCode({
plugins: [expressiveCodeHeaderIcons()],
}),
],
});

Use with proseflyComponents()

The shared components integration owns icons, Markdown transforms, and gallery assets. It does not own Expressive Code, so register both integrations when you want all of those features:

astro.config.ts
import { defineConfig } from 'astro/config';
import astroExpressiveCode from 'astro-expressive-code';
import proseflyComponents from '@prosefly/astro-components/integration';
import { expressiveCodeHeaderIcons } from '@prosefly/astro-components/expressive-code';
export default defineConfig({
integrations: [
proseflyComponents(),
astroExpressiveCode({
plugins: [expressiveCodeHeaderIcons()],
}),
],
});

Dahlia and Lotus already include it

Dahlia and Lotus configure astro-expressive-code and this plugin for their code blocks. Do not register expressiveCodeHeaderIcons() again in a theme project unless you intentionally replace the theme’s Expressive Code setup.

Behavior

The plugin adds a file-type icon to a code frame header. It derives the icon from the frame title when one is present, then falls back to the code language. Untitled frames also receive a readable language label when one is available. Terminal frames are left unchanged, and light/dark icon variants follow the site’s theme.

Options

apiBase

Set apiBase to an Iconify-compatible endpoint when icons must be loaded from an internal service. It defaults to https://api.iconify.design.

Plugin instance

expressiveCodeHeaderIcons(options?) returns an Expressive Code plugin that can be passed in the integration’s plugins array.

For an Iconify-compatible internal endpoint, pass apiBase when creating the plugin:

typescript
astroExpressiveCode({
plugins: [
expressiveCodeHeaderIcons({
apiBase: 'https://icons.example.com',
}),
],
});

Public API

The /expressive-code entry publicly exports only:

  • expressiveCodeHeaderIcons
  • ExpressiveCodeHeaderIconsOptions

For icon preloading and shared Markdown transforms, use @prosefly/astro-components/integration. The Expressive Code entry remains separate so projects can adopt the plugin without adopting the full shared integration.

Last updated Sep 1, 2026