I've been building with Astro for a while now, and the same pain points kept showing up across projects. I got tired of patching around them and just built integrations instead.
Three packages. All on npm. All open source.
π― What's an Astro Integration, anyway?
If you've never built one, an Astro Integration is a package that hooks into Astro's build lifecycle or dev toolbar. You return a name and a hooks object, and Astro calls your callbacks at the right moments.
export default function myIntegration(): AstroIntegration {
return {
name: 'my-integration',
hooks: {
'astro:build:done': ({ pages }) => {
// runs after build
}
}
}
}
That's basically it. It's how @astrojs/react, Tailwind, Partytown, and most of the ecosystem slot into your config without you wiring anything up yourself.
π¦ @shiftescape/astro-bundle-budget
You build your site, ship it, and two weeks later someone notices a page is pulling in 400KB of JS. No warnings. No CI failure. Just a slow page and a mild sense of shame.
This integration hooks into astro:build:done, reads the output, and compares your JS/CSS sizes against budgets you set. Exceed them? Build fails.
import bundleBudget from '@shiftescape/astro-bundle-budget';
export default defineConfig({
integrations: [
bundleBudget({
budgets: [
{ type: 'js', budget: 100 }, // 100KB JS max
{ type: 'css', budget: 50 } // 50KB CSS max
]
})
]
});
Set it once, forget about it. The pipeline tells you when something bloats.
π @shiftescape/astro-env-inspector
You've got env vars spread across .env, .env.local, .env.production. You're debugging something weird and you genuinely don't know which value Astro is actually reading or if the variable is even loaded at all.
This adds a panel to the Astro Dev Toolbar. All your env vars, grouped, masked by default, searchable. Dev only and nothing touches your production build.
import envInspector from '@shiftescape/astro-env-inspector';
export default defineConfig({
integrations: [envInspector()]
});
Beats staring at console.log(import.meta.env) output and trying to remember which file overrides which.
πΊοΈ @shiftescape/astro-toolbar-routes
Once a project gets past a dozen pages, you're either memorizing routes or digging through src/pages/ every time. Neither is fun.
This puts a route map in the dev toolbar. Every page in your project, grouped, searchable, clickable. It reads your file-based routes at build time and lists them out.
import toolbarRoutes from '@shiftescape/astro-toolbar-routes';
export default defineConfig({
integrations: [toolbarRoutes()]
});
Click a route, go there. That's the whole thing.
Using all three together
npm install @shiftescape/astro-bundle-budget @shiftescape/astro-env-inspector @shiftescape/astro-toolbar-routes
// astro.config.mjs
import { defineConfig } from 'astro/config';
import bundleBudget from '@shiftescape/astro-bundle-budget';
import envInspector from '@shiftescape/astro-env-inspector';
import toolbarRoutes from '@shiftescape/astro-toolbar-routes';
export default defineConfig({
integrations: [
bundleBudget({ budgets: [{ type: 'js', budget: 100 }] }),
envInspector(),
toolbarRoutes()
]
});
The toolbar panels are dev-only. The budget check runs at build time and exits non-zero on failure, so CI picks it up without any extra config.
What I Learned Building These
A few things stood out while building these integrations:
The Astro Integration API is genuinely pleasant to work with. The lifecycle hooks are well-named and the docs are thorough. The hardest part is usually understanding exactly which hook fires when but after building a couple integrations you get a feel for it.
The Dev Toolbar API opens up a lot. Being able to inject custom UI panels into the development browser experience is really powerful. Two of these three integrations live in the toolbar, and the API for building toolbar apps is surprisingly straightforward.
Monorepo setup with npm workspaces is worth the upfront investment. Having a single demo/ project that uses all three integrations locally made testing so much easier. I can build a package, start the demo, and see everything working together without publishing first.
What's Next
All three are at v0.1.x β functional and tested, but still early. There's a lot more I want to do with each of them
If any of these save you some time, a β on GitHub goes a long way!
Built with the Astro Integration API and listed in the Astro Integrations Library.





Top comments (0)