1
2
Fork
You've already forked organizer
0
Organizer: Timelines for everything you want to remember. A local-first app for notes, events, and follow-ups — kept in chronological order, stored on your own device. https://www.useorganizer.com
  • TypeScript 74.8%
  • CSS 16.6%
  • JavaScript 8.3%
  • HTML 0.2%
2026年06月27日 22:46:38 +10:00
docs change file structure 2026年06月27日 22:46:38 +10:00
public Initial commit 2026年06月08日 12:04:52 +10:00
scripts Add product demo video and embed it in the homepage hero 2026年06月09日 23:07:59 +10:00
src change file structure 2026年06月27日 22:46:38 +10:00
.gitignore Add product demo video and embed it in the homepage hero 2026年06月09日 23:07:59 +10:00
.vercelignore Add .vercelignore to keep local tooling out of deploys 2026年06月10日 07:33:58 +10:00
CHANGES_REVIEW.md Initial commit 2026年06月08日 12:04:52 +10:00
deploy.sh changed deploy mode 2026年06月27日 22:00:06 +10:00
eslint.config.js Initial commit 2026年06月08日 12:04:52 +10:00
index.html Initial commit 2026年06月08日 12:04:52 +10:00
LICENSE source details 2026年06月08日 18:03:40 +10:00
package-lock.json syncthing merge support and automerge 2026年06月22日 21:30:16 +10:00
package.json make npm run dev kill ports first 2026年06月14日 10:45:51 +10:00
README.md Initial commit 2026年06月08日 12:04:52 +10:00
tsconfig.app.json Initial commit 2026年06月08日 12:04:52 +10:00
tsconfig.json Initial commit 2026年06月08日 12:04:52 +10:00
tsconfig.node.json Initial commit 2026年06月08日 12:04:52 +10:00
UI_STANDARDS.md Initial commit 2026年06月08日 12:04:52 +10:00
vercel.json Enable Vercel cleanUrls so docs serve static HTML 2026年06月08日 18:49:01 +10:00
vite.config.ts Initial commit 2026年06月08日 12:04:52 +10:00

Organizer

A local-first app for keeping chronological logs of anything — client follow-ups, project progress, journals, research notes. Instead of files and folders, you work with timelines: named logs you add timestamped rich-text entries to over time. There's no account and no server; data lives in the browser (IndexedDB) or in a folder you pick on your own machine.

Just want to use the app? This README is for people working on the code. For how to use Organizer, read the user guide: https://www.useorganizer.com/guide/introduction .


Tech stack

Area Choice
UI React 19 + TypeScript
Build / dev Vite
Routing React Router
Rich text TipTap (StarterKit + tables, tasks, links, code, highlight...)
Local storage IndexedDB via idb, plus File System Access API
Icons lucide-react
Tests Vitest + Testing Library + fake-indexeddb
Docs site VitePress
Hosting Vercel

Prerequisites

  • Node.js 20+ (the toolchain targets current Node; @types/node is on v24).
  • npm (the repo ships a package-lock.json).

Getting started

npm install
npm run dev

npm run dev starts two processes concurrently:

  • the app (Vite) — the React application
  • the docs (VitePress) — the user guide under docs/

Vite will print the local URLs for each. If you only want the app, run npm run app:dev; for docs only, npm run docs:dev.

Available scripts

Script What it does
npm run dev Run app + docs dev servers together
npm run app:dev App dev server only (Vite)
npm run docs:dev Docs dev server only (VitePress)
npm test Run the test suite once (Vitest)
npm run test:watch Run tests in watch mode
npm run lint Lint with ESLint
npm run build Full production build: tests → tsc -b → build docs → build app
npm run preview Preview the built app locally

Note: npm run build runs the test suite first and fails the build if tests fail. Keep tests green.

Project structure

src/
 components/ One folder per UI component (Component.tsx + Component.module.css)
 EntryComposer/ The TipTap-based rich-text editor for new/edited entries
 TimelineView/ A single timeline and its entries
 TimelineList/ Sidebar list of timelines (with tags/filtering)
 TodoPage/ Entries that have due dates, surfaced as todos
 Settings/, Modal/, SearchBox/, TagFilter/, ... supporting UI
 context/
 StorageContext.tsx App-wide storage provider; wires the active adapter to the UI
 storage/ The storage abstraction (see below)
 interface.ts StorageAdapter interface + ConflictError
 idbAdapter.ts IndexedDB-backed adapter (default, "browser" storage)
 fileAdapter.ts File System Access API adapter ("folder on disk" storage)
 handleStore.ts Persists the chosen directory handle
 merge.ts Cross-tab / cross-source merge logic (has unit + integration tests)
 db/ Low-level IndexedDB schema and stores (timelines, entries, blobs)
 hooks/ Reusable React hooks
 utils/ Pure helpers
 types.ts Core domain types: Timeline, Entry, etc.
docs/ VitePress user guide (published at useorganizer.com)
public/ Static assets (logo, icons, favicon)

Architecture notes

  • Local-first, no backend. All data stays on the user's device. There is no API layer to call.

  • Two storage backends behind one interface. Everything in the app talks to a StorageAdapter (src/storage/interface.ts). Two implementations exist:

    • idbAdapter — stores timelines, entries, and binary attachments ("blobs") in IndexedDB. This is the default.
    • fileAdapter — stores the same data in a user-selected folder via the File System Access API, so the user owns the files directly.

    When adding storage operations, add them to the interface and both adapters so the two backends stay in lockstep.

  • StorageContext is the seam. UI components don't import adapters directly; they consume the active adapter through StorageContext. Prefer going through it rather than reaching into src/db or a specific adapter.

  • Conflict / merge handling. Because data can change in another tab or on disk underneath us, adapters expose hasConflict() / mergeFromDisk() and the merge logic lives in src/storage/merge.ts. It has both unit tests (merge.test.ts) and an IndexedDB integration test (idbMerge.integration.test.ts) — if you touch merge behaviour, update them.

Styling & UI standards

Component styles use CSS Modules (Component.module.css next to each component). Before adding or changing UI, read UI_STANDARDS.md — it covers the design-token approach, accessibility requirements (visible focus states, contrast minimums, no hover-only actions), icon usage, and reduced motion. New code should follow these; older code is migrated toward them opportunistically.

Testing

  • Tests run on Vitest with Testing Library and a jsdom environment.
  • IndexedDB is faked with fake-indexeddb so storage code is testable without a browser.
  • Run npm test (one-off) or npm run test:watch while developing.
  • The storage/merge layer is the most safety-critical area — keep its coverage intact when changing it.

Documentation

The user-facing guide lives in docs/ (VitePress) and is published at https://www.useorganizer.com/guide/introduction. If your change alters user-visible behaviour, update the relevant guide page in docs/guide/. Run npm run docs:dev to preview docs locally.

Deployment

The app is hosted on Vercel (vercel.json). npm run build produces the production output in dist/, which includes both the app and the built docs.

Contributing checklist

Before opening a PR:

  1. npm run lint passes.
  2. npm test passes (and you've added/updated tests for behaviour you changed — especially in src/storage).
  3. New/changed UI follows UI_STANDARDS.md.
  4. Storage changes are reflected in both adapters and the interface.
  5. User-facing changes are reflected in the docs/ guide.
  6. npm run build succeeds end-to-end.