the bleeding edge bites back
i tried building a portfolio site with Astro 5, Tailwind 4, and Shadcn UI. it was a wild ride. learn from my mistakes

i make a lot of mistakes in my life, but one thing that keeps me comfortable is the fact that I’ll never cause as much damage as the js ecosystem causes with a single
npm install
(orbun i
if you want to add a paint wrap to your 1998 honda civic to forget the fact that its a 1998 honda civic)
— me, 5 minutes before this article
so, i needed a portfolio site, right? quick and dirty. i figured, “i’m a cracked 10x dev, i can whip something up in an afternoon.” famous last words.
i started the way any sane person would: by looking for a template. but everything i found was either bloated, ugly, or both. so, naturally, i decided to roll my own. “how hard could it be?” i naively thought.
my go-to for static sites is astro. it’s fast, flexible, and i’ve used it a bunch. i grabbed an old project, gutted it, and figured i’d have a nice little astro/solidjs/react/tailwind playground. solidjs for performance where it matters, react for the ecosystem, and tailwind because… well, because tailwind.
that’s where the trouble started.
the bleeding edge bites back
i decided to upgrade to astro 5. seemed reasonable, right? then i got a wild hair and decided to throw in shadcn ui. that’s when i realized my tailwind config was borked.
“no problem,” i thought. “i’ll just run npx astro add tailwind
.” except, surprise! it installs tailwind 4.
now, tailwind 4 is cool and all, but it’s still pretty new. the astro docs? they all reference tailwind 4. backwards compatibility? apparently not in astro’s vocabulary.
i tried shoehorning tailwind 3 in there, but every guide i found was for v4. so, fine, i’ll use tailwind 4. except shadcn support for tailwind 4 was in canary.
at this point, i should have just stopped. but no, i’m stubborn.
i ripped out all the css, upgraded to tailwind 4 (which required a vite plugin and broke my theme), and then realized i didn’t want to learn tailwind 4 right now. it was too bleeding edge, not enough people were using it, and this was supposed to be a fast project.
so, i went back to tailwind 3. except now shadcn could work, but the astro 5 tailwind plugin didn’t like tailwind 3. so i downgraded the plugin. except now i’m on astro 5, which doesn’t like the astro 4 tailwind plugin.
are you keeping up? because i barely was.
i went back to tailwind 4. it was miserable. i was running into bugs because i was too stubborn to read anything other than the patch notes.
the shadcn saga
finally, i got tailwind 4 working with the markdown rendering after fighting for 15 minutes with the @tailwind/typography
plugin just straight up not working. i tried everything, except wiping my node modules and my .astro
folder. it worked now, i see markdown. “prose works”. phew.
then i wanted some components. i didn’t feel like rolling a dropdown menu, dark mode support, buttons, inputs, modals, comboboxes etc. well, shadcn with tailwind 4 can’t be that bad right? it’s just in canary, it’s not like it’s totally broken.
i was right, the shadcn components were not too bad… but the shadcn cli just hated me. it couldn’t cope with the fact that i didn’t use a tailwind config, it couldn’t cope with the fact that i was using an obscure plugin, the default @tailwind/typography
plugin.
i took out the plugin, ran the cli again, it worked, and then i added it back. it broke. i punted my node modules again, ran bun i
for the 50th time this day. it works… it finally works.
i got some warnings with running react 19, thought it was fine. then i ran into some bugs. i dropped down to 18. turns out it was an astro/react bug, i forgot “client:load”. i’m a silly goose.
after all the switching of packages i had this like ptsd, where everytime something wasn’t working i was just assuming it had to do with my package versioning. went back to 19, and the rest is history.
the moral of the story
the rest is how i got to this site, to write this article. and i have to say, it’s been a couple weeks since i’ve used the latest frontend tool, and this was a nice reminder on the true frontend experience. everytime i think backend is easier i just think twice. that’s not to say of course that this wouldn’t have happenned on node backend. at the end of the day, it’s a js ecosystem problem, a problem that one has to just accept at this point.
so, what’s the takeaway?
- don’t be afraid to use boring tech. sometimes, the tried-and-true is better than the shiny and new.
- read the docs. seriously, rtfm.
- know when to quit. if you’re spending more time fighting your tools than building your project, it’s time to re-evaluate.
- frontend is still wild. despite all the advancements, the frontend ecosystem is still a chaotic mess. embrace the chaos, or run screaming back to the backend.
and finally, remember: it could be worse, i could be using pip.