
Markdown Notes Web App Scoped for Two Weeks. A Build Next Stack field guide for learners shipping small projects.
Two-week ceiling: what fits and what waits
This app is for one user—you—creating markdown notes in a browser, listing them, editing, and viewing rendered HTML. Two weeks means roughly ten working sessions. In scope: CRUD on notes stored as files or SQLite blobs, markdown preview, basic layout. Out of scope: folders, sharing, real-time collaboration, WYSIWYG toolbars, mobile apps, full-text search across attachments.
Pick a stack you can deploy on a free tier: e.g. FastAPI + Jinja + SQLite, or Express + EJS + filesystem. The lesson is scoping under calendar pressure and finishing with a URL you use for actual meeting notes—not feature parity with Notion.
Define a single user story on a index card: After standup I open the app, create a note titled with the date, paste three bullets, save, and find it tomorrow from the list. If a feature does not serve that story, it waits.
Milestone one: create and list notes
Days 1–4: models and routes. Note fields: id, title, body markdown, updated_at. Routes:
- GET / — list titles sorted by updated desc.
- GET /notes/new — empty form.
- POST /notes — create, redirect to view.
- GET /notes/:id — render markdown to HTML read-only.
Store markdown raw; render on read. Title defaults to first line of body if blank. Acceptance: create three notes, restart server, list persists. Use server-side validation: title max 200 chars, body max 100k to prevent accidental paste bombs.
Escape HTML in titles when rendering list page—markdown in title field is out of scope. XSS from your own notes still teaches sanitization; pretend an old note could contain a script tag from a pasted webpage.
Milestone two: edit flow and safe markdown rendering
Days 5–8: add edit form and PUT or POST update route. Show preview tab optional—if preview doubles time, ship edit-with-save and add preview week two only if ahead.
Render markdown through a library that sanitizes HTML output (disable raw HTML in user markdown unless you trust yourself exclusively). Code blocks and lists must survive round-trip: edit → save → view → edit shows identical source.
Autosave is out of scope; manual save button teaches explicit commits. Show last saved timestamp on view page. Acceptance: edit note twice; history is last version only—no version control yet, and that is fine.
Add delete with a confirm page, not JavaScript alert—server-rendered confirm teaches form POST patterns and prevents accidental loss from mis-clicked AJAX. Log deletes to stdout in dev if you want audit without building audit UI.
Acceptance checks for a solo user
Before declaring two-week project complete:
- Use the app for five real meetings or study sessions—not dummy text.
- List page loads under 300ms local with fifty notes.
- Broken markdown (unclosed code fence) renders without 500 error.
- Deploy HTTPS URL; create note from phone browser (even if editing on phone is clumsy).
- Backup script copies DB or notes folder to zip in one command.
If any check fails, cut a feature rather than extend the deadline. Scope discipline is the deliverable equal to code.
Screenshot the list page with fifty notes once as a performance baseline. If you cannot generate fifty real notes, duplicate lorem entries with distinct titles—performance testing with empty DB teaches nothing.
Styling just enough to read on a phone
One column, system font stack, sixteen-pixel body text, note list as unstyled list with title links. Spend at most two hours on CSS—use a minimal classless stylesheet if temptation strikes. Dark mode waits; contrast ratio 4.5:1 does not.
Touch targets on list items at least forty-four pixels tall. You will open the app on phone even if editing stays desktop-first; readable list prevents duplicate notes because you could not find the first.
Print stylesheet optional joke—unless you actually print meeting notes. Skip PDF export; browser print-to-PDF is free and good enough for v1.
Traps when notes apps become Notion clones
Trap: nested folders on day three. Flat list with good titles beats taxonomies you abandon.
Trap: rich embeds. Images and PDFs explode storage and CSP rules. Link to files elsewhere until v2.
Trap: split-pane IDE layout. Simple pages reduce CSS time. Ugly useful wins pretty imaginary.
Trap: JWT auth for solo use. HTTP basic behind VPN or single-user cookie session is enough. Auth frameworks eat weeks.
Trap: skipping deploy until day fourteen. Deploy on day five with hello-world notes; infrastructure surprises early.
Trap: markdown flavor soup. Pick CommonMark or GFM and disable exotic extensions. Footnotes and task lists tempt; each extension is a rendering bug waiting on edge-case notes you paste from GitHub.
Day-by-day split for fourteen days
Days 1–2: project skeleton, list/create/view.
Days 3–4: edit/update, timestamps, basic CSS.
Days 5–6: markdown sanitization tests, error pages.
Day 7: deploy staging; fix path and env issues.
Days 8–9: polish list UI, delete note with confirm.
Day 10: backup script and README.
Days 11–12: dogfood only—no new features; fix annoyances.
Days 13–14: acceptance checklist, tag v1.0, write short retrospective in one note inside the app.
Retrospective note is meta proof the tool works. If you will not eat your own cooking, the scope was still too large.
Track hours spent versus estimate in the retrospective. Two-week projects teach forecasting; lying that it took two weeks when it took six teaches nothing. Honest numbers improve the next scope box.
Deploy on day five, not day fourteen
Ship list and create this week even if edit is rough. A live URL focuses you on broken paths and missing env vars while motivation is high. Polish locally forever is how notes apps become shelfware.
When tempted to add tags, write a note titled v2 ideas inside the app and return to the checklist. Finishing teaches more than pivoting to a framework rewrite on day eight.
Two weeks is arbitrary but useful. Calendars convert vague learning into shipped software—respect the box.
Archive the repo read-only after v1.0 even if you keep using it. Frozen v1 clarifies when v2 scope creep begins.