You're Vibe Coding Wrong (And It's Not Your Fault)
Let’s say the quiet part out loud: most people are vibe coding completely backwards.
And look, I’m not throwing shade—because until a few months ago, I was doing it wrong too. We all are. Unlike learning Java syntax, or React best practices, “vibe coding” hasn’t been around long enough to establish a set of rules.
But here’s what I figured out after building a graveyard of failed projects and then pivoting to a living room full of apps my family uses every day: vibe coding isn’t about prompting harder. It’s about planning smarter.
This isn’t theory. This is the battle-tested process I use to build functional apps in under an hour. Real apps. The task tracker my son uses every morning. The AI news aggregator that monitors Reddit, YouTube, Twitter, and Bluesky every six hours and feeds me perfectly summarized updates through Claude. The dozen little tools that went from “wouldn’t it be cool if...” to “here, I built it” in the time it used to take me to argue with myself about which framework to pick.
I had to shift my mindset. I stopped treating AI like magic and started treating it like a product team.
You’re not here to write code faster—you’re here to ship actual working software. And that requires something the AI influencers completely skipped over: a systematic process that transforms AI from a random code generator into a disciplined execution engine.
Let me show you exactly how this works. Not the theory. Not the vision. The actual tactical playbook that took me from maybe 10% success rate to damn near 100%.
Because here’s the thing about this moment we’re in: the barrier between having an idea and shipping working software just collapsed. Not for some future version of AI. Not with some secret technique. Right now. Today. With the tools you already have access to.
But only if you know the process.
Ready? Let’s go.
The Expensive Lesson: Why Most Vibe Coding Fails
Let me paint you a picture of my failure graveyard. There’s a half-built recipe app over there. Next to it, a fitness tracker that never tracked anything. Behind them, a budgeting tool that couldn’t budget, a habit tracker that broke, and about twenty other projects that sounded great at 9 PM and were dead by Tuesday.
Every single one failed for the same reason: I jumped straight to Claude Code and let it make the decisions.
Here’s what that looked like: “Hey Claude, let’s build a recipe app!” And Claude Code would say, “Great! Let’s use Next.js 14 with Server Actions, Supabase for the backend, and Tailwind with shadcn/ui.” And I’d say “sure, sounds good!” without realizing I’d never actually deployed a Next.js app with Server Actions before, or that I’d need to figure out Supabase auth, or that I’d spend three hours debugging environment variables.
The tech stack trap is real. When you’re not familiar with the tools, every error becomes a research project. Every bug becomes a “wait, how does this even work?” moment. And eventually, you get frustrated and abandon the whole thing.
If you don’t have a roadmap, AI will take whatever route it wants. And that route might be technically correct but completely wrong for you.
The breakthrough came when I stopped treating vibe coding like magic and started treating it like what it actually is: a compressed product development cycle with AI as your team.
The Three-Tool Process: Brainstorm, Refine, Execute
Here’s the system that transformed my success rate from maybe 10% to damn near 100%:
ChatGPT Voice → Brainstorming (20min-1.5hrs)
Claude Sonnet 4.5 → Refinement and validation
Claude Code → Execution
Why three different tools? Because each one is optimized for a different part of the process. ChatGPT’s voice mode is incredible for talking through ideas. Claude Sonnet 4.5 is brilliant at structured thinking and catching gaps. Claude Code is an execution machine when it has clear instructions.
The handoffs between these tools create natural checkpoints. You can’t just barrel forward—you have to export, review, refine. That friction is a feature, not a bug.
Phase 1: Brainstorming Like a Product Manager
This is where everything changes. You need to shift your mindset: you’re not just vibe coding, you’re product managing.
I open ChatGPT’s voice assistant and start with a prompt that sets the entire tone:
“This is a brainstorming session for a project. You’re acting as a product manager helping me think through this. At the end of this session, we’re going to create a complete project plan including tech stack and development phases. I need you to push back on my assumptions and poke holes in my thinking. The problem statement we’re trying to solve for is XYZ.”
That last part—the problem statement—is your anchor. Everything flows from there.
For my son’s reminder app, the problem was crystal clear: “[Son’s name'] needs to track his school tasks throughout the week, and I need to be able to see the tasks.” That simple statement drove every decision that followed.
Then comes the critical move: I define my tech stack upfront.
“I’m comfortable with React Native, Node/Express, and PostgreSQL. I’m open to alternatives, but this is my default stack. I prefer to deploy to Railway and Vercel. I know how to build APKs with Expo.”
This saves you hours of frustration. Nine times out of ten, ChatGPT will work within that stack. And when it suggests something different, it’s usually for a good reason and it explains why.
During the brainstorming session (anywhere from 20 minutes to 90 minutes depending on complexity), we nail down:
The core problem and end goal
User flows and screens
Tech stack I’m confident deploying
Success criteria (what does “done” look like?)
Potential gotchas and edge cases
The voice interface is key here. I can think out loud, interrupt, redirect, riff on ideas. It’s way faster than typing, and the conversational flow helps surface assumptions I didn’t know I was making.
When we’re done, I have ChatGPT create a project plan that I bring into my next tool.
Phase 2: Refinement with Claude
Now I take that brainstorming export and drop it into Claude Desktop with Sonnet 4.5.
The prompt is simple: “I just brainstormed this project plan with ChatGPT. I want to pass this to Claude Code for execution. Can you verify the process, check that the phases make sense, and make sure I’m not missing anything critical?”
Claude is scary good at this. It catches:
Dependencies I forgot to mention
Phase ordering issues (”You need auth working before you build the task screen”)
Unclear requirements (”You said ‘grayscale theme’ but didn’t specify the actual color values”)
Tech stack conflicts (”You’ll need to configure Expo for Android-only builds”)
This is the validation pass. The cleanup. The “measure twice, cut once” moment.
After some back and forth, I have Claude generate a final artifact: a markdown project plan that becomes my single source of truth.
This is a contract between me and my AI coding team about what we’re building and how we’re building it.
The Anatomy of a Killer Project Plan
Here’s the real project plan I used to build my son’s reminder app in about 2 hours sitting in front of the TV watching Star Trek:
# [Son]’s Weekday Reminder App - Complete Project Plan
## Overview
A simple, grayscale weekday reminder app for Android. [Son] can check off school tasks throughout the week, and both Parent (Sterling) and Kid ([Son]) can log in with their own passwords.
---
## Goals & Scope
### Goals
- Login with password only (2 users: Sterling & [Son])
- Home screen shows Mon-Fri with personalized greeting (”Hello [Son]” or “Hello Sterling”)
- Tap a day → see that day’s task list
- Check off tasks with strikethrough
- Day checkbox auto-completes when all tasks done
- Weekly reset on Sunday at 1:00 AM
- Parent can toggle “kid can edit” to lock/unlock task editing
- Add tasks via “+” button on day screen
- Loading spinner between screen transitions
### Non-Goals (v1)
- No Saturday/Sunday
- No history view (backend tracks it, UI later)
- No notifications (can add in v2)
- Android-only (sideload APK)
---
## Tech Stack
### Frontend
- **Framework**: React Native (Expo) with TypeScript
- **Platform**: Android only
- **State**: Zustand or Redux Toolkit
- **Navigation**: React Navigation (Native Stack)
- **UI**: Grayscale theme, custom wavy-edge components
### Backend
- **Host**: Railway
- **API**: Node.js + Express + TypeScript
- **Database**: PostgreSQL on Railway
- **Auth**: Simple password-based (bcrypt for hashing)
### Deployment
- Sideload APK to phones (no Play Store for v1)
- Backend deployed via Railway GitHub integration
---
## UI Design (from [Son]’s sketches)
### Screen 1: Login
```
┌─────────────────────────┐
│ │
│ [password field] │ ← Masked with dots
│ │
│ [Login Button] │
│ │
└─────────────────────────┘
```
### Screen 2: Home (Weekdays)
```
┌─────────────────────────┐
│ Hello [Son] │ ← Personalized greeting
│ │
│ ╭─ Monday ─────────╮□ │ ← Wavy edges, checkbox right
│ ╰───────────────────╯ │
│ │
│ ╭─ Tuesday ────────╮□ │
│ ╰───────────────────╯ │
│ │
│ ╭─ Wednesday ──────╮□ │
│ ╰───────────────────╯ │
│ │
│ ╭─ Thursday ───────╮□ │
│ ╰───────────────────╯ │
│ │
│ ╭─ Friday ─────────╮□ │
│ ╰───────────────────╯ │
└─────────────────────────┘
```
- Day checkbox shows ✓ when ALL tasks for that day are completed
- Tap a day strip to navigate to day details
### Screen 3: Day Details
```
┌─────────────────────────┐
│ Monday [+] │ ← Add task button (upper right)
│ │
│ ╭─ Task 1 ────────╮ □ │ ← Wavy task strips
│ ╰───────────────────╯ │
│ │
│ ╭─ Task 2 ────────╮ ✓ │ ← Checked + strikethrough
│ ╰───────────────────╯ │
│ │
│ ╭─ Task 3 ────────╮ □ │
│ ╰───────────────────╯ │
└─────────────────────────┘
```
### Loading Transitions
- Show spinner/loading indicator between screen navigations
---
## Database Schema (PostgreSQL)
### `users`
```sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL, -- ‘[Son]’ or ‘sterling’
password_hash VARCHAR(255) NOT NULL,
role VARCHAR(10) NOT NULL, -- ‘parent’ or ‘kid’
display_name VARCHAR(100) NOT NULL, -- ‘[Son]’ or ‘Sterling’
created_at TIMESTAMP DEFAULT NOW()
);
```
### `settings`
```sql
CREATE TABLE settings (
id SERIAL PRIMARY KEY,
kid_can_edit BOOLEAN DEFAULT TRUE,
notify_time TIME DEFAULT ‘07:15’, -- For future notifications
timezone VARCHAR(50) DEFAULT ‘America/New_York’,
updated_at TIMESTAMP DEFAULT NOW()
);
```
### `task_templates`
```sql
CREATE TABLE task_templates (
id SERIAL PRIMARY KEY,
weekday VARCHAR(3) NOT NULL, -- ‘mon’, ‘tue’, ‘wed’, ‘thu’, ‘fri’
text TEXT NOT NULL,
display_order INTEGER NOT NULL,
active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
```
### `task_completions`
```sql
CREATE TABLE task_completions (
id SERIAL PRIMARY KEY,
template_id INTEGER REFERENCES task_templates(id) ON DELETE CASCADE,
completed_date DATE NOT NULL, -- Actual date task was completed
completed_by VARCHAR(50) NOT NULL, -- ‘[Son]’ or ‘sterling’
completed_at TIMESTAMP DEFAULT NOW()
);
```
**Indexes:**
```sql
CREATE INDEX idx_task_templates_weekday ON task_templates(weekday, active);
CREATE INDEX idx_task_completions_date ON task_completions(completed_date);
CREATE INDEX idx_task_completions_template ON task_completions(template_id, completed_date);
```
---
## API Endpoints
### Authentication
- `POST /api/auth/login`
- Body: `{ password: string }`
- Returns: `{ token: string, user: { username, displayName, role } }`
- Validates password, returns JWT token
- `GET /api/auth/me`
- Headers: `Authorization: Bearer <token>`
- Returns current user info
### Tasks
- `GET /api/tasks/:weekday`
- Returns all active task templates for a weekday with completion status for current week
- Response: `{ tasks: [{ id, text, order, completed: boolean }] }`
- `POST /api/tasks`
- Body: `{ weekday: string, text: string }`
- Creates new task template (requires parent or kid_can_edit=true)
- `PUT /api/tasks/:id`
- Body: `{ text: string }`
- Updates task text (requires parent or kid_can_edit=true)
- `DELETE /api/tasks/:id`
- Soft delete (sets active=false)
- Requires parent or kid_can_edit=true
- `POST /api/tasks/:id/complete`
- Marks task as complete for current date
- Body: `{ completed: boolean }`
- Creates/deletes task_completion record
### Settings
- `GET /api/settings`
- Returns current settings (kid_can_edit, notify_time, timezone)
- `PUT /api/settings`
- Body: `{ kid_can_edit?: boolean, notify_time?: string, timezone?: string }`
- Updates settings (parent only)
### Weekly Status
- `GET /api/week/status`
- Returns completion status for all weekdays in current week
- Response: `{ monday: { total: 5, completed: 3 }, tuesday: {...}, ... }`
---
## App State Management (Zustand)
### Auth Store
```typescript
interface AuthState {
user: User | null;
token: string | null;
login: (password: string) => Promise<void>;
logout: () => void;
isLoading: boolean;
}
```
### Tasks Store
```typescript
interface TasksState {
tasksByDay: Record<Weekday, Task[]>;
weekStatus: Record<Weekday, { total: number; completed: number }>;
fetchTasksForDay: (weekday: Weekday) => Promise<void>;
fetchWeekStatus: () => Promise<void>;
toggleTask: (taskId: number, completed: boolean) => Promise<void>;
addTask: (weekday: Weekday, text: string) => Promise<void>;
updateTask: (taskId: number, text: string) => Promise<void>;
deleteTask: (taskId: number) => Promise<void>;
}
```
### Settings Store
```typescript
interface SettingsState {
kidCanEdit: boolean;
notifyTime: string;
timezone: string;
fetchSettings: () => Promise<void>;
updateSettings: (settings: Partial<Settings>) => Promise<void>;
}
```
---
## Rolling Week Logic
### Reset Behavior
- **When**: Every Sunday at 1:00 AM
- **What happens**:
- All task completions for the previous week remain in database (history)
- UI shows all tasks as unchecked for the new week
- All day checkboxes on Screen 2 are cleared
### Day Completion
- A day’s checkbox on Screen 2 is checked (✓) when ALL tasks for that day are marked complete
- This is calculated in real-time based on task_completions for today’s date
### Task Completion Tracking
- When [Son] checks a task on “Monday, October 14, 2025”:
- Record created in `task_completions` with `completed_date = 2025-10-14`
- If unchecked, record is deleted
- Historical data preserved: “On Monday Oct 14, [Son] completed 4/5 tasks”
---
## Project Structure
```
reminder-app/
├── backend/
│ ├── src/
│ │ ├── index.ts # Express app entry
│ │ ├── config/
│ │ │ └── database.ts # PostgreSQL connection
│ │ ├── middleware/
│ │ │ ├── auth.ts # JWT verification
│ │ │ └── errorHandler.ts
│ │ ├── routes/
│ │ │ ├── auth.ts
│ │ │ ├── tasks.ts
│ │ │ ├── settings.ts
│ │ │ └── week.ts
│ │ ├── controllers/
│ │ │ ├── authController.ts
│ │ │ ├── tasksController.ts
│ │ │ ├── settingsController.ts
│ │ │ └── weekController.ts
│ │ ├── models/
│ │ │ └── db.ts # SQL query functions
│ │ └── utils/
│ │ ├── jwt.ts
│ │ └── bcrypt.ts
│ ├── migrations/
│ │ ├── 001_create_users.sql
│ │ ├── 002_create_settings.sql
│ │ ├── 003_create_task_templates.sql
│ │ └── 004_create_task_completions.sql
│ ├── package.json
│ └── tsconfig.json
│
├── mobile/
│ ├── app/
│ │ ├── (auth)/
│ │ │ └── login.tsx
│ │ ├── (tabs)/
│ │ │ ├── index.tsx # Home: weekdays
│ │ │ ├── day/[weekday].tsx # Day details
│ │ │ └── settings.tsx # Parent settings
│ │ └── _layout.tsx
│ ├── components/
│ │ ├── WavyStrip.tsx # Reusable wavy-edge component
│ │ ├── CheckboxItem.tsx # Task with checkbox
│ │ ├── DayTile.tsx # Weekday strip for home
│ │ ├── LoadingSpinner.tsx
│ │ └── PasswordInput.tsx
│ ├── store/
│ │ ├── authStore.ts
│ │ ├── tasksStore.ts
│ │ └── settingsStore.ts
│ ├── lib/
│ │ ├── api.ts # API client
│ │ └── types.ts # TypeScript types
│ ├── constants/
│ │ └── theme.ts # Grayscale colors
│ ├── app.json
│ ├── package.json
│ └── tsconfig.json
```
---
## Implementation Phases
### Phase 0: Project Setup (Day 1)
**Backend**
- [ ] Initialize Node/Express TypeScript project
- [ ] Set up PostgreSQL connection (Railway database URL)
- [ ] Create migration files for all tables
- [ ] Run migrations and verify schema
- [ ] Add seed data (2 users: [Son], sterling)
- [ ] Deploy to Railway and verify connection
**Frontend**
- [ ] Initialize Expo TypeScript project
- [ ] Install dependencies (React Navigation, Zustand, AsyncStorage)
- [ ] Configure Expo for Android-only build
- [ ] Set up API client with Railway backend URL
- [ ] Create basic folder structure
**Definition of Done:**
- Backend running on Railway, database schema created
- Mobile app runs on Android emulator
- API client can ping backend health check endpoint
---
### Phase 1: Authentication (Day 1-2)
**Backend**
- [ ] Implement password hashing (bcrypt)
- [ ] Create JWT signing/verification utilities
- [ ] Build `/api/auth/login` endpoint
- [ ] Build `/api/auth/me` endpoint
- [ ] Create auth middleware for protected routes
**Frontend**
- [ ] Create Login screen with password input (masked)
- [ ] Build auth store (Zustand)
- [ ] Implement login flow (password → token → AsyncStorage)
- [ ] Create auth gate (redirect to login if not authenticated)
- [ ] Add logout functionality
**Testing:**
- [ ] Test login with both passwords ([Son] & sterling)
- [ ] Verify token persists across app restarts
- [ ] Test invalid password returns error
**Definition of Done:**
- [Son] and Sterling can log in with their passwords
- Token stored securely in AsyncStorage
- Protected routes require valid token
---
### Phase 2: Home Screen - Weekdays List (Day 2-3)
**Backend**
- [ ] Implement `/api/week/status` endpoint
- Calculate total/completed tasks per day
- Return data for current week only
**Frontend**
- [ ] Create Home screen with personalized greeting
- [ ] Build `WavyStrip` component (grayscale, wavy edges)
- [ ] Build `DayTile` component (day name + checkbox)
- [ ] Implement week status store (Zustand)
- [ ] Fetch week status on screen load
- [ ] Display Mon-Fri with completion checkboxes
- [ ] Add loading spinner during fetch
- [ ] Navigate to day details on tap
**Testing:**
- [ ] Verify greeting shows “Hello [Son]” or “Hello Sterling”
- [ ] Check that day checkboxes reflect task completion status
- [ ] Test navigation to day details
**Definition of Done:**
- Home screen shows Mon-Fri with proper greeting
- Day checkboxes auto-check when all tasks complete
- Tapping a day navigates to details
---
### Phase 3: Day Details Screen (Day 3-5)
**Backend**
- [ ] Implement `/api/tasks/:weekday` endpoint
- Return active task templates
- Include completion status for current date
- [ ] Implement `/api/tasks/:id/complete` endpoint
- Create/delete task_completion record
- Return updated task state
**Frontend**
- [ ] Create Day Details screen
- [ ] Build `CheckboxItem` component with strikethrough
- [ ] Fetch tasks for selected weekday
- [ ] Implement task toggle (check/uncheck)
- [ ] Add loading spinner during fetch
- [ ] Show empty state if no tasks
- [ ] Optimistic UI updates (instant feedback)
**Testing:**
- [ ] Verify tasks load for each weekday
- [ ] Test checking/unchecking tasks
- [ ] Confirm strikethrough appears on checked tasks
- [ ] Test that completion persists across app restarts
**Definition of Done:**
- Day screen shows all tasks for selected weekday
- Checking tasks adds strikethrough
- Changes persist to database
- UI updates instantly (optimistic)
---
### Phase 4: Add/Edit/Delete Tasks (Day 5-6)
**Backend**
- [ ] Implement `/api/tasks` POST endpoint (create task)
- [ ] Implement `/api/tasks/:id` PUT endpoint (update task)
- [ ] Implement `/api/tasks/:id` DELETE endpoint (soft delete)
- [ ] Add permission checks (parent or kid_can_edit)
**Frontend**
- [ ] Add “+” button in upper right of Day Details screen
- [ ] Create add task modal/input
- [ ] Implement add task flow
- [ ] Add long-press to edit task text
- [ ] Add swipe-to-delete (with confirmation)
- [ ] Check `kid_can_edit` setting before allowing edits
- [ ] Show disabled state if kid can’t edit
**Testing:**
- [ ] Test adding new task
- [ ] Test editing task text
- [ ] Test deleting task (soft delete)
- [ ] Verify kid_can_edit=false prevents edits
- [ ] Test that parent can always edit
**Definition of Done:**
- Tasks can be added via “+” button
- Tasks can be edited and deleted
- Permissions enforced based on role and settings
---
### Phase 5: Settings Screen (Day 6-7)
**Backend**
- [ ] Implement `/api/settings` GET endpoint
- [ ] Implement `/api/settings` PUT endpoint (parent only)
**Frontend**
- [ ] Create Settings screen (parent only)
- [ ] Add toggle for “Kid Can Edit”
- [ ] Add time picker for notification time (future use)
- [ ] Add timezone selector (future use)
- [ ] Save settings to backend
- [ ] Show settings are loading spinner
**Testing:**
- [ ] Test toggling kid_can_edit
- [ ] Verify changes persist
- [ ] Confirm kid role cannot access settings
**Definition of Done:**
- Parent can toggle kid_can_edit
- Settings persist across sessions
- Kid cannot access settings screen
---
### Phase 6: Rolling Week Reset (Day 7)
**Backend**
- [ ] Create cron job or scheduled task for Sunday 1:00 AM
- [ ] Logic: Keep all task_completions, but UI shows new week
- [ ] Alternative: Handle reset client-side by filtering completions by date
**Frontend**
- [ ] Add date logic to tasks store
- [ ] Filter task completions to show only current week
- [ ] Reset week status on Sunday 1:00 AM
- [ ] Test rollover behavior
**Testing:**
- [ ] Manually test by changing system date
- [ ] Verify old completions preserved in database
- [ ] Verify new week shows all tasks unchecked
**Definition of Done:**
- Week resets every Sunday at 1:00 AM
- Historical data preserved
- UI shows fresh week for [Son]
---
### Phase 7: Polish & Accessibility (Day 7-8)
**Frontend**
- [ ] Add loading spinners between all screen transitions
- [ ] Improve wavy edge styling
- [ ] Add accessibility labels to all interactive elements
- [ ] Ensure tap targets are ≥ 44x44 points
- [ ] Test with TalkBack (Android screen reader)
- [ ] Add error states (network errors, etc.)
- [ ] Add empty states (”No tasks yet”)
- [ ] Refine grayscale theme
**Testing:**
- [ ] Full accessibility audit
- [ ] Test on real Android device
- [ ] Verify all animations are smooth
- [ ] Check offline behavior
**Definition of Done:**
- App is fully accessible
- Loading states everywhere
- Graceful error handling
- Beautiful grayscale design
---
### Phase 8: Testing & Build (Day 8-9)
**Backend**
- [ ] Write unit tests for auth logic
- [ ] Write integration tests for API endpoints
- [ ] Test password validation edge cases
**Frontend**
- [ ] Write unit tests for stores (Zustand)
- [ ] Write component tests (React Native Testing Library)
- [ ] Test navigation flows
- [ ] End-to-end test: login → check tasks → logout
**Build & Deploy**
- [ ] Configure EAS Build for Android
- [ ] Build APK for sideloading
- [ ] Test APK on both devices ([Son]’s & Sterling’s)
- [ ] Document installation steps
**Definition of Done:**
- All critical paths tested
- APK built and sideloadable
- App works on both phones
---
## Key Technical Details
### Password Authentication
- Passwords stored as bcrypt hashes
- JWT tokens with 7-day expiration
- Token stored in AsyncStorage (React Native)
- Middleware validates token on protected routes
### Task Completion Logic
```typescript
// Pseudo-code for day completion check
function isDayComplete(weekday: Weekday, date: Date): boolean {
const tasks = getTasksForWeekday(weekday);
const completions = getCompletionsForDate(date);
return tasks.every(task =>
completions.some(c => c.template_id === task.id)
);
}
```
### Wavy Strip Component
```typescript
// Use SVG or react-native-svg for wavy edges
// Create a reusable component with props:
// - text: string
// - checked: boolean
// - onPress: () => void
```
### Grayscale Theme
```typescript
const colors = {
background: ‘#F5F5F5’,
stripBackground: ‘#FFFFFF’,
stripBorder: ‘#CCCCCC’,
text: ‘#000000’,
textMuted: ‘#666666’,
checkbox: ‘#333333’,
checkmark: ‘#000000’,
};
```
---
## Environment Variables
### Backend (.env)
```
DATABASE_URL=postgresql://user:password@railway.internal:5432/db
JWT_SECRET=your-secret-key-here
PORT=3000
NODE_ENV=production
```
### Frontend (app.json or .env)
```
API_BASE_URL=https://your-railway-app.railway.app
```
---
## Seed Data (for testing)
```sql
-- Insert users
INSERT INTO users (username, password_hash, role, display_name) VALUES
(’[Son]’, ‘$2b$10$...’, ‘kid’, ‘[Son]’),
(’sterling’, ‘$2b$10$...’, ‘parent’, ‘Sterling’);
-- Insert default settings
INSERT INTO settings (kid_can_edit, notify_time, timezone) VALUES
(true, ‘07:15’, ‘America/New_York’);
-- Insert sample tasks
INSERT INTO task_templates (weekday, text, display_order) VALUES
(’mon’, ‘Bring gym shoes’, 1),
(’mon’, ‘Library book due’, 2),
(’tue’, ‘Science homework’, 1),
(’wed’, ‘Art supplies’, 1),
(’thu’, ‘Spelling test’, 1),
(’fri’, ‘Permission slip’, 1);
```
---
## Risks & Mitigations
### Risk: Week reset fails
**Mitigation**: Implement client-side date filtering as backup. Even if server reset fails, app shows correct week based on current date.
### Risk: Offline behavior
**Mitigation**: Use AsyncStorage to cache tasks. Queue mutations and sync when online.
### Risk: Concurrent edits (both users editing same task)
**Mitigation**: Last write wins. Simple conflict resolution for v1.
### Risk: APK installation issues
**Mitigation**: Document step-by-step sideloading process. Enable “Install from Unknown Sources.”
---
## Future Enhancements (Post v1)
- [ ] Push notifications at set time
- [ ] History view (see past weeks)
- [ ] Multiple kids per family
- [ ] Task templates (reusable task lists)
- [ ] Dark mode support
- [ ] Task notes/details
- [ ] Recurring task patterns beyond weekly
- [ ] Export data to CSV/JSON
- [ ] Parent dashboard (web view)
---
## Success Criteria
✅ [Son] can log in with his password
✅ [Son] sees “Hello [Son]” on home screen
✅ [Son] can view tasks for each weekday
✅ [Son] can check off tasks (strikethrough appears)
✅ Day checkbox auto-completes when all tasks done
✅ Sterling can toggle “kid can edit” setting
✅ Week resets every Sunday at 1:00 AM
✅ App works offline (with cached data)
✅ App is accessible (TalkBack compatible)
✅ APK installs and runs on both Android phones
---
## Development Timeline
- **Phase 0**: 1 day (setup)
- **Phase 1**: 1-2 days (auth)
- **Phase 2**: 1-2 days (home screen)
- **Phase 3**: 2-3 days (day details)
- **Phase 4**: 1-2 days (add/edit/delete)
- **Phase 5**: 1 day (settings)
- **Phase 6**: 1 day (weekly reset)
- **Phase 7**: 1-2 days (polish)
Phase 3: Execution with Claude Code
Here’s where it gets fun.
I create a brand new directory. Empty. Nothing in it. I haven’t run git init
. I haven’t created any folders. It’s completely blank.
Then I drop in one file: the markdown project plan.
Now I fire up Claude Code: “I have a project plan in this directory. Let’s start with Phase 0. Do not move to Phase 1 until Phase 0 is complete and tested.”
This is the non-negotiable rule that makes everything work:
“Do not move to the next phase until the current phase is tested and working.”
This single instruction prevents the death spiral where you’re 80% done with a project and realize the foundation is broken. It forces incremental validation. It catches issues early. It enables clean git commits (one per phase). It prevents the “let’s refactor everything” catastrophe.
The Parallel Workflow
While Claude Code is setting up the backend and database schema, I’m not just watching progress bars. I’m:
Creating my Railway account and provisioning the database
Setting up environment variables
Generating JWT secrets
Installing Expo CLI
By the time Phase 1 (Authentication) starts, everything Claude Code needs is ready to go.
The Iteration Loop
The rhythm becomes:
Claude Code completes a phase
It provides specific testing instructions
I test and validate
Everything works? Green light for next phase
Something’s broken? Debug before advancing
Don’t move onto the next phase unless everything in the current phase is working and tested.
When errors pop up (and they will), I drop the error message right into Claude Code. It has full context from the project plan, so solutions are targeted, not random guessing.
For the reminder app, Phase 3 (Day Details Screen) took three attempts because I discovered the completion state wasn’t syncing correctly. But because Phase 1 and 2 were solid, I knew exactly where the problem was. Fix, test, commit, move on.
The Product Team Mindset
Here’s the reframe that matters: treat this like you’re running a real product team, just with highly compressed sprints.
Some projects take one hour start to finish. My AI news aggregator? I vibe coded that over three weeks, in hour-long sessions after my kids went to bed. Each session was a sprint with a clear goal:
Night 1: Set up Reddit monitoring
Night 2: Add YouTube transcript scraping
Night 3: Build the RAG database
Night 4: Create the MCP server integration
Night 5: Polish the query interface
Each night: ship one feature. Test it. Commit it. Next session builds on a solid foundation.
This is product development at 10x speed, but the principles are identical. Features, not chaos. Testing, not hoping. Incremental progress, not big-bang deployments.
Version control is your friend. After each phase, commit. Your git history becomes a beautiful progression: “Phase 1: Auth complete”, “Phase 2: Home screen complete”, “Phase 3: Day details complete”. If something breaks later, you can roll back to a working state instantly.
Real Results: What This Enables
Let me show you what’s actually possible when you follow this process:
[Son’s] Reminder App - My son wanted to track his school tasks. In one weekend (8 hours total), we built a full Android app with login, task management, parent controls, and a rolling weekly reset. He uses it every single day. It works.
AI News Aggregator - Every 6 hours, an automated agent monitors Reddit’s AI subreddits, YouTube channels like AI Daily Brief, Twitter AI discussions, and Bluesky threads. Everything gets stored in a PostgreSQL database. I connected it to Claude Desktop via an MCP server. Now I just ask: “What’s the most recent AI news?” or “Catch me up on the last 24 hours” and get a perfect summary with links.
Both of these are real, production applications that solve actual problems. Not demos. Not half-working prototypes. Shipped products.
The time equation looks like this:
Planning: 30 minutes to 2 hours
Execution: 30 minutes to several hours
Total for simple tools: Under one hour
Total for complex apps: Under one day
Compare that to the alternative: weeks of unstructured coding that maybe results in something working.
The Key Principles (Save This)
Plan like a product manager, vibe code like a developer
Define your tech stack upfront — stick to what you know unless there’s a compelling reason to learn
Phase-by-phase with hard testing gates — no forward progress on broken foundations
One clear problem statement drives everything — if you can’t articulate the problem, you can’t solve it
Let AI push back on your assumptions early — that’s where the magic happens
Empty directory + plan = forced discipline — no shortcuts, no “I’ll define that later”
Commit after each phase — your future self will thank you
Treat it like a real product team — sprints, validation, iteration, not chaos
Common Pitfalls to Avoid
I learned these the hard way, so you don’t have to:
Skipping the planning phase — This is how you join my graveyard of abandoned projects. Every. Single. Time.
Letting Claude Code choose the tech stack — Unless you’re explicitly learning something new, use tools you know. The friction isn’t worth it.
Moving to the next phase with untested code — This is death. You’re building a house of cards. When it collapses (and it will), you won’t know which layer failed.
Vague problem statements — “I want to build a productivity app” gives Claude Code nothing to work with. “I need to track my son’s school tasks throughout the week” gives it everything.
No Definition of Done for phases — How do you know Phase 1 is complete? If you can’t answer that, you’re not ready to start.
Trying to build too much at once — Start with v1. Ship it. Then iterate. The apps that survive are the ones that launch.
Getting Started: Your First Vibe-Coded Project
Start small. Like, really small. Pick something that genuinely annoys you—a personal pain point you’d use every day. Maybe it’s a dashboard for your favorite API. Maybe it’s a tool to organize your screenshots. Maybe it’s a simple game for your kids.
Keep it to 3-5 screens maximum for v1. You can always add more later.
The Checklist:
20-60 minute ChatGPT brainstorm with a crystal clear problem statement (let it poke holes)
Tech stack you’re already comfortable with (no learning three new frameworks)
Claude refinement pass (let it poke more holes)
Markdown plan with explicit phases and testing criteria
Empty directory start (just the plan, nothing else)
Test after each phase (seriously, don’t skip this)
Ship it (even if it’s just to yourself)
Success looks like: you have a working app, you understand every technical decision, you can extend it when you want to, and most importantly—you actually use it.
The Real Shift
This isn’t about coding faster. It’s about shipping more.
The secret isn’t better AI or better prompts. It’s treating AI as your product team instead of your replacement. You’re the product manager. You set the vision. You make the calls. AI executes with superhuman speed—but only when you give it clarity.
My graveyard of failed projects taught me what doesn’t work. My living room full of apps my family uses every day taught me what does.
The barrier between “I wish I had a tool that...” and “here’s the tool I built” just collapsed. Not because the tech got better (though it did), but because the process got clearer.
Planning doesn’t slow you down. Planning unlocks speed.
You can build what you need, when you need it. The tools are here. The process works. The only question is: what are you going to ship first?
Start with one small project. Follow the process. See what happens.
Then tell me about it—I want to hear what you build.