Thomas Harmond

This is my notebook.

My Stack

What I used to build Church Space

I recently launched Church Space. Here's where I landed for my stack.

01. FRAMEWORK

Next.js and React with TypeScript.
Everyone has their (very strong) opinions on this, but Next is the best way to ship an app in 2025. AI coding tools know it well which helps a solo-dev (like myself) fix bugs and move fast. I use the app router with server actions for most interactions with with my database.

I use a Turborepo to allow me to reuse code across apps. There are 5 apps right now:

  1. Church Space
  2. Church User Content
    • I use this to proxy content in email as Supabase puts a Cloudflare set cookie header on all content which leads to some email clients not loading images.
    • I also use this to add on the play button for YouTube video thumbnails.
    • The images and content are cached here so that each email open is not hitting my storage.
  3. Church Space Email
    • This is where people can manage their email preferences and view emails in the browser.
  4. Custom Domains
    • This is used for link pages with custom domains as well as for forms.
  5. Docs/Help Center
    • Built with Mintlify.

Eventually, we'll add mobile to this list. I plan to use React Native and Expo when that time comes.

02. STYLING

Tailwind CSS and shadcn/ui
Similar to Next, Tailwind and shadcn/ui help me move fast while still giving me loads of flexibility. Colocating my styles allows me to make all changes to a component on a single file. The CSS bundle stays small due to the way that Tailwind complies down to just the classes used.

Shadcn provides the perfect starting point. Why would I build a button from scratch when I can start with a base of something that's already functional, accessible, and well designed?

Nucleo Icons
For icons, I'm a huge fan of Nucleo. It's a one time purchase, new icons and styles are constantly added, the icons are beautiful, and I've had icon requests be added quickly. I feel like I'm stealing with how affordable it is. Plus they elevate your app above the standard Lucide icons.

Motion (previously Framer Motion)
Using Motion helps bring small things to life in the app. Micro-animations (along with taste and design) help set apps apart in 2025 when a feature can be prompted in 10 minutes.

03. DATABASE

Postgres (Supabase)
Postgres just makes sense to me. It's how I thought about data before I knew anything about database.

Supabase is easy to work with and affordable. Could I self-host? Sure. But that's not what I want to spend my time and energy on at this stage.

I also use Supabase for auth and storage. Again, this is a choice that helps me move fast while also keeping things as simple as possible for me to maintain.

Upstash
At the moment, I only use Redis for rate limiting, but there are loads of things that could be improved in Church Space by using it more.

04. AI

Vercel AI SDK with Google Gemini
The AI SDK is a dream to work with. You're able to quickly test out different models with a single line of code, it's easy to add tools, and like most things in my stack, it lets me move fast.

Google has been my go to model provider. It's incredibly cheap and the models are plenty good for what I'm doing. Even with doing OCR on paper forms submissions, my AI bill is cheap.

Cursor and Claude Code
For dev tools, I've been using Cursor and Claude Code. Cursor's tab complete is unmatched, and Claude Code's limits allow me to have a background task or two going at any time while I work on the details and on files that need human intervention.

05. EVERYTHING ELSE

Vercel
Vercel's DX is unmatched. Again, I could self host my app, but why on earth would I do that as a solo dev when I can pay $20/mo to not think about it? Additionally, they keep improving the product and keep cutting costs with things like Fluid Compute and Active CPU.

I also use Vercel for analytics. I'll eventually move to Posthog, but I'm not hitting free limits on Vercel any time soon.

Trigger.dev
I use Trigger.dev for my background jobs. While node has it's drawbacks at scale, I love writing everything in TS and being able to reuse functions from other parts of the app.

Resend
Resend is what I use for email delivery. The DX is super easy. I use their webhooks for things like opens, click tracking, and domain verification.

Zustand, React Query, and Nuqs
I use Zustand for global state in the app (mainly just things to do with the user, their organization, and their PCO connection).

I use React Query for all server state management.

I use Nuqs for url state management, and it's such a breeze to work with.

DND Kit
My drag and drop tool of choice. Used throughout the app. Has some quirks, but good overall.

Tiptap
The extensions (both included and custom) make Tiptap a great option for a rich text editor. I like that I can get the json and the and HTML of the editor contents. If/when I eventually work on mobile, having some flexibility with the data format will be helpful.

React QR Code Logo
A great tool for making custom QR codes.

06. CLOSING THOUGHTS

In the past 2 months since having actually put something out in the world, I've been able to connect with so many people: builders, churches, and companies. I built for a year in private, just slowly working on what I wanted to do. Building in public is 1,000x more rewarding and motivating. Stop worrying about your stack. Go build something.

If you'd like to get updates on my writing, you can subscribe to my newsletter here.