TaskNest is a personal productivity app built on Next.js 14 App Router with MongoDB/Mongoose and NextAuth credentials auth.
It started as a nested task tracker, but the current app is broader:
- workspaces with infinitely nested tasks
- task deadlines and inline attachments
- dashboard/overview filters across all tasks
- process mindmaps
- habit tracking
- loan tracking
- pomodoro timer and reporting
- basic profile editing
- Next.js
14.2.5 - React
18.3.1 - TypeScript
- Tailwind CSS
- NextAuth
4.24.7with JWT session strategy - Mongoose
8.5.1 bcryptjsfor password hashing
Main scripts from package.json:
npm run devnpm run buildnpm run startnpm run lint
From .env.example:
MONGODB_URINEXTAUTH_SECRETNEXTAUTH_URL
Note: .env.example currently contains what looks like a concrete MongoDB connection string rather than a placeholder. Treat that as sensitive and consider rotating/removing it if it is real.
/redirects to/dashboardwhen authenticated, otherwise/login/dashboardrenders the cross-workspace task overview/workspacesrenders the actual nested task/workspace UI/processesrenders process mindmaps/habitsrenders the habit tracker/loansrenders loan tracking/pomodororenders pomodoro reports/profilerenders profile editing
src/app/providers.tsx wraps the app with:
SessionProviderfrom NextAuthPomodoroProviderPomodoroFloating, which means the timer widget is available on most authenticated pages
src/lib/auth.ts uses:
- NextAuth credentials provider
- email/password login
bcrypt.compare(...)- JWT sessions
The session callback adds session.user.id, and server routes usually authorize by calling src/lib/session.ts.
src/lib/db.ts uses a cached global Mongoose connection to survive Next.js dev reloads.
Most API routes follow the same pattern:
- call
requireUserId() dbConnect()- query/update only documents belonging to that
userId
Primary files:
src/components/Dashboard.tsxsrc/components/WorkspaceTabBar.tsxsrc/components/TaskTree.tsxsrc/components/TaskItem.tsxsrc/app/api/tasks/route.tssrc/app/api/tasks/[id]/route.tssrc/app/api/tasks/[id]/toggle/route.tssrc/lib/models/Task.ts
Behavior:
- workspaces are bottom tabs with create, rename, delete, and drag-reorder
- tasks are stored flat in MongoDB with
workspaceId,parentId, andorder - the client rebuilds the nested tree in
TaskTree.buildTree(...) - within each sibling group, tasks are sorted by earliest deadline, then
order - users can add top-level tasks and child tasks
- task text is inline editable
- deadlines are editable per task
- deleting a task recursively deletes all descendants
Completion logic:
- toggling a task cascades the same completion state down to descendants
- ancestor completion is reconciled upward so a parent is only complete when all children are complete
- creating a child under a completed parent uncompletes ancestors
Important implementation note:
src/lib/models/Task.ts explicitly deletes the cached Mongoose model before recompiling. This was added because Next.js HMR was causing newly-added schema fields like attachments to be silently stripped on writes.
Primary files:
Supported attachment types:
linkpdfnote
Current storage model:
- attachments are embedded directly on the task document
- PDFs are stored inline as base64 data URLs
- notes are stored inline as text
Important constraints:
- max
10attachments per task - max PDF size is
2 MB - note content is clamped to
20000chars - invalid attachments are dropped during sanitization instead of crashing the request
UX details:
- links open in a new tab
- notes open in an in-app modal
- PDFs are converted from data URL to blob URL before viewing because direct
data:opening is unreliable in modern browsers - PDF blob URLs are revoked to avoid leaking memory
Primary file:
This is the current /dashboard page.
It loads all workspaces and all tasks, then offers:
- status filtering: all, pending, completed
- date filtering: all, overdue, today, next 7 days, none
- manual from/to deadline filtering
- workspace filtering
- nesting-level filtering
- summary cards for total/completed/upcoming/overdue
Important detail:
The README still frames the app mainly as a nested to-do app, but the current route split is:
/dashboard= overview across all tasks/workspaces= actual nested task management
Primary files:
src/components/Processes.tsxsrc/components/Mindmap.tsxsrc/app/api/processes/route.tssrc/lib/models/Process.ts
Behavior:
- each process has a recursive embedded
rootnode - tree edits are debounced before saving
- processes can be exported as JSON
- imports support either:
- a nested
roottree - a linear
stepsshortcut that is normalized into a tree
- a nested
- the import modal includes a copyable LLM prompt for generating valid JSON externally
Primary files:
Habit kinds:
checkcounttime
Behavior:
- API returns the habit list plus the last 90 days of logs
- cards show streaks and 7-day activity bars
- detail modal shows 12-week heatmap and recent logs
- time habits track whether the earliest log met a target time
Primary files:
Behavior:
- tracks
lentvsborrowed - filters by direction and repayment status
- supports optional notes, due date, and screenshot
- screenshots are pasted or uploaded as inline data URLs
- outstanding totals are split into "owed to me" vs "I owe"
Primary files:
src/components/PomodoroProvider.tsxsrc/components/PomodoroFloating.tsxsrc/components/PomodoroReport.tsxsrc/app/api/pomodoro/route.tssrc/app/api/pomodoro/items/route.ts
Behavior:
- active timer state lives in client context and is persisted in
localStorage - the floating widget is available across authenticated pages
- users can start a pomodoro against a task, habit, process, or ad-hoc "other" item
- completing a session plays a synthesized Web Audio bell/chime
- sessions shorter than 30 seconds are intentionally not persisted
- the report page shows totals and a 30-day leaderboard
Primary files:
src/components/ProfileForm.tsxsrc/app/api/profile/route.tssrc/app/api/auth/signup/route.tssrc/lib/models/User.ts
Behavior:
- signup is email/password only
- passwords must be at least 6 characters
- profile editing currently supports
nameandemail
src/types/index.ts is the main shared DTO file for:
- tasks and task tree nodes
- workspaces
- attachments
- processes
- habits and habit logs
- loans
- pomodoro sessions
This file is a good first stop before changing any client/server payload shape.
- global font is DM Sans via Google Fonts in
src/app/layout.tsx - styling is mostly Tailwind utility classes
- top navigation is centralized in
src/components/Header.tsx - the app uses a consistent teal/nav color language across modules
- Task attachments and loan screenshots are stored inline in MongoDB documents. This keeps the app simple, but document size can become a scaling concern.
- Task sorting is deadline-first in the client tree, even though
orderis still stored. If a future drag-sort is added for tasks, that interaction will need to reconcile with deadline sorting. - Several models delete compiled Mongoose models under HMR to avoid stale schemas. Be careful when changing model compilation patterns.
- Most pages fetch and then fully reload the relevant collection after a mutation instead of doing fine-grained local updates. This keeps state simpler but can feel heavier.
- The README has some stale wording and encoding artifacts; the codebase is a better source of truth right now.
- nested task behavior:
src/components/TaskTree.tsx,src/components/TaskItem.tsx,src/app/api/tasks/route.ts - attachments:
src/components/AttachmentEditor.tsx,src/lib/attachments.ts - dashboard filters:
src/components/Overview.tsx - pomodoro:
src/components/PomodoroProvider.tsx,src/components/PomodoroReport.tsx - auth/session:
src/lib/auth.ts,src/lib/session.ts