Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

13 Commits
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Atomic β€” Daily Habit Tracker & Behavioral Insights

A mobile-first productivity app that helps you track daily habits, manage tasks and goals, and delivers AI-powered insights into your behaviour patterns on a weekly and monthly basis.


Table of Contents


Overview

Atomic is a cross-platform mobile application built with React Native (Expo) that empowers users to take control of their productivity. Users can create and manage tasks, organise them by category and priority, link them to long-term goals, and mark them complete as part of their daily routine.

What sets Atomic apart is its intelligent feedback engine. Using OpenAI's API, the app analyses your task completion data over rolling weekly and monthly windows and surfaces personalised, natural-language insights about your behaviour β€” helping you identify patterns, celebrate consistency, and course-correct when habits slip.


Features

Core Functionality

  • Task Management β€” Create, edit, delete, and complete tasks with title, description, category, priority, and estimated time
  • Goal Tracking β€” Define long-term goals and link individual tasks to them to track incremental progress
  • Category System β€” Organise tasks by categories (Work, Health, Personal, Grocery, and custom)
  • Priority Levels β€” Assign Low, Medium, or High priority to surface what matters most
  • Daily Dashboard β€” At-a-glance view of today's pending and completed tasks

Insights & Analytics

  • Weekly Behaviour Reports β€” AI-generated summaries of your completion rate, streaks, and patterns over the past 7 days
  • Monthly Deep Dives β€” Broader trend analysis across 30 days, highlighting your most and least productive periods
  • Natural Language Feedback β€” Insights written in a conversational tone via OpenAI, not just raw charts

Security & Auth

  • Email & Password Auth β€” Secure signup and login with hashed passwords (bcrypt)
  • Google OAuth β€” One-tap sign-in with Google via OAuth 2.0
  • JWT Auth with Refresh Rotation β€” Short-lived access tokens with secure refresh token rotation and session management
  • Forgot / Reset Password β€” OTP-based password reset delivered via email (Resend)
  • Rate Limiting β€” Per-route rate limiting on all sensitive endpoints

Infrastructure

  • Push Notifications β€” Expo push notifications for reminders and daily nudges (iOS & Android)
  • Session Management β€” Device-scoped sessions stored in Redis for fast lookup and invalidation
  • Background Jobs β€” Scheduled tasks using node-cron (e.g. sending weekly insight digests)
  • Containerised Deployment β€” Fully Dockerised backend deployed on Render

Tech Stack

Frontend

Technology Purpose
React Native Cross-platform mobile UI framework
Expo (SDK 54) Managed workflow, routing, fonts, splash screen
Expo Router File-based navigation for React Native
NativeWind v4 Tailwind CSS utility classes in React Native
Zustand Lightweight global state management
Expo Secure Store Secure storage for refresh tokens on-device
React Native Reanimated Smooth declarative animations
React Native Safe Area Context Safe area inset handling
Expo Google Fonts Plus Jakarta Sans typeface
React Native Toast Message Non-intrusive in-app notifications

Backend

Technology Purpose
Node.js + Express.js REST API server
Prisma ORM Type-safe database access and schema migrations
PostgreSQL Primary relational database
ioredis Redis client for session storage and caching
OpenAI API GPT-powered behavioural insight generation
Google Auth Library Server-side Google OAuth token verification
Resend Transactional email delivery (OTP, digests)
node-cron Scheduled background jobs
express-rate-limit Rate limiting middleware
bcrypt Password hashing
jsonwebtoken JWT generation and verification
express-validator Request body validation

Infrastructure & DevOps

Technology Purpose
Docker Containerisation of the backend service
Render Cloud deployment platform
Redis In-memory store for sessions and rate limit state
PostgreSQL Hosted production database

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Mobile Client                        β”‚
β”‚              React Native + Expo Router                 β”‚
β”‚                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”‚
β”‚  β”‚  Zustand β”‚  β”‚ Secure   β”‚  β”‚ Expo     β”‚              β”‚
β”‚  β”‚  Store   β”‚  β”‚ Store    β”‚  β”‚ Notifs   β”‚              β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      β”‚ HTTPS / REST API
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  Express.js API                         β”‚
β”‚                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚  β”‚  Auth Routes  β”‚  Task Routes  β”‚  Goal Routes β”‚       β”‚
β”‚  β”‚  Rate Limiter β”‚  Validators   β”‚  Middleware  β”‚       β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
β”‚                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚  β”‚  Prisma ORM β”‚  β”‚ ioredis  β”‚  β”‚ OpenAI API   β”‚        β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚         β”‚              β”‚                                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚  β”‚ PostgreSQL  β”‚  β”‚  Redis   β”‚  β”‚  node-cron   β”‚        β”‚
β”‚  β”‚  (Prisma)  β”‚  β”‚ Sessions β”‚  β”‚  Scheduler   β”‚        β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚  β”‚  Google OAuth  β”‚  Resend Emails  β”‚  bcrypt   β”‚       β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚     Docker     β”‚
              β”‚   Container    β”‚
              β”‚  (Render.com)  β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Getting Started

Prerequisites

Make sure you have the following installed:


Environment Variables

Backend .env

# Server
PORT=3000
NODE_ENV=development

# Database
DATABASE_URL=postgresql://user:password@localhost:5432/atomic_db

# Redis
REDIS_URL=redis://localhost:6379

