Skip to content

Cengizbey-m/Bloom

Repository files navigation

🌸 Bloom — Kawaii Life Planner

A beautiful, modern life planner PWA built for real people. Think Notion × Daylio × Sunsama, wrapped in a soft kawaii aesthetic. Designed for Samsung Tab S9 FE, iPhone, and laptop.


✨ What Is Bloom?

Bloom is a full-featured personal planning app that combines everything you need to live intentionally. Think Notion × Sunsama × Daylio, wrapped in a soft kawaii aesthetic.

Core Features

Feature Description
⚡ Quick Capture Global Ctrl/Cmd+K shortcut — add a task, event, or note from any page in 2 seconds
✅ Tasks Priority levels, time estimates, kanban board, categories, today's time budget
📅 Calendar Month/week/day views, recurring events, .ics export, WhatsApp/email sharing
🌱 Habits Forgiveness-based score (0–100%), not punishing streak resets; 28-day heatmap
🎯 Goals Milestones, progress slider, deadline tracking — fully persisted across sessions
📖 Notes Markdown editor, sections, tags, GIF embeds, Markdown/JSON export, XSS-safe
🌙 Journal Mood + weather picker, 30-day mood calendar grid, mood-habit correlation insights
⏱ Focus Pomodoro timer with session tracking, sound picker, in-session task list
🏡 Dashboard Daily intention, today's schedule timeline, weekly stats, smart insight strips

What Makes Bloom Different

  • Forgiveness algorithm — Habits show a consistency percentage, not a binary streak. Missing one day drops you from 100% to 90%, not to zero. Research shows this prevents the "what-the-hell effect" that causes 52% of habit app abandonment.
  • Global Quick CaptureCtrl+K anywhere opens a modal to capture tasks, events, or notes instantly. No navigation required.
  • Mood-Habit Correlation — Like Daylio, Bloom analyzes which habits correlate with your better mood days and surfaces the insight automatically.
  • Daily Intention — Set a focus word or mantra for the day (Sunsama-inspired). Persisted per day, shown beautifully on the dashboard.
  • Today's Timeline — A vertical chronological view of today's calendar events (Structured/Cron-inspired), always visible on the dashboard.
  • Weekly Stats — A 7-day productivity snapshot: habit consistency bar chart, tasks completed, mood average, focus sessions.
  • Task time estimates — Add estimated minutes to any task. Dashboard shows "Today: 1h 20m planned / 45m done".

All data is persisted locally (works offline) and optionally synced to the cloud via Supabase. Installs as a PWA on any device.


🛠 Tech Stack

Layer Technology
Framework React 18
Language TypeScript (strict, zero errors)
Build Tool Vite
Styling Tailwind CSS v4 + CSS Variables (themes)
Animations Framer Motion
State Zustand v4 with persist middleware (localStorage, version 4)
Cloud Backend Supabase (Auth + PostgreSQL + Realtime)
Security DOMPurify (XSS sanitization on all HTML renders), Supabase RLS
PWA vite-plugin-pwa + Workbox (offline support, installable)
Icons Lucide React
Date Handling date-fns
Notifications react-hot-toast
Confetti canvas-confetti
GIFs GIPHY API
Markdown Custom renderer + DOMPurify allowlist sanitizer
Calendar Export Manual .ics string generation (no library needed)
Image Export html2canvas (month view snapshot)

🗂 Project Structure

bloom/
├── public/                    # Static assets + PWA icons
├── supabase/
│   └── schema.sql             # Full database schema + RLS policies
├── src/
│   ├── components/
│   │   ├── animations/        # Sakura petals, floating elements
│   │   ├── layout/            # Sidebar, MobileNav
│   │   ├── notes/             # GifPicker component
│   │   ├── widgets/
│   │   │   ├── MoodWidget.tsx
│   │   │   ├── WaterWidget.tsx
│   │   │   ├── TasksWidget.tsx
│   │   │   ├── HabitsWidget.tsx
│   │   │   ├── QuoteWidget.tsx
│   │   │   ├── CountdownWidget.tsx
│   │   │   ├── WeatherWidget.tsx
│   │   │   ├── TimelineWidget.tsx   # ← NEW: Today's schedule (Cron/Structured style)
│   │   │   ├── WeeklyStatsWidget.tsx # ← NEW: 7-day productivity overview (Sunsama style)
│   │   │   └── IntentionWidget.tsx  # ← NEW: Daily intention setter (Sunsama ritual)
│   │   ├── ErrorBoundary.tsx  # Global crash handler with retry
│   │   ├── QuickAdd.tsx       # ← NEW: Global Ctrl+K capture (Akiflow/Todoist style)
│   │   └── StatusBar.tsx      # Online/offline banner + sync dot
│   ├── hooks/
│   │   └── useEasterEggs.ts   # Fun hidden interactions
│   ├── lib/
│   │   ├── supabase.ts        # Supabase client (env-gated)
│   │   └── sync.ts            # Pull/push layer between Zustand ↔ Supabase
│   ├── pages/
│   │   ├── Auth.tsx           # Sign in / Register / Email verification
│   │   ├── Calendar.tsx       # Full calendar (month/week/day, recurring, sharing)
│   │   ├── Dashboard.tsx      # Home with smart insights + all widgets
│   │   ├── Focus.tsx          # Pomodoro timer (sessions tracked in store)
│   │   ├── Goals.tsx          # Goal + milestone tracking (fully persisted)
│   │   ├── Habits.tsx         # Habit tracker with forgiveness score + analytics
│   │   ├── Journal.tsx        # Daily journal + mood grid + habit correlation
│   │   ├── Notes.tsx          # Markdown notes editor (DOMPurify sanitized)
│   │   ├── Settings.tsx       # Theme, name, preferences
│   │   └── Tasks.tsx          # Task manager + time estimates (list + kanban)
│   ├── stores/
│   │   ├── useAppStore.ts     # All app state (Zustand + localStorage v4)
│   │   └── useAuthStore.ts    # Auth state (Supabase session)
│   ├── types/
│   │   └── index.ts           # Shared TypeScript interfaces
│   ├── utils/
│   │   └── cn.ts              # Class utilities + nanoid
│   ├── App.tsx                # Root layout, routing, auth gate, QuickAdd
│   └── main.tsx               # React entry point
├── .env.local                 # 🔒 Never commit — Supabase keys here
├── README.md                  # This file
├── ROADMAP.md                 # Stage tracker + future plans
├── package.json
├── tailwind.config.ts
├── tsconfig.app.json
└── vite.config.ts

