Hey everyone, I know it’s been a while.
Since founding Eventship, a platform for building in-person communities with events, I haven’t had much time to write. But I am hoping to change that, starting with sharing my experience and tips on using Claude Code to build a scaling production product.
For background, the original platform was built on Bubble, a no-code tool. I chose Bubble because my friend works there and asked me to try it and to be fair, Eventship (used to be called Startup Beach) was never meant to be a startup. It was a side project so I could run my monthly startup mixer without drowning in spreadsheets.
But it became real. I raised an angel round, I went full-time, I scaled to 20k users, and immediately knew I had to build our own platform.
We had a lot running on Bubble: event management, community tools, ticketing, coupons, messaging, AI-powered introductions, native mobile apps, reminders, communication tools, the list goes on. It was a massive platform and the estimate to rebuild the whole thing was around 4-5 engineers and it would take 6 months.
No thanks.
I really didn’t want to wait that long and definitely didn’t want to run in parallel with two platforms.
So I decided to try Claude Code and see how far I could get before going down the “hire a whole team” path.
Five weeks later, I was done. The new platform was live, fully built, and 20k users, 500 hosts, and 2k events were all migrated over. They woke up and carried on with their day like nothing had happened… well, except for some scaling mistakes I made which I’ll get to below.
The best part is, I didn’t need to worry about token costs since I kept things simple. Me, Notion Docs, and Claude Code via the desktop app. That’s it. I started with the Claude $100/month tier and then moved to the $200/month tier, which I still use today.
Here’s how I did it, and what I would do differently.
The single most important decision I made was writing detailed documentation before touching a line of code.
Leading up to the rebuild, I had already had 143 articles in Notion. Each one was a deep dive on a feature or an area of Eventship: what it needed to do, specific things to test, UI hints, edge cases, and context about how it connected to other parts of the platform.
I treated Claude Code like a junior engineer, not a super-human coder. In every session, I started with pointing it to a Notion Doc, and my prompt was always something like this:
Review the requirements for [feature x] in this Notion Doc [linked] and see the attached mockup for the design.
Write a plan in our /docs folder on how this feature will be implemented and tested.
Do not start with the code yet until I approve your plan.
With this, Claude would write a plan (sometimes update an existing one depending on the task), but more importantly, it would write a test plan which forced it (and me) to think of edge cases to verify and think about what could go wrong.
Once I was happy with the plan, I asked it to actually start coding.
I usually ran 4 Claude Code sessions at the same time, each one was focused on a single feature or a small area. I tried going up to 6 and more, but honestly, I couldn’t keep my head straight on which session was doing what.
For each session I followed this process:
I started with Claude Code in the Cloud with the prompt above and then got it to do the first iteration of the code.
When ready, I would pull the code and branch down to my machine and run it locally.
I would then start a new Claude Code session locally to fix and debug until I was ready to officially merge the code and move on to the next feature.
This “last mile” approach worked much better than trying to continuously give feedback to the cloud version and having to pull down the code to check it constantly.
This also let me be in control of the codebase at all times, since Claude never merged any code directly. I handled that on my side.
The trickiest part of rebuilding an entire platform isn’t any individual feature, but the dependencies between them. On our event page alone, we have ads, sponsors, speakers, hosts, venues, and more. Each of those is its own system that needed to exist before the event page could be completed.
So I had to move features forward together without finishing any of them all the way. Just like I was managing multiple Claude Code sessions, I was managing multiple Notion Docs that I marked as in progress while pushing them forward.
For example, I built the first version of the event page which was bare, then built the sponsorship system, then came back and wired sponsors into the event page. For both, I also needed to have the create event flow ready.
It felt messy since things were half-done all over the place, but it was the only way to make progress without getting stuck.
Sometimes I would notice small bugs and to ignore them to keep things moving and get to a point where I had the platform up and running end to end. I kept note of those small bugs in Notion and came back to them in the next phase.
Weeks 1-2: I had the entire platform working end to end. All of the main screen and core flows were functional, features were connected, and the foundation basically standing and running.
Week 3: I went through every single one of those 143 Notion docs and fixed the bugs that I had captured, then I verified each feature manually and with automated tests. A lot was broken. Honestly, this was the really painful part and where the real work started to happen.
The initial built felt very easy compare to this polish and hardening phase which was very tedious.
Also during week 3, I launched a temp copy of the site and let a few close friends in to help me test. Of course, they caught things I couldn’t see anymore from being so in the weeds.
At this point, a good buddy of mine started working on a data migration script to get it started.
Week 4: I opened up the site to 50 of our top event hosts and asked for honest feedback. Some of them went through every single feature in their workflow, which was tremendously helpful. This is where I fixed the last few bugs and got ready for launch.
Week 5: Launch week…. which really happened at the end of week 5 since I was still debugging, writing more tests, and making sure every flow worked. At the same time, this week the focus was entirely on the data migration script.
I would dry run the data migration script, look for errors, figure out where the error was, fix it, run it again. Over and over. By the time I ran the actual script, I must have run it manually close to a hundred times.
The data migration was a whole other challenge on its own. Bubble’s database structure doesn’t map 1:1 to a relational database. Bubble stores relationships as lists of unique IDs on the record itself instead of using junction tables, and its auto-generated IDs don’t match standard primary keys.
Instead of maintaining a persistent ID mapping table, I used a deterministic hash so that every Bubble ID gets converted to a UUID5 under a fixed namespace. What that all means is that the same Bubble ID would always produce the same PostgreSQL UUID so that we can keep relationships between records, i.e., users to events, events to registrations, registrations to transactions, etc. intact. It also allowed us to re-run the migration script without causing problems.
Like I mentioned earlier, I must have ran this script over 100 times before it was ready for the real run.
To avoid having to do a sync post-migration of data changes, I decided to notify our users that we would take our first (and hopefully last) downtime maintenance window ever. We started in the evening, took down the site and got to work.
Everything went as smooth as it could since I had run the migration 10 times earlier in the day to make sure there were no problems but one thing I did not anticipate was that GCP would take over an hour to provision our SSL certificate. So while we had planned a quick 30 mins migration to give our scripts time to run, we finished and sat there waiting and refreshing GCP until the certificate was provisioned.
Regardless, close to 20,000 users and all their associated data moved over without data loss.
They woke up the next day and carried on using Eventship with what looked like a refreshed UI, but in reality, was a completely new platform.
People always ask me how we kept the design consistent between the old Bubble site and the new custom-built one.
As a start, I had screenshots from from the old platform that I could feed into Claude Code (you can do the same with Figma designs too) and then I set up a design workflow that seems very simple but worked great:
I had Claude create UI elements as shared components so we could reuse them across our platform.
I had Claude create a Storybook page that listed all of our shared components.
I gave claude a list of our colors and typography, named them and made sure we always used them instead of hardcoding colors.
Finally I made sure all of that was documented in Claude.md.
PS: event with all of that Claude would sometimes still create new UI components or hardcode colors, so make sure to review your code before merging to make sure it references the shared ones.
At the end of every Claude Code session, I always asked Claude to review our docs, tests, and CLAUDE.md files to make sure they were up to date based on what we just changed. Every feature shipped with test coverage and internal documentation. This was tedious and time-consuming, but I truly believe that it was part of the reason why we were successful.
For our docs, I mainly had two sets.
I had a /docs folder that served as internal documentation for Claude and anyone else internally to access and read. This slowly replaced the Notion docs I had.
Then there were the CLAUDE.md files, which are specific for Claude to use while coding.I started with a single CLAUDE.md file, but it grew too large to be useful. I split it into separate files: a main one, plus dedicated files for frontend, API, web, and mobile. Now I also have separate ones for our MCP server, AI Assistant, and a few other large features that needed their own context.
One thing to note here is that CLAUDE.md would get really large as I was coding so I would ask Claude to review it and compress it as features were being built. When a feature was fully built and well documented, Claude.md didn’t need as much content in it’s CLAUDE.md file to function as good.
This migration was not a simple site. When I said we built a lot on Bubble, I meant it. Here’s what I built to complete the migration:
Backend: FastAPI (Python)
Infrastructure: all on GCP, using Cloud Run, Cloud Functions, Cloud Scheduler, Cloud Tasks, etc… and managed all of it via Pulumi
Web: Vite + React + TypeScript
Mobile: Expo / React Native
Database: PostgreSQL with SQLAlchemy + Alembic migrations
Integrations: Stripe Connect (payments & payouts), PayPal, SendGrid (transactional email), Firebase Auth + Storage, Cloudflare Workers (CDN & edge logic), Tinify (image optimization), Apple & Google Wallet passes, Brandfetch (ad auto-population), Google Maps, Cloud Tasks, ipapi.co (IP geolocation), Anthropic Claude + Google Gemini (AI), and more.
1. Don’t underestimate your own traffic
This was my biggest mistake. We went live, I sent the announcement, and everyone rushed the site. It went down within minutes. On Bubble, scaling was handled for us, so we never thought about it. On our own infrastructure, I hadn’t configured GCP’s scaling resources properly for the traffic spike. I had to scramble to reconfigure everything while users were hitting a broken site. This was embarrassing and entirely avoidable. Load test your launch. Seriously.
2. 20,000 Users will find every edge case
My test coverage was high. My manual testing was painfully thorough. But when you have close to 20,000 users on your platform, you quickly realize how many edge cases exist that you simply can’t anticipate. I could have done better, but honestly, sometimes you need 20,000 pairs of eyes to find the things one person never will.
3. Ship parity first, then celebrate new features
This one stings. During the rebuild, I launched a bunch of new features that users had been waiting for. But I couldn’t celebrate or announce any of them because they were overshadowed by the scaling issues and edge case bugs I was working on fixing after launch.
In hindsight, I should have rebuilt the platform as a 1:1 match of the old one, migrated everyone over, stabilized, and then shipped the improvements as separate releases. We’re now a few weeks into the new platform and people are still sending me notes about features they didn’t realize we added.
Those features deserve their own moment!
4. Never give Claude infra access
I made absolutely sure Claude had no direct write access to our GCP infrastructure or production databases. One wrong command could delete data or alter infrastructure in ways that would be catastrophic. This is non-negotiable.
5. Dealing with timezones sucks
This might be specific to my case since we are an events platform. For us every date and time has to be correct across time zones locally and when browsed from a different timezone.
I realized that Claude gets timezones wrong by default. It loves using the browser’s local timezone for everything unless you are specific with it. If you deal with timezones, you probably also know that testing timezone issues is tedious and easy to mess up, so we ended up with a clear CLAUDE.md rule for Claude to stop messing with our timezones and get it right.
So if you deal with timezones, make sure your timezone rules are in your CLAUDE.md file.
If you’ve been thinking about rebuilding your platform, whether it’s from no-code to custom, from one custom stack to another, or just from legacy to modern, know that it’s possible at a speed and cost that would have been laughable two years ago.
Claude Code is as good as everyone says, but it makes mistakes and it needs to be managed. That’s the same as working with humans. I once had an employee unplug the wrong cable and take down our entire office network. At least with Claude, the blast radius is contained to a PR you hopefully did not merge yet and are reviewing.
Focus on documentation. Focus on tests. Focus on components. Manage the AI like you would manage a team. And for the love of everything, set up your scaling before you announce your launch!
Eventship is a platform for building in-person communities. If you’re running events or meetups, come check us out.