A full-stack note-taking app for creative entrepreneurs. Built with vanilla HTML/CSS/JS frontend + Python FastAPI backend.
Open index.html with VS Code Live Server (by Ritwick Dey).
All notes save automatically to your browser's localStorage.
⚠️ Use Live Server, not Five Server. Five Server injects ashare-modal.jsscript into your page that crashes the JavaScript runtime, breaking all functionality.
cd backend
pip install -r requirements.txt
uvicorn main:app --reload --port 8000Then open index.html via Live Server — it will automatically sync with the backend.
- Create, edit, delete notes
- Pin important notes to top
- Archive old notes
- 6 creative entrepreneur categories: Ideas, Projects, Clients, Inspiration, Finances, Marketing
- Tag system with sidebar tag filtering
- Full-text search (title, content, tags)
- Color-coded notes (8 colors)
- Dark / Light mode
- Auto-save every 3 seconds
- Word count
- Python panel with live API examples and SDK code
- Keyboard shortcuts: Ctrl+S (save), Ctrl+N (new note)
- Fully responsive (mobile, tablet, desktop)
- Works offline (localStorage fallback)
| Method | Path | Description |
|---|---|---|
| GET | /notes | List notes (supports ?search=, ?tag=, ?category=, ?archived=) |
| POST | /notes | Create note |
| GET | /notes/{id} | Get single note |
| PATCH | /notes/{id} | Update note |
| DELETE | /notes/{id} | Delete note |
| PATCH | /notes/{id}/archive | Toggle archive |
| GET | /tags | All unique tags |
| GET | /categories | All categories |
API docs: http://127.0.0.1:8000/docs
creativeflow-notes/
├── index.html ← Single-file frontend (HTML + CSS + JS)
├── backend/
│ ├── main.py ← FastAPI routes
│ ├── models.py ← SQLAlchemy models
│ ├── database.py ← DB connection
│ ├── schemas.py ← Pydantic schemas
│ └── requirements.txt
└── README.md
Cause: A browser extension (e.g. image editors, screenshot tools) is injecting a script into your page that crashes the JavaScript runtime before init() runs.
Fix:
- Open DevTools (F12) → Console tab
- If you see an error referencing an unfamiliar
.jsfile on load, a browser extension is the culprit - Go to
chrome://extensions, disable all extensions, and hard refresh (Ctrl+Shift+R) - Re-enable extensions one at a time to identify which one is causing the conflict
Cause: localhost and 127.0.0.1 can be treated as different origins by the browser, causing fetch requests to fail silently.
Fix: The frontend uses http://127.0.0.1:8000 — ensure your backend is also bound to 127.0.0.1 (this is uvicorn's default). Do not change the API constant to localhost.
Cause (original bug — now fixed): loadNotes() was async and awaited the backend before rendering. If the backend was slow or unavailable, the note list never populated.
Fix applied: Notes now load from localStorage immediately on init, then sync with the backend in the background. The UI is always instant regardless of backend status.
Cause: Some browsers intercept Ctrl+S before the page's keydown listener fires.
Fix applied: The keydown handler now calls e.stopPropagation() in addition to e.preventDefault() to block browser interception.
Before running the project, verify:
- Using Live Server (not Five Server) to serve
index.html - No browser extensions active that inject scripts into local pages (Grammarly, image editors, screenshot tools are common offenders)
- Running
uvicornfrom inside thebackend/folder, not the project root — local imports (models,database) will fail otherwise - Dependencies installed:
pip install -r requirements.txt - Browser window is wider than 640px — the note list panel is hidden below this breakpoint by design
Check if JavaScript is running:
// Paste in browser console
init()Check if localStorage is working:
localStorage.getItem('cf_notes')Check if the backend is reachable:
fetch('http://127.0.0.1:8000/notes').then(r => r.json()).then(console.log)Check if a note is selected:
console.log(currentNote)- The frontend falls back to localStorage automatically when the backend is unreachable — no errors are thrown
- Auto-save triggers 3 seconds after the last keystroke; a manual
Ctrl+Sor the Save button saves immediately - New notes are assigned a
local-TIMESTAMPID until saved to the backend, at which point they receive a numeric ID from the database