⮌ back | Overview | Home

🌟 The Starlight Plugin

The Starlight Plugin from the Bag of Tricks adds view transitions to your Starlight site, bringing smooth animations and a touch of magic to every page change.

See what the plugin did↗ to the Starlight Starter!

Read the whole story behind this plugin at vtbag.dev↗!

If you only want standard cross-fade view transitions, do not install the plugin but do this.

Add view transitions to your existing Starlight site in two simple steps:

Terminal window
cd .../my-starlight-project
npm install -D astro-vtbot
astro.config.mjs
import { defineConfig } from 'astro/config';
import { viewTransitions } from "astro-vtbot/starlight-view-transitions";
export default defineConfig({
integrations: [
starlight({
plugins: [viewTransitions()],
...
...})]
})

You can customize the plugin with additional behavior. These steps are all optional:

The Starlight Plugin provides an easy way to define expect links using a frontmatter filed called renderBlocking. If you do not use this option, you can alternatively use Starlight’s head fields to define such links.

If you want to use the renderBlocking attribute in the markdown frontmatter to tell the browser to wait for a fragment identifier “below the fold”, you need to extend Starlight’s content config.

src/content.config.ts
import { defineCollection, z } from 'astro:content';
import { docsLoader } from '@astrojs/starlight/loaders';
import { docsSchema } from '@astrojs/starlight/schema';
export const collections = {
docs: defineCollection({
loader: docsLoader(),
schema: docsSchema(
{extend: z.object({renderBlocking: z.string().optional()})}
)
}),
};

After that, you can set the renderBlocking attribute in your frontmatter

my-page.mdx
renderBlocking: my-below-the-fold-heading

and the Starlight plugin will automatically add

<link rel="expect" href="#my-below-the-fold-heading" blocking="render" />

to the <head> of your page.

If this option is enabled, the Starlight Plugin will automatically add the end-of-markdown id…at the end of the markdown. If you do note enable the renderBlocking option above or do not define a renderBlocking id on a page, the plugin will automatically insert a render blocking link for you.

<link rel="expect" href="#end-of-markdown" blocking="render" />

So view transitions will not start until the whole content of your page is loaded. This can be convenient for small pages, but might also come with some performance penalties for larger content.

To enable this option, import and include the remarkEndOfMarkdown plugin:

astro.config.mjs
import { defineConfig } from 'astro/config';
import { viewTransitions, remarkEndOfMarkdown } from "astro-vtbot/starlight-view-transitions";
export default defineConfig({
markdown: { remarkPlugins: [remarkEndOfMarkdown] }
integrations: [
starlight({
plugins: [viewTransitions()],
...
...})],
})

Under the hood, the Starlight Plugin installs some of the @vtbag scripts. Those can be configured by setting fields of the plugin’s options object:

OptionPackageScriptScript Option
allPagesturn-signalindex,debug,directiondata-selector↗
directionTypesturn-signalindex,debug,directionsdata-direction-types↗
directionAttributeturn-signalindex,debug,directionsdata-direction-attribute↗
declarativeNamesutensil-drawerdeclarative-namesdata-vtbag-decl↗
camShaftNamescam-shaftindexdata-view-transition-names↗

For example, if you want to assign view transition names to all <h2> headings you would instruct the declarative-names script like so:

astro.config.mjs
starlight({
plugins: [viewTransitions({ declarativeNames: "h2 = heading2-" })],
...
...})

Want to see all the magic this plugin brings? Head over to vtbag.dev for the fifth episode of Fun With View Transitions: Adding View Transitions to Your Starlight Site↗.

Of course you can alternatively create the head entry independent of vtbot by using Starlight’s frontmatter head field

my-page.mdx
head:
- tag: link
attrs:
rel: "expect"
href: "#my-below-the-fold-heading"
blocking: "render"

or Starlight’s global head option:

astro.config.mjs
import viewTransitions from 'astro-vtbot/starlight-view-transitions'
export default defineConfig({
integrations: [
starlight({
plugins: [viewTransitions()],
head: [{
tag: "link",
attrs: {
rel: "expect",
href: "#below-the-fold",
blocking: "render"
}
}]
...
...})]})

The global head option works particularly well if you define an id for the main content area or an element below the markdown content. To do this, you have to override Starlight components↗ to set the id, for example:

./src/components/MarkdownContent.astro
---
import Default from "@astrojs/starlight/components/MarkdownContent.astro";
---
<Default><slot /></Default>
<div id="vtbag-below-the-fold" />

If you just want a whole-viewport cross-fade effect on your Starlight site and none of the spiffy thrills of the plugin, you can alternatively add the following CSS to a custom CSS↗ file and be all set.

custom.css
@media (prefers-reduced-motion: no-preference) {
@view-transition {
navigation: auto;
}
}