A personal discipline system with binary outcomes. No gamification, no social features, no motivational quotes. Just execution tracking with visible consequences.
MVD is a personal operating system for daily execution. It tracks tasks across three layers (Core, Support, Discipline), calculates scores with bonuses, and determines binary pass/fail outcomes. The streak system preserves your streak on the first failure but resets everything on a second consecutive fail.
Key Features:
- Binary pass/fail day outcomes
- Three-layer task system (Core, Support, Discipline)
- Point scoring with completion bonuses
- Streak tracking with warning system
- Permanent day records (no editing after finalization)
- Full history with calendar view
- Node.js 18+ installed
- A Supabase account (free tier works)
- Git (optional, for cloning)
# Clone the repository
git clone https://github.com/UserAAR/minimum-viable-day.git
cd minimum-viable-day
# Or download and extract the ZIP filenpm install- Go to supabase.com and sign in
- Click "New Project"
- Choose your organization
- Enter a project name (e.g., "mvd")
- Set a secure database password (save this!)
- Choose a region close to you
- Click "Create new project" and wait for setup
- In your Supabase Dashboard, go to Settings → API
- Copy the following values:
- Project URL (under "Project URL")
- anon public key (under "Project API keys")
- In Supabase Dashboard, go to SQL Editor
- Click "New query"
- Paste the following SQL and click "Run":
-- Create settings table
CREATE TABLE IF NOT EXISTS mvd_settings (
id INTEGER PRIMARY KEY DEFAULT 1,
default_core_tasks JSONB DEFAULT '["Deep Work Session", "Priority Task", "Learning Block"]'::jsonb,
default_support_tasks JSONB DEFAULT '["Email Processing", "Planning Session", "Review & Reflect"]'::jsonb,
default_discipline_tasks JSONB DEFAULT '["No Social Media", "Sleep by 11pm", "Exercise"]'::jsonb,
streak INTEGER DEFAULT 0,
consecutive_fail_count INTEGER DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT single_settings CHECK (id = 1)
);
-- Create days table
CREATE TABLE IF NOT EXISTS mvd_days (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
date_key TEXT UNIQUE NOT NULL,
core_tasks JSONB DEFAULT '[]'::jsonb,
support_tasks JSONB DEFAULT '[]'::jsonb,
discipline_tasks JSONB DEFAULT '[]'::jsonb,
finalized BOOLEAN DEFAULT FALSE,
result TEXT CHECK (result IN ('PASS', 'FAIL') OR result IS NULL),
warning BOOLEAN DEFAULT FALSE,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Create indexes for faster queries
CREATE INDEX IF NOT EXISTS idx_mvd_days_date_key ON mvd_days(date_key);
CREATE INDEX IF NOT EXISTS idx_mvd_days_finalized ON mvd_days(finalized);
-- Insert default settings (will only insert if table is empty)
INSERT INTO mvd_settings (id) VALUES (1) ON CONFLICT (id) DO NOTHING;- You should see "Success. No rows returned" — this means the tables were created
- Copy the example environment file:
cp .env.example .env.local- Edit
.env.localwith your Supabase credentials:
NEXT_PUBLIC_SUPABASE_URL=https://your-project-id.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-hereReplace your-project-id and your-anon-key-here with your actual values from Supabase.
npm run devOpen http://localhost:3000 in your browser.
- Push your code to GitHub
- Go to vercel.com and import your repository
- Add environment variables in Vercel:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEY
- Deploy!
Build the production version:
npm run build
npm start├── app/
│ ├── page.tsx # Today view (main page)
│ ├── history/ # History/calendar view
│ ├── settings/ # Task configuration
│ ├── guide/ # Documentation
│ ├── layout.tsx # Root layout with providers
│ └── globals.css # Global styles
├── components/
│ ├── today-view.tsx # Today's task interface
│ ├── history-view.tsx # Calendar and day review
│ ├── settings-view.tsx # Default task editor
│ ├── guide-view.tsx # System documentation
│ ├── task-section.tsx # Task list component
│ ├── day-status.tsx # Score/status display
│ ├── mvd-header.tsx # App header
│ └── mvd-nav.tsx # Navigation tabs
├── lib/
│ ├── mvd-types.ts # TypeScript types
│ ├── mvd-context.tsx # React context/state
│ ├── mvd-database.ts # Supabase operations
│ └── supabase/
│ └── client.ts # Supabase client
└── scripts/
└── 001_create_tables.sql # Database schema
| Layer | Points | Bonus | Purpose |
|---|---|---|---|
| Core | 5/task | +5 | Primary work (non-negotiables) |
| Support | 3/task | +4 | Secondary tasks (maintenance) |
| Discipline | 2/task | +4 | Behavior/habits (self-control) |
A day is a PASS if either:
- All Core tasks are completed, OR
- Raw points exceed the Core Threshold (Core tasks × 5)
Otherwise, the day is a FAIL.
- PASS: Streak +1, warning cleared
- First FAIL: Warning issued, streak preserved
- Second consecutive FAIL: Hard fail, streak reset to 0
Finalizing a day is permanent:
- Locks all task states
- Records pass/fail result
- Updates streak/warning status
- Archives to history
- Check that your Supabase URL and key are correct in
.env.local - Verify the database tables exist (run the SQL script again)
- Check browser console for specific error messages
- Ensure your Supabase project is active (not paused)
- Check network tab for failed API calls
- Verify the
mvd_daystable exists
- Restart the development server after changing
.env.local - Make sure variable names start with
NEXT_PUBLIC_ - Don't use quotes around values in
.env.local
- Framework: Next.js 15 (App Router)
- Database: Supabase (PostgreSQL)
- Styling: Tailwind CSS
- UI Components: shadcn/ui
- Deployment: Vercel
MIT License - Use it however you want.
Execute or fail. There is no in-between.