Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Focus Study

Focus Study local feature overview

Focus Study is a local-first workspace for learning any topic. Bring your own versioned Question & Answer collection in a strict Markdown format, study it in the browser, and keep attempts, notes, highlights, favourites, priorities, and progress on your device.

The app begins with an empty library and a Getting Started guide.

Run it with Docker

Docker is the supported developer workflow. From the repository root:

make up

Open http://localhost:5174. The Compose bind mount keeps Vite hot reload enabled while the named focus-study-node-modules volume keeps container dependencies out of the host checkout.

Stop the server with:

make down

Common checks run inside Docker:

make test       # Vitest unit and interaction tests
make typecheck  # TypeScript project references
make build      # Production Vite bundle
make check      # typecheck + test + build

make clean removes the Compose container, named dependency volume, and orphan containers. It does not remove learner data stored by your browser.

Bring your own collection

Use the included skills/focus-study-collection/ Codex skill to generate a collection that matches the public focus-study Markdown contract. The skill validates the result before returning it. You can also author the format directly.

Each collection has YAML frontmatter with format_version: 1.0, a stable collection ID, title, and description. Each question is an immutable-ID focus-study-question fenced YAML record with its topic, section, question number, question, Markdown answer, tags, priority, difficulty, and initial favourited value.

Import a .md file from the Library / Getting Started screen. Focus Study validates the whole file before changing the local library and presents errors without partially importing content. Re-importing a collection with the same stable IDs refreshes its content while retaining progress and learner preferences. Imported priority, difficulty, and favourite values are defaults for newly seen questions only.

The app does not read a local study-guides/ directory at runtime. A deployed browser app cannot read files on your computer; collections are added only through an explicit import or restore action.

Portable backups

Export any selected collection as a .focus-study.zip backup. It contains the original collection.md, collection-qualified learner state, and a versioned manifest. Restoring that archive resumes the collection with its attempts, active session, notes, highlights, filters, answer revisions, and preferences intact.

Optional Google Drive sync

Focus Study works completely offline by default. Set VITE_ONLINE_HOST=true and provide VITE_GOOGLE_CLIENT_ID only for a hosted deployment that offers optional Google Drive sync.

When enabled, the app asks the learner to connect Google Drive and requests the narrow drive.appdata permission. Each browser writes a separate hidden device snapshot in Drive's private appDataFolder; it does not create a visible .focus-study folder or require an application backend. On sync, the app reads the legacy snapshot and all device snapshots, unions collections by stable collection_id, chooses the newest content for duplicate collections, and merges learner state. A collection missing from one device is never treated as deleted. Access tokens stay in browser memory, so syncing works only while the site remains open and connected. The sync UI shows status, last sync time, and a manual Sync now action.

Do not commit a Google client ID configuration intended for a private deployment. Keep local Vite values in .env.local.

Product surface

  • Library / Getting Started — generation prompt and template, strict Markdown import preview, validation errors, collection management, backups, and optional Drive sync.
  • Study — responsive collection/topic/section/question navigation, search, tag/attempt/favourite/priority filters, masked answers, Markdown notes (including fenced code blocks), timer recovery, and completed-attempt feedback.
  • Analytics — collection/topic/date/tag/favourite/priority/attempt filters, reconciled KPI cards, section progress, a text-equivalent time trend, and a sortable question table.

Local-first storage

Learner state is persisted in browser IndexedDB, with localStorage as a last-resort fallback when necessary. The header exposes which path is active. All state is qualified by collection ID so different collections can reuse question IDs safely.

Only a completed Done action creates an immutable attempt. An active session stores its ISO start timestamp and note draft, so reload recovery calculates elapsed time from the original timestamp instead of resetting to zero.

Verification notes

The UI uses semantic HTML, accessible names, visible focus rings, a skip link, keyboard search suggestions, live status announcements, text labels alongside attempt colours, SVG icons, and a reduced-motion media query. Responsive layouts are defined for 375px, 768px, 1024px, and 1440px checkpoints; visually verify those widths after make up.

The automated suite covers parsing and validation, import/re-import, archive round-trips, study metrics, active-session recovery, and browser-only Drive sync behavior. Use make check before handing off changes.

Project layout

src/
  components/                 # accessible library, study, sidebar, analytics UI
  lib/                        # Markdown contract, storage, archive, and sync logic
skills/focus-study-collection/# Codex collection-generation skill and template
design-system/                # persisted UI/UX design decisions

About

Study tracker for Markdown Q&A collections, with timed practice, notes, progress analytics, portable backups

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages