Rolling Back Main (And Why You Shouldn't Have to)
Practical guide for solo developers who need to undo bad commits on main, followed by an honest reflection on why it happened and how to avoid it when vibecoding with AI tools.
Rolling Back Main (And Why You Shouldnāt Have to)
A guide for solo developers who committed directly to main and need to undo it, followed by an honest look at why it happened. Written from real experience on a mobile-first turborepo project: Expo for native, Next.js for web and admin, Hono for the API, all wired together with tRPC and backed by Turso.
Part 1: The Rollback Guide
The Situation
I was vibecoding the early scaffolding of a mobile-first turborepo. Clerk auth was integrated, tRPC was wired up, NativeWind was styled, the Expo app was talking to the Hono API. Things were moving. Then I started refactoring the auth screens to āimprove user experience,ā and five commits later I had broken a bunch of things I didnāt notice until it was too late.
The irony: the commit messages all say things like āimprove,ā āenhance,ā āstreamline.ā They were doing the opposite. Letās fix this mess!
Before You Start
The first step is figuring out where you are and where you need to go back to. Run this to see your recent commit history:
git log --oneline
Youāll get a list of commits, newest first. Each line is a short SHA and a commit message. What youāre looking for is the last commit where everything still worked. Scan the messages and find the boundary between āthis was fineā and āthis is where things started breaking.ā
Next, check whether your bad commits have already been pushed to the remote:
git log origin/main --oneline
If the bad commits are only local, your life is easier. If theyāre already on the remote, youāll need to either force push (Strategy A) or push revert commits (Strategy B).
My Situation
Hereās what my log looked like:
49ac744 (HEAD -> main, origin/main) Update documentation: add SERVICES.md...
831db24 Refactor useVerifyEmail hook to improve session finalization logic...
c24cdd7 Enhance authentication flow by integrating email parameter handling...
3027eec Refactor authentication screens to improve user experience...
8b6b164 Enhance error messages and handling in authentication screens...
b853068 Update documentation to reflect recent changes: add AUTH-SETUP.md...
ce956ac Refactor mobile app layout and TabOneScreen to improve navigation...
751f5f7 Integrate Clerk authentication into mobile app...
66afbd7 Refactor mobile app layout and TabOneScreen to integrate SafeAreaProvider...
...etcetera!!!...
Everything from 8b6b164 up through 49ac744 needs to go. The last known good state is b853068, right after documenting the auth setup and before touching the auth screen components. Thatās 5 commits to undo (a topic for laterā¦).
All five bad commits were already pushed (origin/main pointed to 49ac744). That means whichever strategy I pick, I need to deal with the remote too.
Strategy A: Rewrite History (git reset)
What it does: Moves the main branch pointer back to your last good commit as if the bad commits never happened. Clean history, but those commits are erased from the branch.
When to use it: Youāre a solo developer, nobody else has pulled your bad commits, and you donāt care about preserving a record of the mistake.
# 1. Make sure your working directory is clean
git stash # if you have uncommitted changes you want to keep
# 2. Reset main to the last good commit (use your SHA here)
git reset --hard b853068
# 3. If you already pushed the bad commits to remote, force push
git push --force-with-lease origin main
--force-with-lease is safer than --force. It refuses to push if someone else has pushed commits you havenāt seen. Unlikely for a solo dev, but itās a good habit that costs nothing.
After this: Both local and remote main point to your last good commit. In my case, the auth screen refactoring, the useVerifyEmail hook changes, the email parameter handling, and the documentation updates from those commits are all gone from history.
The bad commits still exist in gitās reflog for about 30 days if you need to recover anything. Run git reflog to see them:
b853068 (HEAD -> main, origin/main, origin/HEAD) HEAD@{0}: reset: moving to b853068
49ac744 HEAD@{1}: clone: from https://github.com/antoniwan/nido-app.git
See that 49ac744 HEAD@{1}? Thatās the HEAD of the bad commits, still accessible. If I realize later that one of those five commits had something I actually needed, I can cherry-pick it out:
# Check out a specific file from the bad commits without restoring the whole thing
git checkout 49ac744 -- path/to/file-i-actually-needed.ts
# Or cherry-pick a single commit onto a new branch to extract what you need
git checkout -b recovery/grab-that-one-thing
git cherry-pick c24cdd7
The reflog is the safety net under the safety net. The bad commits arenāt really gone; theyāre just not on any branch. Git will garbage-collect them after about 30 days, so if you think you might need something from them, donāt wait.
Strategy B: Preserve History (git revert)
What it does: Creates new commits that undo the bad commits. The original commits stay in history, and the revert sits on top. Nothing is erased.
When to use it: You want a record of what happened and what you undid, or youāre uncomfortable rewriting history, or others may have already pulled your changes.
# 1. Revert the bad commits (newest to oldest), staged but not yet committed
# Replace the number with however many commits you need to undo
git revert --no-commit HEAD~5..HEAD
This runs silently if there are no conflicts. No output means it worked.
(Note: when I tested this strategy, I did a dry run reverting 3 commits instead of all 5. The output below reflects that test. The process is identical regardless of the count ā just adjust the number.)
Now review what it staged:
git diff --cached
Hereās a truncated version of what I saw when I ran this on my project (reverting 3 documentation-related commits as a test):
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -38,10 +38,9 @@ pnpm check-types
| [GETTING-STARTED.md](docs/GETTING-STARTED.md) | How to chip away ā build order, commands, where to look |
| [AUTH-SETUP.md](docs/AUTH-SETUP.md) | Auth setup, test users, testing login and sign-up |
| [MONOREPO.md](docs/MONOREPO.md) | Monorepo layout, three web apps (marketing, admin, embedded) |
diff --git a/apps/admin/.env.example b/apps/admin/.env.example
deleted file mode 100644
--- a/apps/admin/.env.example
+++ /dev/null
@@ -1,4 +0,0 @@
-# Clerk (admin auth). Get keys from https://dashboard.clerk.com/
-NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxxx
-CLERK_SECRET_KEY=sk_test_xxxx
diff --git a/apps/admin/.gitignore b/apps/admin/.gitignore
@@ -27,7 +27,6 @@ yarn-error.log*
.env*
-!.env.example
diff --git a/apps/mobile/.env.example b/apps/mobile/.env.example
deleted file mode 100644
... (many more files ā the diff will be long in a monorepo)
This is the āreviewā step. Youāre reading the diff to confirm itās undoing what you expect: documentation rows removed from the README table, .env.example files deleted, .gitignore exclusions reverted. If something looks wrong, you can abort with git reset HEAD before committing anything.
Once youāre satisfied, commit and push:
# 3. Commit the revert as a single commit
git commit -m "Revert auth refactoring commits (49ac744..8b6b164): broke session finalization and email verification flow. Rolling back to b853068."
# 4. Push normally (no force needed)
git push origin main
Hereās what my commit and push looked like:
[main 6c650fb] Revert commits because I'm a dumbass
22 files changed, 261 insertions(+), 2283 deletions(-)
delete mode 100644 apps/admin/.env.example
delete mode 100644 apps/mobile/.env.example
delete mode 100644 apps/mobile/app/(auth)/_layout.tsx
delete mode 100644 apps/mobile/app/(auth)/sign-in.tsx
delete mode 100644 apps/mobile/app/(auth)/sign-up.tsx
delete mode 100644 apps/mobile/app/(auth)/verify-email.tsx
delete mode 100644 apps/mobile/app/index.tsx
delete mode 100644 docs/AUTH-SETUP.md
22 files changed. 2,283 lines deleted. Thatās the cost of five bad commits in a monorepo.
The push goes through normally since weāre adding commits, not rewriting history:
To https://github.com/antoniwan/nido-app.git
b853068..6c650fb main -> main
A note on the commit message: My actual message was āRevert commits because Iām a dumbass.ā Iām of two minds on this. On one hand, itās honest and itās my repo. On the other hand, commit messages are documentation. Six months from now, git log --oneline will show 6c650fb Revert commits because I'm a dumbass sandwiched between actual descriptions of work. It tells future-me nothing about what was reverted or why. A message like Revert auth refactoring (8b6b164..49ac744): broke verify-email flow and session handling is less cathartic but actually useful when youāre scanning the log trying to understand what happened. Self-deprecation in commit messages is another form of the laziness this guide is about: it feels like accountability, but itās skipping the work of writing something informative. Even solo devs deserve a readable log. Especially solo devs, because thereās no one else to ask āhey, what was this commit about?ā
The --no-commit flag is what makes this clean. Without it, git would create a separate revert commit for each bad commit (three āRevert ā¦ā entries in the log). With it, everything gets staged together and you commit once.
Note on the range: HEAD~5..HEAD means āthe last 5 commits.ā Adjust the number to match how many bad commits you have. If youāre unsure, count them in git log --oneline.
Strategy Comparison
| Reset (A) | Revert (B) | |
|---|---|---|
| History | Clean, bad commits gone | Full record preserved |
| Remote push | Requires --force-with-lease | Normal push |
| Recovery | Via reflog (~30 days) | Original commits visible forever |
| Complexity | 3 commands | 4 commands |
| Solo dev? | The right call | Also fine |
| Team? | Dangerous | Safe |
For a solo developer, Strategy A is usually the right call. Itās simpler and gives you a clean history. In my case, Iām the only one pulling from this repo, so thereās no reason to preserve the record of five commits that did nothing but break things. Strategy B is there if you want the paper trail or if anyone else might have cloned your repo.
Turborepo-Specific Cleanup
The git part is done. But in a monorepo, rolling back the code is only half the job. Your local environment still thinks itās living in the future: node_modules have packages that the restored commit doesnāt expect, Turboās cache has build artifacts from the bad commits, and your package managerās lockfile might be out of sync. If you skip this cleanup, youāll get mysterious build failures and wonder if the rollback even worked.
Your specific project will have its own cleanup needs depending on your stack. Think about what your bad commits touched: did they add dependencies? Change shared packages? Modify config files? Anything that leaves artifacts outside of git needs to be cleaned up manually. Hereās what I had to do for mine:
# 1. Nuke node_modules across the entire monorepo
# In a turborepo, each app/package has its own node_modules
# Don't just clear the root ā get all of them
rm -rf node_modules apps/*/node_modules packages/*/node_modules
# 2. Reinstall from the lockfile at the restored commit
# This project uses pnpm (common with turborepo)
pnpm install
# 3. Clear Turborepo's build cache
# Stale cache = stale builds = mysterious "it still doesn't work" moments
rm -rf .turbo
turbo daemon clean
Now verify each app builds. In a monorepo, donāt just build one app and assume the rest are fine. The bad commits touched auth components in the mobile app, but also documentation, .env.example files, and .gitignore rules across admin and mobile. Stale state in any of those apps could cause problems:
# Build everything
turbo build
# If you want to be thorough, check each app individually
turbo build --filter=mobile
turbo build --filter=web
turbo build --filter=admin
turbo build --filter=api
For the Expo mobile app specifically, Metro has its own bundler cache that lives outside of Turbo:
cd apps/mobile
npx expo start --clear
Beyond the build cache, think about what else your bad commits touched that lives outside of gitās awareness. In my case, the reverted commits had added Clerk keys to apps/admin/.env.example and apps/mobile/.env.example, both of which got deleted in the rollback. So I had to double-check that my actual .env files still matched what the restored code expected.
If your bad commits modified shared packages in packages/, the source is reverted but any built output (like dist/ folders) might still be stale. Nuke them: rm -rf packages/*/dist and rebuild. If they included database migrations, rolling back the code doesnāt roll back the schema ā thatās a separate problem youāll need to handle manually. If they changed native dependencies in an Expo or React Native project, you may need npx expo prebuild --clean or a full rebuild of your development client. And if they touched CI/CD config (GitHub Actions, Vercel, etc.), verify the restored config still works on your next deployment.
The general principle: git only rolls back the source. Caches, build artifacts, databases, environment config, native builds ā anything that exists outside of .git needs to be manually reconciled. The rollback command gets you 80% of the way there. The last 20% is on you, and itās the part that will bite you if you skip it.
Part 2: Why I Had to Do Any of This
Hereās the part where I talk about why this happened. Iām writing this for myself, but if any of it resonates, take whatās useful.
My Laziness Masked as Efficiency
Working directly on main felt faster to me. No branch to create, no PR to open, no merge to deal with. As a solo developer vibecoding the foundation of a new project, it felt especially justified. āIām scaffolding. Iām moving fast. Everything is changing anyway. Who am I branching for?ā
This reasoning sounded like efficiency to me, but looking back, it was laziness. The way I see the difference: efficiency is removing steps that donāt add value. Laziness is skipping steps that do add value because the cost of skipping them feels abstract until it isnāt.
Creating a branch takes five seconds:
git checkout -b feature/refactor-auth-screens
Thatās the entire overhead I was skipping. Five seconds of āceremonyā that would have meant the difference between git checkout main and the multi-step surgery described in Part 1.
What Actually Happened
The scaffolding phase went fine. Integrating Clerk, wiring up tRPC, setting up NativeWind with a custom color palette, getting the Expo app to talk to the Hono API through Turso: all of that worked, committed to main, no issues. The habit got reinforced. āSee? Branching would have been pointless overhead.ā
Then came the auth screen refactoring. Five commits that touched the sign-in flow, the sign-up flow, the email verification hook, the session finalization logic, and the navigation between all of them. Each commit message said things like āimprove,ā āenhance,ā āstreamline.ā Each one introduced subtle breakage I didnāt catch because I was testing the happy path and moving to the next thing.
By the time I realized the useVerifyEmail hookās session finalization was broken and the email parameter handling in sign-in was tangled, I was five commits deep with no clean state to fall back to. The ālast good stateā was somewhere behind me in the log, and getting back to it meant reading a rollback guide and praying I didnāt miss a step.
If I had run git checkout -b feature/refactor-auth-screens before that first commit, main would still be sitting clean at b853068, and ārolling backā would have been: git checkout main. Delete the branch if you want. Done.
What Branching Actually Gives Me as a Solo Developer
I used to think branching was a team practice. Itās not. Hereās what it gives me, working alone on a turborepo with four apps:
A stable reference point. Main always works. The mobile app launches, the API responds, the web app renders, the admin panel loads. If my auth refactoring experiment breaks the verify-email flow, main doesnāt care. Main is still clean.
Cheap experimentation. Branches are free. I could have tried three different approaches to the auth screen architecture: one with shared hooks, one with per-screen logic, one with a state machine. Keep the one that works, delete the rest. On main, every experiment is a commitment I might have to surgically remove.
Cleaner recovery. Compare the two recovery paths. Without branching: read a guide, identify the SHA, run reset or revert commands, force push, nuke node_modules across every app and package in the monorepo, clear the turbo cache, clear the Metro cache, rebuild all four apps, check my .env files. With branching: git checkout main. Done.
Better commit history. When I work on a branch and squash-merge, my main branch tells a clean story: āintegrated Clerk auth,ā āwired up tRPC,ā āadded NativeWind.ā When I work on main, the story becomes: ārefactor auth screens,ā āenhance auth flow,ā ārefactor useVerifyEmail,ā āupdate docs for the refactoring,ā then a revert commit that says ārolled all of that back because it was broken.ā One of these histories is useful. The other is a diary of my mistakes.
The Trap I Fell Into
The trap isnāt that I donāt know this. I do. Iāve told other developers to branch. The trap is that the cost of not branching was invisible to me 99% of the time. I committed to main, it worked, I moved on. Twenty-two commits of scaffolding went fine on main. The habit got reinforced with every single one.
Then the 1% hit. I was five commits deep into an auth refactoring that broke session finalization across the Expo app, and I was reading a guide about git reset --hard and --force-with-lease and nuking node_modules from every directory in a monorepo, and I realized I had traded five seconds of branch creation for thirty minutes of cleanup and the low-grade anxiety of wondering if I actually got everything back to the right state.
That trade was never efficient. To me, it was just laziness that hadnāt been invoiced yet.
Five Commits of Not Noticing
This part deserves its own section because itās a separate failure from the branching problem. The auth screen refactoring didnāt break on the first commit. It broke across five commits, and I didnāt notice until all five were in.
Thatās worth sitting with. Five commits means I wrote code, committed it, looked at the result, thought āthis is fine,ā and moved on. Five times. The breakage was there the entire time. I just wasnāt looking at the right things.
Why? A few possibilities, and Iām being honest with myself about all of them:
I was testing the happy path only. I refactored the sign-in screen, tested sign-in, it worked, committed. Then the sign-up screen, tested sign-up, committed. But did I test the full flow end to end? Did I verify that the useVerifyEmail hook still finalized the session correctly after the changes in c24cdd7? Did I check that the email parameter handling in sign-in still worked after the navigation changes? No. I tested the thing I just changed, not the things adjacent to it.
I was reading my own commit messages as progress. āEnhance authentication flow.ā āImprove session finalization logic.ā āStreamline email parameter handling.ā Each commit message told a story of improvement. But I wrote those messages, and I was biased toward believing my changes were improvements. The commit messages were aspirational, not verified.
My vibecoding feedback loop was too short. When Iām iterating fast with AI-generated code, the cycle is: generate, glance, commit, next. The āglanceā step is doing a lot of heavy lifting, and itās the weakest link. Iām pattern-matching on ādoes this look right?ā instead of ādoes this actually work across all the flows it touches?ā
I had no checkpoint. This connects back to the branching problem, but itās worth stating separately. If I had a working main to compare against, the breakage would have been obvious earlier. I could run the app from main, run it from my branch, and see the difference. Without that reference point, āworkingā was just āseems okay to me right now.ā
The takeaway for me: catching breakage five commits late isnāt just a branching problem. Itās a testing-and-verification problem. Branching gives me a safety net. But the reason I needed the safety net is that I wasnāt checking my work thoroughly enough between commits. Both failures contributed. Fixing one without fixing the other just means the next incident will look slightly different.
What would have caught this earlier: after each commit, run through the full auth flow. Sign up, verify email, sign in, sign out, sign back in. Every time. Yes, itās tedious. Itās less tedious than rolling back five commits.
But thereās something deeper here that I think deserves serious attention, and itās the thing Iām most uncomfortable admitting: this is a critical thinking failure. Not a tooling failure, not a workflow failure. A thinking failure.
Every commit I made was a decision. āThis code is good enough to commit.ā āI donāt need to test the adjacent flows.ā āThe commit message says āimproveā so it must be an improvement.ā āI donāt need a branch for this.ā Five commits means five decisions where I chose not to stop and think critically about what I was doing. I deferred to momentum instead of judgment. I let the feeling of productivity substitute for the evidence of it.
Vibecoding made this worse in a specific way. When I write code myself, I have to think the implementation into existence. That thinking is a natural review moment ā Iām reasoning through the logic as I type it, so I at least have a chance of noticing when something doesnāt fit. When the AI generates the code, that step disappears. I go from āI need to refactor this hookā to āhereās the refactored hookā without the intermediate step of actually reasoning through the implementation. The āglanceā I mentioned earlier is doing even less work than I thought, because Iām not checking work I did ā Iām checking work someone else did, at speed, with my guard down because it looks right. The AI produces code that reads well. Readable code feels correct. But feeling correct and being correct are different things, and five commits of not noticing is what happens when I let one substitute for the other.
I think this matters beyond my repo. The way I make decisions in a codebase reflects how I make decisions generally. Every shortcut I take, every verification I skip, every assumption I donāt question ā those are habits of mind, not habits of git. A repo is just a place where the consequences of lazy thinking become visible and measurable. In other areas of life, the consequences are just as real but harder to trace back to the specific moment I stopped thinking critically.
The uncomfortable question Iām sitting with: if I canāt be bothered to think critically about five commits in my own solo project, where the only person affected is me, what does that say about the rigor I bring to decisions with higher stakes? I donāt have a clean answer for that yet. But I think the question is worth asking.
Do AI Agents Even Work Better When You Branch?
This is a question I started asking myself after this whole mess, and it turns out the answer is unambiguously yes. Not just ābetter practiceā yes, but āthe tools are literally designed around itā yes.
GitHub Copilotās coding agent can only push to branches prefixed with copilot/. It is physically prevented from pushing to main. Thatās not a suggestion or a best practice doc buried in a wiki. Itās a hard constraint built into the product. GitHub looked at the problem of AI agents writing code and decided the first safety rail is: never let it touch main directly. If GitHubās own AI agent isnāt trusted to commit to main, I have to ask myself why I thought I should be trusted to do it while vibecoding at speed.
Claude Code has built-in git worktree support. You can spin up isolated worktrees where each agent session gets its own branch and working directory. The idea is that you can run multiple AI agents in parallel, each on its own branch, and they canāt interfere with each other or with main. When the agent is done, you review the branch and merge what works. If it produced garbage, you delete the worktree and nothing is lost.
The pattern across the ecosystem is consistent: Cursor, Aider, Cline, Claude Code, Copilot ā they all either enforce or strongly encourage branching. The emerging best practice is to treat each AI coding session as its own branch, commit small and often within that branch, and only merge to main after human review. Some teams even use naming conventions like agent/feature-name to make it obvious which branches were AI-assisted.
Hereās what I find interesting about this: the AI tooling community arrived at āalways branch, never commit to main directlyā not because of some abstract git philosophy, but because they learned the hard way that AI-generated code needs isolation. The output is variable. Running the same prompt twice can produce different results. The agent might refactor something you didnāt ask it to touch. Without branch isolation, youāre one bad generation away from exactly the situation I described in Part 1.
I donāt have a definitive answer on whether branching makes the AI itself produce better code. But Iām fairly convinced that branching makes the workflow around AI-generated code dramatically safer and more manageable. The isolation means you can experiment freely, the branch boundary means main stays stable, and the merge step forces a review moment that the āgenerate, glance, commit, nextā cycle on main completely skips.
If the companies building these tools decided that branching isnāt optional for AI-assisted development, maybe it shouldnāt be optional for me either. Something to sit with.
The Fix
For me, the fix isnāt discipline. Itās making the right thing the default. Hereās what Iām doing:
Git aliases. Making branching so easy I donāt think about it:
git config --global alias.start '!f() { git checkout -b "$1" && echo "Working on $1"; }; f'
# Now: git start feature/refactor-auth-screens
A pre-commit hook on main. Making committing to main annoying on purpose:
#!/bin/sh
# .git/hooks/pre-commit
branch=$(git rev-parse --abbrev-ref HEAD)
if [ "$branch" = "main" ]; then
echo ""
echo " ā You're committing directly to main."
echo " Remember the auth screen rollback?"
echo " Use: git checkout -b feature/your-thing"
echo ""
echo " (bypass with --no-verify if you really mean it)"
exit 1
fi
A personal rule. Main is for merges only. Every change, no matter how small, gets a branch. No exceptions. The āitās just scaffoldingā exception is exactly how this project ended up needing a rollback guide.
The Honest Summary
I didnāt need a rollback guide. I needed a five-second habit. The rollback guide exists because I optimized for the wrong thing: speed of committing instead of safety of my codebase. To me, thatās laziness wearing efficiencyās clothes. Iām not calling anyone else lazy for doing the same thing. But I know it was laziness for me, because I knew better and I still skipped it.
The goal isnāt to feel bad about it. The goal is to make the five-second habit automatic so this guide collects dust.
Written after rolling back five commits on my own project because I was too lazy to type git checkout -b. Learn from my experience if it speaks to you.
Sources
Git Documentation
- git reset ā Moving branch pointers and unstaging changes
- git revert ā Creating commits that undo previous commits
- git reflog ā Viewing the reference log to recover ālostā commits
- git cherry-pick ā Applying specific commits from one branch to another
- git worktree ā Managing multiple working trees for parallel development
- git push āforce-with-lease ā Safer force pushing that checks for upstream changes
AI Agents and Branching
- Using Git Worktrees for Multi-Feature Development with AI Agents ā Nick Mitchinson on worktree-based workflows for AI coding
- How weāre shipping faster with Claude Code and Git Worktrees ā incident.ioās real-world workflow with parallel AI agents
- Parallel Vibe Coding: Using Git Worktrees with Claude Code ā Dan Does Code on parallel AI sessions
- Claude Code: Common Workflows ā Official Claude Code docs on worktrees and branching
- About GitHub Copilot Coding Agent ā GitHubās docs on Copilotās
copilot/branch prefix restriction - GitHub Copilot Coding Agent 101 ā Getting started with Copilotās agentic workflows
- Responsible Use of GitHub Copilot Coding Agent ā GitHubās safety guidelines including branch protection
Vibecoding Best Practices
- AI Coding Best Practices in 2025 ā DEV Community overview of commit hygiene with AI tools
- Building With AI Coding Agents: Best Practices for Agent Workflows ā Elisheba Anderson on agent workflow patterns
- My LLM Coding Workflow Going Into 2026 ā Addy Osmani on layering AI tools with git discipline
- Vibe Coding with GitHub Copilot ā GitHubās official vibecoding tutorial
Turborepo
- Turborepo Documentation ā Official Turborepo docs for monorepo management and caching
š¬ Join the Conversation
Share your thoughts, ask questions, or simply let me know what resonated with you. I read and respond to every comment personally. Sign in with your favorite social account to participate.