Your thoughts, organized.
A personal notes app built as a frontend-only product: React + Vite, no backend,
no accounts, no network calls. Everything you write lives in your browser's
localStorage.
npm install
npm run dev # http://localhost:5173npm run build # production bundle into dist/
npm run preview # serve the built bundle
npm run lint # oxlint- Write — create, edit and delete notes in a focused editor with idle
autosave, explicit save (
⌘/Ctrl + S) and a last-saved indicator. - Organise — pin, archive, tag (up to six per note), move to trash and restore. Permanent deletion always asks first.
- Find — search titles, body text and tags; filter by All, Pinned, Recent, Archive or Trash; sort by recently updated, oldest or title A–Z.
- Theme — a hand-built light and dark palette, remembered between visits and applied before first paint so there is no flash.
- Keyboard —
/focuses search,Nstarts a note,Escleaves the editor or closes a dialog, arrow keys move through menus.
src/
components/ Sidebar, Topbar, SearchBar, NoteCard, NoteGrid, Tag,
Menu, Modal, SettingsDialog, EmptyState, ThemeToggle, Toast, Logo
pages/ Dashboard, Editor
hooks/ useNotes (all note state), useTheme, useLocalState
utils/ notes (filter/search/sort), date (relative labels), storage
data/ mockNotes — the seed notes for a first run
styles/ tokens.css (design system), base.css (elements), app.css (layout)
useNotes owns every mutation; components receive notes and callbacks, which
keeps them presentational. Filtering, searching and sorting are pure functions in
utils/notes.js.
All colour, type, spacing, radius, shadow and motion values are CSS custom
properties in src/styles/tokens.css. The dark theme redefines only the
semantic tokens under [data-theme="dark"] — it is a separate palette, not an
inversion.
| Width | Layout |
|---|---|
| ≥ 1025px | Persistent sidebar, auto-filling multi-column grid |
| 768–1024px | Narrower persistent sidebar, two-column grid |
| ≤ 767px | Slide-over drawer, single column, full-width search, 38–40px touch targets |
The breakpoint lives in CSS only; React just toggles an .app--drawer-open
class, so the two can never disagree.
No authentication, no backend, no database and no external APIs — including web fonts, so the app works offline. Notes are per-browser and are not synced or shared; clearing site data clears them. Note content is plain text rather than rich text or Markdown, and there is no file import or export.