All Projects
Confidential context: Personal productivityWeb systemIn progress

Smart Pomodoro

Calendar blocks became recoverable app-local focus sessions with planning, presets, runtime state, and history.

Smart Pomodoro cover screenshot

How the project is put together

Architecture map

6 layers / 5 directed links

100%

plans withqueriespersistsauthorized bydeploys via
  1. 01
    Interface

    Today cockpit, timer, presets, history, settings, and active focus experience.

    Next.js / React 19 / Tailwind CSS / Three.js
  2. 02
    Application

    Calendar-derived sessions, recovery, progress, recommendations, and UI state orchestration.

    TanStack Query / Timer runtime / Shared planning logic
  3. 03
    Services/API

    Auth, calendars, sessions, presets, settings, and smart planning endpoints.

    NestJS / Zod / Google APIs / Drizzle
  4. 04
    Data

    Users, settings, OAuth tokens, sessions, presets, progress, and completion history.

    PostgreSQL / Drizzle ORM / Migrations
  5. 05
    Auth/Permissions

    Read-only calendar access with server-side token encryption and HTTP-only session cookies.

    Google OAuth / Signed cookies / Encrypted tokens
  6. 06
    Runtime

    Workspace dev flow with local Docker Postgres and intended DigitalOcean/Dokploy deployment.

    pnpm / Turborepo / Docker Postgres / Dokploy target

From broken workflow to operating system

Study plans lived in the calendar while actual timer sessions lived somewhere else.

A Next/Nest product reads focus calendar blocks, generates local intervals, and runs a resilient focus timer.

The workflow constraint

Focus planning usually lives apart from the calendar, so planned study blocks and actual timer sessions drift apart. The product needed to respect calendar intent while keeping timer state local and recoverable.

What changed

Google OAuth and focus-calendar selection
Today planning cockpit with calendar-derived sessions
Recoverable active focus timer
Presets, history, settings, and recommendations

Decisions and trade-offs

Read-only Calendar integration

The app needed calendar context without taking over the user's calendar or filling it with generated focus/break entries.

Decision: Read selected focus calendar events and generate intervals inside the app instead of writing generated sessions back to Google Calendar.

Trade-off: Calendar remains cleaner and safer, but focus-session completion data must live in the app database.

Timestamp-based timer over interval counting

Browser timers can drift when tabs are backgrounded or the device sleeps.

Decision: Calculate active session progress from timestamps and persisted session state rather than trusting every interval tick.

Trade-off: Slightly more runtime state management, but recovery and completion behavior are much more reliable.

NestJS API over server-only Next routes

The app has auth, calendar, sessions, presets, settings, and planning domains that benefit from backend module boundaries.

Decision: Use NestJS with Drizzle/PostgreSQL as a separate API layer behind the Next frontend.

Trade-off: More services to run locally, but cleaner domain boundaries and deployment flexibility.

Constraints, architecture, and proof

Next.js App Router renders Today, Timer, Presets, History, and Settings. TanStack Query talks to a NestJS API for auth, calendars, presets, sessions, settings, and smart planning. Drizzle persists state in PostgreSQL, while Google OAuth tokens are encrypted and sessions use signed HTTP-only cookies.

Generated focus and break intervals must remain app-local
Google Calendar access should stay read-only
Timer runtime must survive background tab throttling and page refreshes
OAuth tokens need encrypted server-side storage
Planning logic should be shared and testable outside the UI

Deployment, security, and maintenance

Signed HTTP-only cookies, encrypted OAuth tokens, read-only calendar scope, persisted session progress/completion state, and shared pure planning logic reduce calendar, auth, and timer failure risk.

Honest edges and next improvements

Generated focus and break intervals stay app-local and are not written back to Google Calendar.
Deployment Dockerfiles and production docs are still open work.

What I would improve next

Complete deployment Dockerfiles and Dokploy notes
Add richer mobile layout polish
Expand analytics around planning accuracy and completion

Screenshots from the build