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

hero-image

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
(or bun 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.