What I Learned While Deploying a T3 stack app called KidCheckIn with Laravel Forge
Today was a huge milestone in building KidCheckIn. I deployed the site through Laravel Forge. It wasn’t smooth, but it was solid. I hit a bunch of errors, rolled up my sleeves, and pushed through until everything worked the way it was supposed to. Honestly, I learned more from today’s struggles than from weeks of tutorials.
Here’s what went down and what I picked up along the way.
The Build Process Taught Me to Respect Linting
My first blocker was a wave of lint errors that hit when I tried to deploy. I had skipped over them before, thinking they were just minor style things. But today, I realized that linting isn’t just about formatting, it can break your build if you ignore it.
I fixed each lint issue one by one, ran pnpm lint, fixed what was necessary, and then built locally with:
pnpm build
Lesson learned: Don’t ignore linting, especially when you’re deploying to production.
Writing a Deployment Script for Forge
To make the whole deployment process smoother, I wrote a custom Bash deployment script for Forge. Here’s a snapshot of what it does:
#!/bin/bash cd /home/forge/kidcheckin.com git pull origin t3-kidcheckin export NODE_ENV=production pnpm install pnpm build pnpm drizzle-kit push pm2 delete kidcheckin || true pm2 start "pnpm start" --name kidcheckin --watch pm2 save
This script pulls the latest code, installs dependencies, builds the app, pushes Drizzle migrations, and restarts the app with PM2. Now I can hit deploy in Forge or push to GitHub and let this script handle the rest.
Nginx and SSH: Facing the Scary Stuff
Nginx config used to feel like a black box, but I got hands-on today and it finally clicked. I made sure my site was pointing to the right .output directory from the Next.js build:
nginx Copy Editlocation / { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; }
I also SSH’d into the Forge server, set up PostgreSQL, and created the database .
Once that was done, I connected it all through .env and tested locally before going live.
Quick Deploy + GitHub Auto-Deploy
One of the coolest things I set up today was Quick Deploy through Forge. Once the deployment script was working, I linked it to my GitHub repo and enabled automatic deployment from the t3-kidcheckin branch. Now whenever I push changes, Forge picks it up and runs the whole process for me.
I tested it by making a small update, pushing to GitHub, and boom — it deployed live without me touching a thing.
Wrapping It Up
Today stretched me. I got frustrated, had to Google way too many things, and felt like I broke the site more than I fixed it. But by the end, I had:
- Fixed my build process
- Written a working deployment script
- Configured Nginx with confidence
- Set up and connected PostgreSQL on a live server
- Enabled auto-deploy from GitHub
It’s wild how much you can learn from just sitting down and doing the thing. KidCheckIn is one step closer to being ready for Sundays.