🏗 Architecture

┌─────────────────────────────────────────────────────┐
│                    USER (Browser / PWA)              │
│                                                     │
│   ┌─────────────┐   ┌───────────────────────────┐  │
│   │  React UI   │◄──│  Zustand Store (persist)  │  │
│   │  (pages +   │   │  localStorage (offline)   │  │
│   │  widgets)   │──►│  version 3, migrated      │  │
│   └──────┬──────┘   └────────────┬──────────────┘  │
│          │                       │                   │
│          │ user actions          │ pull / push       │
│          │                       ▼                   │
│          │          ┌────────────────────────────┐  │
│          │          │       sync.ts layer        │  │
│          │          │  pullAll() / pushAll()      │  │
│          │          │  subscribeRealtime()        │  │
│          │          └────────────┬───────────────┘  │
│          │                       │                   │
└──────────┼───────────────────────┼───────────────────┘
           │                       │ Supabase JS SDK
           ▼                       ▼
┌──────────────────────────────────────────────────────┐
│                    SUPABASE                          │
│                                                      │
│  ┌──────────┐  ┌──────────────┐  ┌───────────────┐ │
│  │   Auth   │  │  PostgreSQL  │  │   Realtime    │ │
│  │  (email  │  │  (10 tables) │  │  (live sync   │ │
│  │  + OAuth)│  │  + RLS       │  │  across tabs) │ │
│  └──────────┘  └──────────────┘  └───────────────┘ │
└──────────────────────────────────────────────────────┘

Data Flow

  1. Offline-first: All reads/writes hit Zustand → persisted to localStorage
  2. On login: pullAll() fetches from Supabase and merges into store
  3. On changes: debounced pushAll() syncs to Supabase in the background
  4. Realtime: subscribeRealtime() listens for changes from other devices
  5. Auth gate: If Supabase is configured and no session exists, the Auth page is shown

Security Model

  • All Supabase tables have Row Level Security (RLS) — users can only read/write their own data
  • Markdown preview is sanitized with DOMPurify to prevent XSS attacks
  • Auth tokens are managed by Supabase JS SDK (HttpOnly cookies in production)
  • No user data is ever sent to third-party services (GIFs are fetched client-side via GIPHY)

🚀 Running Locally

Prerequisites

  • Node.js 18+
  • npm 9+

Setup

# 1. Clone the repo
git clone <your-repo-url>
cd bloom

# 2. Install dependencies
npm install --legacy-peer-deps

# 3. Set up environment variables
cp .env.example .env.local
# Fill in your Supabase URL + anon key (optional — app works without it)

# 4. Run the dev server
npm run dev

The app runs at http://localhost:5173.

Without Supabase: The app works fully offline — data is stored in localStorage. You can skip the .env.local step entirely and use the app as a local tool.

Building for Production

npm run build
# Output: dist/

Environment Variables

# .env.local
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key-here
VITE_GIPHY_KEY=your-giphy-api-key-here   # optional, for GIF picker in notes

🗄 Database Setup (Supabase)

  1. Create a new project at supabase.com
  2. Go to SQL Editor → New Query
  3. Paste and run the full contents of supabase/schema.sql
  4. Go to Database → Replication and enable Realtime for all tables
  5. (Optional) Enable storage bucket for avatar uploads (instructions in schema.sql comments)

🎨 Themes

Bloom supports three built-in themes, switchable from Settings:

Theme Description
pink Soft rose & sakura (default)
dark Deep plum night mode
light Clean white minimal

Themes are applied via CSS custom properties on [data-theme] attribute.


📱 PWA Installation

Bloom is a full Progressive Web App:

  • Android / Samsung Tab: Open in Chrome → "Add to Home Screen"
  • iPhone / iPad: Open in Safari → Share → "Add to Home Screen"
  • Desktop (Mac/Windows): Chrome/Edge address bar → Install icon

Once installed, the app works completely offline.


👩‍💻 Made By

Made By Cengiz 💕

About

Calendar app

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors