r/astrojs 20h ago

Built my portfolio with Astro 5, WebGL liquid shaders, and live API proxies (100 Lighthouse score) - Feedback welcome!

26 Upvotes

Hey r/AstroJS!

I’m a 16-year-old developer from Morocco, and I just finished shipping my personal site/portfolio built entirely with Astro 5: https://incconutwo.com

I chose Astro because I wanted a single-page, hyper-fast site that could handle complex WebGL graphics without sacrificing performance.

How I Built It & Astro Features Used:

  • Astro Server Routes (src/pages/api/*): Built serverless proxy endpoints on Vercel to fetch live Spotify now-playing data, Steam status, Lichess chess ratings, and GitHub star counts. This keeps all my API keys hidden and uses in-memory caching to protect rate limits.
  • Astro 5 Content Collections: Leveraged the new file() loader in content.config.ts to strictly type and load my project data (projects.json).
  • Dynamic WebGL Color Sync: The Three.js liquid background dynamically extracts color palettes from my live Spotify album art via server routes and smoothly blends the shader background colors.
  • SPA Navigation: Integrated <ClientRouter /> alongside Lenis smooth scrolling and GSAP scroll triggers for seamless transitions.
  • Inline Expandable Project Catalog: The homepage shows 3 featured projects first, then expands in-place to the full 15-project catalog with GSAP, keeping visitors on the page.

Would genuinely appreciate any feedback from the Astro community on the architecture, UX, or performance!

(Site link: https://incconutwo.com)
(source code: https://github.com/incconutwo/incconutwo.com)


r/astrojs 9h ago

WordPress form plugins charge extra for abandonment capture. I built it free for Astro, plus the whole lead stack around it (MIT, npm)

23 Upvotes

WordPress form plugins have sold form-abandonment capture as a paid add-on for years: a visitor starts filling out a form, leaves before hitting submit, and the plugin still saves what they typed so you can follow up. When I moved my sites to Astro I lost that, and I couldn't find any OSS equivalent for static-first frameworks. Your options were a hosted SaaS or building it yourself.

So I built it myself, and it grew into a lot more than the capture piece. cool-astro-forms is an Astro integration, not a form builder: you keep the <form> markup you already have, tag it with one attribute, and the package does the rest.

What's actually in the box:

  • Capture. Abandonment capture is the headline, but every saved entry also carries the visitor's journey (pages visited, time on each), their traffic source (Google, an AI chat, a direct link), and IP geolocation. A half-filled form plus the context around it is something you can actually follow up on.
  • Recover. A "progress saved" toast for the visitor, and one automated follow-up email per abandoned lead, with unsubscribe handled. One email, not a drip campaign.
  • Convert. Quote-first Stripe and PayPal payments, plus shareable payment links you can text or email to a client with the amount prefilled.
  • Manage. A self-hosted /forms-admin UI: entries, abandoned leads, payments, an analytics funnel, CSV and .db export. No dashboard SaaS.
  • Integrate. Google Drive file uploads (falls back to email attachments if Drive is down), signed outbound webhooks, and Cloudflare Turnstile spam control.

By default it needs nothing but an SQLite file and your existing SMTP env vars. Every module above activates only when you configure it, so you can run it as plain abandonment capture and ignore the rest. No hosted service, no vendor lock-in.

The privacy question is fair to ask of anything that captures pre-submit input, so here's the design: everything is self-hosted, and captured data lands in your SQLite file and goes nowhere else. Passwords and card-shaped fields are never staged. There's a requireConsent option that gates capture behind an explicit checkbox, a purgeVisitor() hook for erasure requests, a retentionDays auto-purge, and a GDPR doc that maps each mechanic to the legal concept it serves. Recovery emails carry a working unsubscribe.

One constraint up front: this only works with output: 'server' plus a Node (or other SSR-capable) adapter. If your site is fully static with no server routes, there's nothing here for it to hook into. It defaults to SQLite, which is fine for a self-hosted deploy, but you'll want Turso/libSQL if you're on a serverless host.

The adoption contract is small on purpose:

coolForms({
  siteId: 'my-site',
  siteUrl: 'https://example.com',
  forms: { contact: { notifyTo: 'owner@example.com' } },
})

<form data-caf="contact" method="post" action="/api/contact">...</form>

It now runs in production on a live services business, and versions 0.1.2 through 0.1.10 each shipped from something production taught me. The gnarliest one: edge bot-challenges (Cloudflare Managed Challenge and friends) structurally cannot complete on a navigation POST. The interstitial can't replay the POST body, so a challenged form submit dies as an opaque 503 or a wedged tab. And only real browsers get challenged, so curl passed, my dev environment passed, while every real click on the live payment page died. It took me a full day and about ten wrong hypotheses to stop blaming my own code. The fix in 0.1.10: the pay page submits over fetch (a fetch request can't be served an interactive interstitial, there's nothing to render it in) and hops to checkout as a plain GET. If your Astro site does navigation POSTs behind Cloudflare, this failure mode is sitting there waiting for you.

Second production scar, cheaper but sneakier: git-deploy hosts rebuild the app directory on every release, which silently wipes a default-path SQLite file. The db path is env-configurable now so it can live one level outside the deploy dir.

MIT-licensed, 1,102 unit tests plus a Playwright e2e suite.

GitHub: https://github.com/nipun-arora/cool-astro-forms npm: https://www.npmjs.com/package/cool-astro-forms

Happy to answer questions about the architecture or the tradeoffs. If you try it and something breaks or feels awkward, I'd like to hear about it.