0%
Sep 8, 202513 min read

The 5-Day MVP Scope

TL;DR: Any idea can become a testable MVP in 5 days if you scope it right. Cut features, not corners. Ship the smallest thing that proves your hypothesis.

Most MVPs fail because they're not minimal enough.


Why 5 Days (Not 5 Weeks)

The problem with longer timelines:

  • Feature creep becomes inevitable
  • Market conditions change
  • Team motivation declines
  • Scope confusion grows

The 5-day advantage:

  • Forces ruthless prioritization
  • Maintains urgency and focus
  • Enables rapid iteration
  • Limits technical debt accumulation
  • Creates real shipping deadlines

Constraints breed creativity. 5 days breeds MVPs that actually ship.


The 5-Day Framework

Day 1: Scope and Strip (Planning Day)

Morning: Define the core hypothesis Afternoon: Cut everything non-essential Evening: Technical architecture decisions

Day 2: Foundation (Backend Day)

Focus: Database, API, authentication basics Goal: Core data models and endpoints working No UI yet: Just API testing and data flow

Day 3: Core Feature (Logic Day)

Focus: The one thing that makes your product unique Goal: Main user workflow functioning end-to-end Basic UI: Functional, not pretty

Day 4: Interface (Frontend Day)

Focus: User interface that actually works Goal: Complete user journey from signup to core action Polish later: Ship functional, improve continuously

Day 5: Deploy and Test (Ship Day)

Morning: Production deployment Afternoon: End-to-end testing and bug fixes Evening: Share with first 10 users


Day 1: The Scoping Session

The One-Hypothesis Rule

Start with your assumption: "I believe that [target customer] will [take specific action] because [specific reason]."

Examples:

  • ✅ "Freelance designers will pay $29/month for instant client approval workflows because approval delays kill momentum"
  • ✅ "Restaurant managers will use daily profit tracking because they currently have no visibility into real-time margins"
  • ❌ "Small businesses need better project management" (too vague)
  • ❌ "People want to be more productive" (not specific enough)

The Feature Elimination Process

List everything you think you need:

Example: Client Approval Tool
□ User registration/login
□ File upload system
□ Approval workflow
□ Comments and feedback
□ Version control
□ Email notifications
□ Client billing integration
□ Analytics dashboard
□ Mobile app
□ API access
□ White-label options
□ Team management

Apply the 5-day filter:

Keep (Essential for testing hypothesis):

  • ✅ User registration (simple email/password)
  • ✅ File upload (basic, no fancy preview)
  • ✅ Approval workflow (approve/reject buttons)
  • ✅ Email notifications (simple alerts)

Cut (Nice-to-have):

  • ❌ Comments and feedback (can be email for now)
  • ❌ Version control (file naming convention works)
  • ❌ Analytics dashboard (Google Analytics sufficient)
  • ❌ Mobile app (responsive web works)

Cut (Future phases):

  • ❌ Client billing integration (manual invoicing works)
  • ❌ API access (no integration needs yet)
  • ❌ White-label options (prove core first)
  • ❌ Team management (single user sufficient)

Technical Stack Decisions (30 minutes max)

Use what you know, not what's trendy:

Frontend: React/Vue if you know it, HTML/CSS if you don't Backend: Node.js/Python/Rails - whatever's familiar Database: PostgreSQL/MySQL - avoid NoSQL complexity for MVPs Hosting: Vercel/Netlify for frontend, Railway/Render for backend Auth: Clerk/Auth0 - don't build authentication yourself

The wrong decision: Spending Day 1 researching the "best" tech stack The right decision: Using familiar tools to build faster


Day 2: Backend Foundation

Database Schema (First 2 hours)

Start with the core entities:

-- Users table (basic auth)
CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  email VARCHAR UNIQUE NOT NULL,
  password_hash VARCHAR NOT NULL,
  created_at TIMESTAMP DEFAULT NOW()
);

-- Projects table (main entity)
CREATE TABLE projects (
  id SERIAL PRIMARY KEY,
  user_id INTEGER REFERENCES users(id),
  name VARCHAR NOT NULL,
  status VARCHAR DEFAULT 'draft',
  created_at TIMESTAMP DEFAULT NOW()
);

-- Files table (what gets approved)
CREATE TABLE files (
  id SERIAL PRIMARY KEY,
  project_id INTEGER REFERENCES projects(id),
  filename VARCHAR NOT NULL,
  file_url VARCHAR NOT NULL,
  status VARCHAR DEFAULT 'pending', -- pending, approved, rejected
  created_at TIMESTAMP DEFAULT NOW()
);

