Last month, I launched Happy Little Monoliths, 1st Edition.
This ebook covers full stack development using only Fastify and Vite, no meta-frameworks involved. So instead of Next.js, Fastify, Vite and React. Instead of Nuxt, Fastify, Vite and Vue. It covers the @fastify/vite
Fastify plugin — which I also authored, as well as the @fastify/vue
and @fastify/react
adapters.
Writing with VitePress
VitePress has had a permanent presence in my projects for a long time, being my choice for building documentation sites. There are other excellent options out there, for sure — VitePress is what you want if you use Vue, Docusaurus is what you want if you use React. Both are capable and mature.
Things I love VitePress about are the comprehensive code formatting options, the Mermaid plugin, and of course the fact the default theme is written in Vue, so it's very approachable to me. But it's also built in a way that you can customize about anything and even override internal components through configuration:
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vitepress'
export default defineConfig({
vite: {
resolve: {
alias: [
{
find: /^.*\/VPNavBar\.vue$/,
replacement: fileURLToPath(
new URL('./components/CustomNavBar.vue', import.meta.url)
)
}
]
}
}
})
Though I wish it could have been that simple for me. For the book, I knew I needed enough customizations that just starting out with a complete copy of the default theme would be better. In the end, I modified nearly 30 components.
To get this pretty result:

Time spent on this theme accounted roughly for 20% of the entire time spent writing the book. I just couldn't let go — needed to have it just the way I wanted — thinking I was going to reuse for future books, so the extra effort was justifiable.
PDF Wrangling
For building PDFs, I used the vitepress-export-pdf, using the config file to adjust for page ordering and PDF margins. The margins were the only obvious thing I needed to adjust — but other than that, it just worked on the first try.
Kudos to @condorheroblog.
import { defineUserConfig } from 'vitepress-export-pdf'
const routeOrder = [
'/1-introduction',
'/2-modern-js-in-2025',
'/3-a-fastify-and-vite-crash-course',
'/4-choosing-a-rendering-strategy',
'/5-building-an-application-shell',
'/6-fetching-and-submitting-data',
'/7-maintaining-sessions',
'/8-maximizing-ssr-performance',
'/9-production-deployment'
]
export default defineUserConfig({
routePatterns: ['!/'],
sorter: (pageA, pageB) => {
const aIndex = routeOrder.findIndex(route => route === pageA.path)
const bIndex = routeOrder.findIndex(route => route === pageB.path)
return aIndex - bIndex
},
pdfOptions: {
margin: {
top: '40px',
bottom: '40px'
}
}
})
Once I have the main PDF exported, I just use Acrobat directly to add the cover as first page. This is one part of the process I couldn't automate yet.
I could of course add an extra page on the VitePress suite for the cover, but I couldn't work out the margins. Probably something trivial, I'll most definitely address it by the time I start working on the second edition.
PDF Delivery
The checkout setup is a low tech as it can get — just a Stripe payment link, and I'm still personally emailing PDFs and adding readers to the GitHub repository.
If I ever reach 100 copies sold, I'll work on integrating Polar and automating this part of the process, and add a chapter to the book covering the integration with @fastify/vue
. Hopefully that happens soon enough!
⁂
Having the first edition of the book out was important for the @fastify/vite project, so it got to a point where I eliminated all blockers and focused on shipping. Working out a proper and customized PDF checkout would have further delayed the release. Now it's planned material for the second edition!
By buying the book, you also get access to the book repository with all the source code mentioned in this article!