DEV Community

Cover image for I built a minimal task manager with Next.js and Turso — here's what I learned
hcacode
hcacode

Posted on

I built a minimal task manager with Next.js and Turso — here's what I learned

The problem

I tried Todoist, Notion, TickTick — all great tools. But I kept spending more time tweaking my system than actually getting things done.

I wanted something dead simple: show me today's tasks, let me check them off, move on.

So I built Daybrick.

The concept

Daybrick is a daily task manager built around one idea: one day at a time.

  • Duties — areas of responsibility (Work, Health, Learning) that group your tasks
  • Tasks — scheduled for a specific day, so you only see what matters today
  • Habits — recurring tasks with streak tracking
  • Paths — multi-day goals with progress visualization

No kanban boards, no AI, no complexity. Just your day, broken into bricks.

The stack

  • Next.js 16 (App Router)
  • React 19
  • Turso (SQLite at the edge)
  • Drizzle ORM
  • Vercel for hosting and cron jobs
  • Resend for transactional emails
  • Web Push API for notifications
  • PostHog for privacy-friendly analytics

Some technical decisions worth sharing

Why Turso over Postgres?

SQLite is fast, simple, and Turso gives you edge replication for free. For a single-user-per-request app like a task manager, it's a perfect fit. Drizzle ORM makes the DX feel no different from Postgres.

PWA over native

I wanted Daybrick on both desktop and mobile without maintaining two codebases. A PWA with a service worker handles push notifications, offline capability, and "Add to Home Screen" — close enough to native for a productivity tool.

Push notifications that actually work

This was the trickiest part. A few gotchas I hit:

  1. Chrome deduplicates notifications by tag — if you send the same tag twice, the second one silently replaces the first. I append Date.now() to make each tag unique.
  2. event.data.json() can crash your service worker — a malformed payload kills the push handler for all future notifications. Always wrap it in try/catch.
  3. Multi-device support — storing a single "notifications enabled" flag per user doesn't work. If you toggle off on your phone, your laptop stops getting notifications too. I store subscriptions per device and check active subscriptions directly.

Localization without URL params

Daybrick supports English and Turkish. Instead of /en/dashboard or /tr/dashboard, the locale is stored in a cookie and the user's DB profile. Cleaner URLs, simpler routing, same result.

Emails that match the user's language

All transactional emails (OTP, welcome, password reset, "we miss you") pull from a centralized i18n module, so a Turkish user gets Turkish emails automatically.

What I'd do differently

  • Start with semantic release from day one. I added it later and had to retrofit conventional commits. Setting it up early is 10 minutes of work that saves hours.
  • Don't trust toISOString() for dates. It converts to UTC, which shifts your dates. Use local date methods (getFullYear(), getMonth(), getDate()) when working with calendar dates.
  • Design your notification system for multiple devices from the start. Retrofitting multi-device support after building around a user-level flag was painful.

The result

I've been using Daybrick daily for my own work. It's minimal, it's fast, and it stays out of my way — which is exactly what I wanted.

If you want to try it: 👉 daybrick.io

It's free. I'd love feedback from the dev community — especially on the UX and mobile experience.

Top comments (0)