# JWT
ACCESS_TOKEN_SECRET=your_access_token_secret
REFRESH_TOKEN_SECRET=your_refresh_token_secret
ACCESS_TOKEN_EXPIRY=15m
REFRESH_TOKEN_EXPIRY=7d

# Google OAuth
GOOGLE_CLIENT_ID=your_google_client_id

# OpenAI
OPENAI_API_KEY=your_openai_api_key

# Resend (Email)
RESEND_API_KEY=your_resend_api_key
FROM_EMAIL=noreply@yourdomain.com

Frontend .env

EXPO_PUBLIC_API_BASE_URL=http://localhost:3000

Running Locally

1. Clone the repository

git clone https://github.com/your-username/atomic.git
cd atomic

2. Start the backend with Docker

cd backend
docker compose up --build

This will spin up:

  • The Express.js API server
  • A PostgreSQL instance
  • A Redis instance

3. Run Prisma migrations

cd backend
npx prisma migrate dev
npx prisma generate

4. Install and start the frontend

cd frontend
npm install
npx expo start

Scan the QR code with Expo Go, or press i for iOS simulator / a for Android emulator.


API Overview

All endpoints are prefixed with /api/auth or /api as appropriate. Protected routes require a valid Bearer access token in the Authorization header.

Auth Routes β€” /api/auth

Method Endpoint Auth Required Description
POST /signup No Register a new user
POST /login No Log in with email & password
POST /auth/google No Log in or register via Google OAuth
POST /logout Yes Invalidate session and clear tokens
GET /me Yes Get the authenticated user's profile
POST /forgot-password No Send OTP reset code to email
POST /reset-password No Reset password using OTP
POST /refresh No (uses refresh token) Rotate and issue new token pair
POST /register-push-token Yes Save device push notification token

Task Routes β€” /api/tasks

Method Endpoint Auth Required Description
GET / Yes Fetch all tasks for the user
POST / Yes Create a new task
PATCH /:id Yes Update an existing task
DELETE /:id Yes Delete a task
PATCH /:id/complete Yes Mark a task as completed

Goal Routes β€” /api/goals

Method Endpoint Auth Required Description
GET / Yes Fetch all goals for the user
POST / Yes Create a new goal
PATCH /:id Yes Update a goal
DELETE /:id Yes Delete a goal

Insights Routes β€” /api/insights

Method Endpoint Auth Required Description
GET /weekly Yes Get AI-generated weekly insight
GET /monthly Yes Get AI-generated monthly insight

Authentication Flow

Atomic uses a dual-token authentication strategy with device-scoped session management backed by Redis.

1. User logs in β†’ server issues:
   - Short-lived Access Token (15 min) β†’ stored in Zustand (memory)
   - Long-lived Refresh Token (7 days) β†’ stored in Expo SecureStore

2. Each API request attaches the Access Token as a Bearer header.

3. On 401 (token expired):
   - Client sends the Refresh Token to /api/auth/refresh
   - Server validates the token against the Redis session
   - If valid, issues a new Access + Refresh token pair (rotation)
   - Old session is invalidated immediately (prevents reuse attacks)

4. On logout:
   - Redis session is deleted
   - SecureStore is cleared
   - Zustand state is reset

5. On app restart:
   - hydrateAuth() reads Refresh Token from SecureStore
   - Calls /refresh to restore the session silently

AI Insights

The insights engine is powered by OpenAI's GPT models. Here is how it works:

  1. A node-cron job runs on a configurable schedule (e.g. every Sunday evening and on the first of each month)
  2. The job queries the database for each user's task completion data over the relevant window (7 or 30 days)
  3. Aggregated stats (completion rate, categories worked on, streaks, busiest days) are structured into a prompt
  4. The prompt is sent to the OpenAI Chat Completions API
  5. The resulting natural-language insight is saved to the database and surfaced in the app
  6. Users can also trigger an on-demand insight refresh from within the app

Example insight output:

"This week you completed 14 out of 18 tasks β€” a strong 78% rate. Your most productive day was Wednesday, where you knocked out 5 tasks. Health tasks saw the most consistency, but your Work category had 3 overdue items by Friday. Try front-loading work tasks earlier in the week to keep that streak going."


Push Notifications

Atomic uses Expo's push notification service to send timely reminders and weekly insight digests.

  • On login, the device's Expo push token is registered with the backend
  • Tokens are stored per-user and per-platform (iOS / Android) in the push_tokens table
  • node-cron jobs trigger batch notification sends at scheduled times
  • Notifications deep-link back into the relevant screen in the app

Screenshots

Tasks screenshot Report screenshot Goals screenshot Dashboard screenshot

Roadmap

  • Habit streaks and visualised streak calendar
  • Weekly insight email digest via Resend
  • Onboarding flow with personalisation questions
  • Social accountability features (share goals with a friend)
  • Widget support for iOS and Android home screen
  • Offline mode with background sync
  • Dark mode support

Contributing

Contributions, issues, and feature requests are welcome! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/your-feature-name
  3. Commit your changes: git commit -m 'feat: add some feature'
  4. Push to the branch: git push origin feature/your-feature-name
  5. Open a Pull Request

Please make sure your code follows the existing patterns and that any new API routes are covered by validation middleware.


License

This project is licensed under the MIT License.


Built with β˜• and a lot of habit-tracking

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages