⮌ 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. If you only want standard cross-fade view transitions, do not install the plugin but do this.

See what the plugin did↗ to the Starlight Starter!

Contents

Installation

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

1. Install astro-vtbot from npm

Terminal window
cd .../my-starlight-project
npm install -D astro-vtbot

2. Add the plugin to your astro.config file.

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

Optional Steps

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

Option 1: Enable the renderBlocking field for use in the frontmatter

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.

Option 2: Automatically wait for the whole markdown section (if renderBlocking isn’t defined)

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()],
...
...})],
})

Option 3: Set config strings for included scripts

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-" })],
...
...})

Curious About the Details?

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↗.

How to Expect Content without the Plugin

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" />

Simple alternative: Just Whole-Viewport Cross-Fade

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;
}
}