Tornado Building
The universal problem-solving cycle that can fix any bug or implement any feature.
The Principle
Three forces spinning together create unstoppable momentum: Research, Logs, and Tests. Like a tornado, they feed each other and grow stronger with each rotation.
The Tornado Cycle
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ โ
โ ๐ช๏ธ THE TORNADO CYCLE โ
โ โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
โโโโโโโโโโโโโโโ
โ RESEARCH โ
โ + DOCS โ
โโโโโโโโฌโโโโโโโ
โ
โญโโโโโโโโโโโโผโโโโโโโโโโโโฎ
โฑ โ โฒ
โฑ โ โฒ
โฑ โ โฒ
โโโโโโโโโผโโโโโโโโ โ โโโโโโโโผโโโโโโโโ
โ โ โ โ โ
โ LOGS โโโโโโโโโดโโโโโโโบโ TESTS โ
โ โ โ โ
โโโโโโโโโฌโโโโโโโโ โโโโโโโโฌโโโโโโโโ
โ โ
โฐโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโฏ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโ
โ SOLUTION EMERGES โ
โโโโโโโโโโโโโโโโโโโโโโโ
Each element feeds the others:
RESEARCH โ informs what to LOG โ informs what to TEST
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
failures inform researchThe Three Forces
1. ๐ Research + Documentation
Before touching code, understand the landscape:
"Research the NextAuth.js documentation for:
- How session callbacks work
- The correct way to add custom fields to session
- Common pitfalls when extending the User type"What you get:
- Correct API usage
- Known edge cases
- Proven patterns
2. ๐ Logs (Observability)
Make the invisible visible:
// Add strategic logs at every decision point
console.log('[Auth] Session callback triggered', {
user: user.id,
token: token.sub,
timestamp: new Date().toISOString()
});
console.log('[Auth] Token before modification:', JSON.stringify(token, null, 2));
console.log('[Auth] Token after modification:', JSON.stringify(newToken, null, 2));What you get:
- Actual execution flow
- Real data shapes
- Exact failure points
3. ๐งช Tests (Verification)
Prove it works before shipping:
describe('Session callback', () => {
it('should add user role to session', async () => {
const session = await getSession({ user: mockUser });
expect(session.user.role).toBe('admin');
});
it('should handle missing user gracefully', async () => {
const session = await getSession({ user: null });
expect(session).toBeNull();
});
});What you get:
- Confidence it works
- Regression protection
- Documentation of behavior
How They Feed Each Other
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ THE FEEDBACK LOOP โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ RESEARCH โ
โ โ โ
โ โ "Docs say to use getServerSession, not getSession" โ
โ โผ โ
โ IMPLEMENT โโโโโโโบ LOGS โ
โ โ โ
โ โ "Log shows session is null on server" โ
โ โผ โ
โ TESTS โ
โ โ โ
โ โ "Test reveals we're calling client-side โ
โ โ function from server component" โ
โ โผ โ
โ MORE RESEARCH โ
โ โ โ
โ โ "Docs show Next.js 13+ needs different โ
โ โ approach for app router" โ
โ โผ โ
โ SOLUTION โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโExample: Debugging a Payment Integration
Cycle 1: Research
"Research the Stripe API for:
- How to create a checkout session
- Required vs optional parameters
- Webhook verification best practices"Learned: Need to include line_items and success_url
Cycle 2: Implement + Log
// payment.ts
export async function createCheckout(items: CartItem[]) {
console.log('[Stripe] Creating checkout with items:', items);
const session = await stripe.checkout.sessions.create({
line_items: items.map(item => ({
price: item.priceId,
quantity: item.quantity,
})),
mode: 'payment',
success_url: `${process.env.URL}/success`,
});
console.log('[Stripe] Session created:', session.id);
return session;
}Log output:
[Stripe] Creating checkout with items: [{priceId: undefined, quantity: 1}]
Error: Invalid price IDCycle 3: More Research
"The Stripe log shows priceId is undefined.
Research: How should I be getting the price ID from my products?"Learned: Need to store Stripe price IDs in database, not generate them
Cycle 4: Write Test
describe('createCheckout', () => {
it('should require valid price IDs', async () => {
const invalidItems = [{ priceId: undefined, quantity: 1 }];
await expect(createCheckout(invalidItems))
.rejects.toThrow('Invalid price ID');
});
it('should create session with valid items', async () => {
const validItems = [{ priceId: 'price_123', quantity: 1 }];
const session = await createCheckout(validItems);
expect(session.id).toBeDefined();
});
});Cycle 5: Solution Emerges
// Now with validation and proper data flow
export async function createCheckout(items: CartItem[]) {
// Validate all items have price IDs
const invalidItems = items.filter(item => !item.priceId);
if (invalidItems.length > 0) {
throw new Error(`Invalid price ID for items: ${invalidItems.map(i => i.name).join(', ')}`);
}
console.log('[Stripe] Creating checkout with validated items:', items);
const session = await stripe.checkout.sessions.create({
line_items: items.map(item => ({
price: item.priceId,
quantity: item.quantity,
})),
mode: 'payment',
success_url: `${process.env.NEXT_PUBLIC_URL}/success`,
cancel_url: `${process.env.NEXT_PUBLIC_URL}/cart`,
});
console.log('[Stripe] Session created:', session.id);
return session;
}The Tornado Prompt
Use this prompt to invoke the tornado cycle:
I need to [implement feature / fix bug].
Before writing code:
1. RESEARCH: Look up the documentation for [relevant APIs/libraries]
2. Identify common pitfalls and best practices
Then:
3. LOGS: Add strategic console.logs at decision points
4. TESTS: Write tests that verify the expected behavior
Show me all three parts, then implement the solution.Visual: The Acceleration Effect
Speed of Problem Solving
โ
โ โโโโ
โ โโโโ
โ โโโโ
โ โโโโ
โ โโโโ
โ โโโโ
โ โโโโ
โ โโโโ
โ โโโโ
โ โโโ
โ โโโ
โ โโโ
โ โโโ
โ โโ
โ โโ
โโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
1 2 3 4 5 6 7 8
Tornado Cycles
Each cycle builds on previous knowledge.
By cycle 4-5, solutions emerge rapidly.When to Spin the Tornado
| Situation | Why Tornado Works |
|---|---|
| New integration | Research prevents common mistakes |
| Mysterious bug | Logs reveal what's actually happening |
| Refactoring | Tests ensure you don't break things |
| Performance issue | Logs + research identify bottlenecks |
| Security concern | Research reveals threat models, tests verify fixes |
Key Takeaways
- Never skip research โ 10 minutes of docs saves 2 hours of debugging
- Logs are your eyes โ You can't fix what you can't see
- Tests lock in wins โ Each cycle's solution stays solved
- Cycles compound โ Each rotation makes you faster
The tornado works because the three forces feed each other. Research informs what to log. Logs reveal what to test. Tests expose what to research next. Skip one and the tornado weakens.
"The tornado doesn't ask permission. It spins until the problem is solved."