Avoid over-engineering:

  • No complex relationships yet
  • No optimization (indexes can wait)
  • No audit trails or soft deletes
  • Basic data types only

API Endpoints (Remaining 6 hours)

Focus on CRUD operations:

// Essential endpoints only
POST /auth/register
POST /auth/login
GET /projects
POST /projects
GET /projects/:id
POST /projects/:id/files
PUT /files/:id/status

Don't build:

  • Complex filtering/searching
  • Batch operations
  • File processing/thumbnails
  • Advanced authentication (just basic JWT)

Testing (API only)

Manual testing with Postman/Insomnia:

  • Can create users and log in
  • Can create projects and upload files
  • Can change file approval status
  • All endpoints return proper errors

No unit tests yet: Ship first, test later


Day 3: Core Feature Implementation

The Single User Journey

Map the critical path:

  1. User uploads file to project
  2. System sends approval request to client
  3. Client clicks approve/reject link
  4. System notifies user of decision
  5. User sees updated status

Build this flow completely before anything else

File Upload Implementation

Simple, not scalable:

// Basic file upload - no fancy features
app.post("/projects/:id/files", upload.single("file"), async (req, res) => {
  const file = req.file

  // Save to local storage or basic cloud storage
  const fileUrl = await saveFile(file)

  // Create database record
  const fileRecord = await db.query(
    "INSERT INTO files (project_id, filename, file_url) VALUES ($1, $2, $3) RETURNING *",
    [req.params.id, file.originalname, fileUrl]
  )

  // Send approval email immediately
  await sendApprovalEmail(fileRecord.id)

  res.json(fileRecord)
})

What we're NOT building:

  • File type validation (accept everything for now)
  • File size limits (beyond basic server limits)
  • Preview generation
  • Multiple file uploads
  • File versioning

Approval Workflow

Dead simple approach:

// Approval endpoint - accessible via email link
app.get("/approve/:fileId/:token", async (req, res) => {
  const { fileId, token } = req.params

  // Verify token (simple approach)
  if (token !== generateSimpleToken(fileId)) {
    return res.status(400).send("Invalid approval link")
  }

  // Update file status
  await db.query("UPDATE files SET status = ? WHERE id = ?", ["approved", fileId])

  // Notify user
  await sendStatusEmail(fileId, "approved")

  res.send("File approved! The designer has been notified.")
})

// Same for reject
app.get("/reject/:fileId/:token", async (req, res) => {
  // Similar implementation for rejection
})

Simple token generation:

function generateSimpleToken(fileId) {
  // Not cryptographically secure, but fine for MVP
  return Buffer.from(`${fileId}-${process.env.SECRET_KEY}`).toString("base64")
}

Day 4: Functional Interface

The Brutally Simple UI

HTML/CSS that works:

<!-- Project dashboard -->
<div class="container">
  <h1>Your Projects</h1>
  <button onclick="createProject()">New Project</button>

  <div id="projects">
    <!-- Projects loaded via JavaScript -->
  </div>
</div>

<!-- File upload -->
<div class="upload-area">
  <input type="file" id="fileInput" />
  <button onclick="uploadFile()">Upload for Approval</button>
</div>

<!-- Status display -->
<div class="file-status">
  <span class="status pending">Pending Approval</span>
  <span class="status approved">✓ Approved</span>
  <span class="status rejected">✗ Rejected</span>
</div>

Basic styling (1-2 hours max):

.container {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}
.upload-area {
  border: 2px dashed #ccc;
  padding: 40px;
  text-align: center;
}
.status {
  padding: 5px 10px;
  border-radius: 3px;
}
.status.approved {
  background: #d4edda;
  color: #155724;
}
.status.rejected {
  background: #f8d7da;
  color: #721c24;
}
.status.pending {
  background: #fff3cd;
  color: #856404;
}

JavaScript Functionality (No Framework)

Keep it vanilla and functional:

// Project creation
async function createProject() {
  const name = prompt("Project name:")
  if (!name) return

  const response = await fetch("/projects", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ name }),
  })

  if (response.ok) {
    loadProjects() // Refresh list
  }
}

// File upload
async function uploadFile() {
  const fileInput = document.getElementById("fileInput")
  const file = fileInput.files[0]
  if (!file) return

  const formData = new FormData()
  formData.append("file", file)

  const response = await fetch(`/projects/${currentProjectId}/files`, {
    method: "POST",
    body: formData,
  })

  if (response.ok) {
    alert("File uploaded! Approval email sent.")
    loadFiles() // Refresh file list
  }
}

User Authentication (Minimal)

Simple login form:

<form id="loginForm">
  <input type="email" placeholder="Email" required />
  <input type="password" placeholder="Password" required />
  <button type="submit">Login</button>
</form>

Basic session handling:

// Store JWT in localStorage (not secure, but functional)
async function login(email, password) {
  const response = await fetch("/auth/login", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ email, password }),
  })

  if (response.ok) {
    const { token } = await response.json()
    localStorage.setItem("token", token)
    showDashboard()
  }
}

Day 5: Deploy and Ship

Morning: Production Deployment

Choose the simplest deployment:

  • Frontend: Netlify/Vercel (drag and drop)
  • Backend: Railway/Render (Git deploy)
  • Database: Planet Scale/Supabase (managed)

Environment variables checklist:

DATABASE_URL=postgresql://...
JWT_SECRET=your-secret-key
EMAIL_API_KEY=your-email-service-key
FILE_STORAGE_KEY=your-storage-key

Don't optimize yet:

  • No CDN setup
  • No caching
  • No load balancing
  • No monitoring beyond basic logs

Afternoon: End-to-End Testing

Test the complete user journey:

  1. ✅ User can register and log in
  2. ✅ User can create a project
  3. ✅ User can upload a file
  4. ✅ Email is sent to intended recipient
  5. ✅ Client can approve/reject via email link
  6. ✅ User receives notification of decision
  7. ✅ Status updates correctly in dashboard

Bug triage rules:

  • Fix immediately: Anything breaking the core flow
  • Fix before sharing: UI bugs affecting usability
  • Log for later: Nice-to-have improvements

Evening: First User Testing

Share with 10 people:

  • 5 potential customers (ideal users)
  • 3 friends/colleagues (honest feedback)
  • 2 strangers (unbiased perspective)

Ask specific questions:

  1. "Can you complete [core action] without help?"
  2. "What's confusing about this process?"
  3. "Would you pay $X/month for this?"
  4. "What's the biggest thing missing?"
  5. "How often would you use this?"

Scope Creep: The 5-Day Killer

Common Scope Creep Triggers

"This would be easy to add..."

  • Extra form fields
  • Additional user types
  • More file formats
  • Extra notification channels

"Users will expect this..."

  • Advanced search
  • Bulk operations
  • Mobile optimization
  • Real-time updates

"It's industry standard to have..."

  • User roles and permissions
  • Advanced security features
  • Comprehensive reporting
  • Integration capabilities

The Anti-Scope Creep Protocol

When tempted to add features:

  1. Stop and document: Write it down for next iteration
  2. Ask the core question: Does this prove/disprove my hypothesis?
  3. Estimate truthfully: How many hours would this really take?
  4. Remember the goal: Ship something testable, not something perfect

The 5-day rule: If you can't ship it without this feature, your scope is too big.


Post-Launch: The Next 5 Days

Days 6-10: Iteration Based on Feedback

Focus on:

  • Critical bugs that prevent core usage
  • One-click improvements (copy changes, button placement)
  • Most requested feature (if it fits the hypothesis)

Ignore:

  • Feature requests that change core value proposition
  • Technical debt that doesn't affect users
  • Scaling concerns (unless you have 100+ active users)

Week 2: Decide the Direction

Three possible outcomes:

1. Hypothesis Confirmed (Users love it)

  • Double down on core feature
  • Improve UI/UX based on usage patterns
  • Start building sustainable infrastructure

2. Hypothesis Partially Confirmed (Mixed feedback)

  • Pivot slightly based on strongest positive feedback
  • A/B test variations of core feature
  • Focus on specific user segment that responded best

3. Hypothesis Rejected (Users don't engage)

  • Kill it fast
  • Document learnings
  • Start next 5-day MVP based on learnings

FAQ

Q: What if my idea is too complex for 5 days? A: Your scope is too big. Find the smallest testable version of your hypothesis.

Q: Can I use this framework for hardware products? A: Adapt it to hardware: Day 1-2 for design, Day 3-4 for prototyping, Day 5 for testing with users.

Q: What if users expect more features? A: Users who really need your solution will use a basic version. Users who demand features first weren't real customers anyway.

Q: How do I handle technical debt from 5-day sprints? A: Refactor incrementally as you validate product-market fit. Don't optimize prematurely.


Ready to scope your 5-day MVP?

We use this framework to ship testable MVPs in one week, not one month. No feature creep, no over-engineering.

Quick Build ($750)Full Sprint ($7,500)

Internal links:

Ready to build your MVP?

Stop overthinking architecture. Start with the smallest version that proves your hypothesis works.

BuildThatMVP.
Stop planning. Start shipping.