Ritme is a Laravel 12 web app for building consistent daily routines with a warm editorial UI style.
The app includes habit and todo management, quick check-ins, focus session tracking, notifications, and profile management with photo upload.
- Authentication (Laravel Breeze): login, register, reset password, email verification.
- Authentication also supports Google Sign-In (OAuth 2.0) with automatic account linking by email.
- Dashboard metrics: active habits, completed today, streak, focus minutes, unread notifications.
- Habit management:
- create, edit, archive, activate/deactivate,
- color picker + icon field,
- daily/weekly frequency and target count.
- Habit check-in:
- quick check-in from dashboard/list,
- log status and quantity.
- Todo management:
- create, edit, delete todos,
- pending/completed/overdue filters,
- mark done / return to pending,
- optional due date + reminder time.
- Focus sessions:
- start/stop timer,
- focused vs background duration,
- interruption count and session history.
- Notifications:
- list notifications,
- mark single/read all,
- unread badge in navbar,
- reminder emails for habit and todo (SMTP required),
- optional Telegram reminder delivery (per-user bot token + chat ID via Settings, with optional server fallback token).
- Profile:
- update name/email,
- update password,
- delete account,
- profile photo upload/remove,
- activity tab (habit, check-in, focus, notification history).
- Subtle page transition on internal navigation (without target-page flicker).
- PHP 8.2+
- Laravel 12
- Blade + Tailwind CSS + Alpine.js
- MySQL (local via XAMPP)
- Vite (frontend build tool)
- PHPUnit (feature + unit tests)
- XAMPP (PHP + MySQL)
- Composer 2+
- Node.js 18+ and npm
For this project, the local PHP binary used is:
/opt/lampp/bin/php- Clone repository and enter project directory.
git clone <your-repo-url> habit-tracker
cd habit-tracker- Install PHP dependencies.
composer install- Prepare environment file.
cp .env.example .env- Configure database in
.env.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=habit-tracker
DB_USERNAME=root
DB_PASSWORD=Optional Telegram reminder configuration:
TELEGRAM_BOT_TOKEN=your_bot_token_here
TELEGRAM_API_BASE_URL=https://api.telegram.orgOptional Google Sign-In configuration:
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
GOOGLE_REDIRECT_URI="${APP_URL}/auth/google/callback"- Create database (XAMPP MySQL).
/opt/lampp/bin/mysql -h 127.0.0.1 -P 3306 -u root -e "CREATE DATABASE IF NOT EXISTS \`habit-tracker\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"- Generate app key and run migrations.
/opt/lampp/bin/php artisan key:generate
/opt/lampp/bin/php artisan migrate- Link public storage (required for profile photos).
/opt/lampp/bin/php artisan storage:link- Install frontend dependencies and build assets.
npm install
npm run build- Run local app.
/opt/lampp/bin/php artisan serveOpen: http://127.0.0.1:8000
Run Vite in dev mode:
npm run devRun tests:
/opt/lampp/bin/php artisan testRun scheduler loop in local terminal:
/opt/lampp/bin/php artisan schedule:workManual reminder check command:
/opt/lampp/bin/php artisan habit:check-reminders
/opt/lampp/bin/php artisan todo:check-remindersThe app schedules habit:check-reminders and todo:check-reminders every minute in app/Console/Kernel.php.
Production cron example:
* * * * * /opt/lampp/bin/php /path/to/habit-tracker/artisan schedule:run >> /dev/null 2>&1All routes below require authentication unless stated otherwise.
| Method | Path | Purpose |
|---|---|---|
GET |
/ |
Redirect to login or dashboard |
GET |
/dashboard |
Main dashboard page |
GET |
/habits |
Habit list page |
GET |
/habits/create |
Create habit form |
GET |
/habits/{habit} |
Habit detail page |
GET |
/habits/{habit}/edit |
Edit habit form |
GET |
/todos |
Todo list page |
GET |
/todos/create |
Create todo form |
GET |
/todos/{todo}/edit |
Edit todo form |
GET |
/focus-sessions |
Focus timer and history page |
GET |
/notifications |
Notifications page |
GET |
/settings |
Notification channel settings (email/telegram, including per-user Telegram bot token) |
GET |
/profile |
Profile settings and activity page |
These are internal JSON endpoints consumed by Blade + JS modules.
- All
/ajax/*endpoints require authenticated session (webguard). - For
POST/PATCHrequests, send CSRF token from<meta name="csrf-token">. - Recommended header for API calls:
Accept: application/jsonX-CSRF-TOKEN: <token>
Success:
{
"success": true,
"message": "Human-readable message",
"data": {}
}Error:
{
"success": false,
"message": "Error message",
"errors": {}
}Common status codes:
200success401unauthenticated403forbidden (ownership/authorization)404resource not found422validation/domain error
| Method | Path | Request | Success data |
|---|---|---|---|
GET |
/ajax/dashboard/summary |
none | total_active_habits, completed_today, current_streak, focus_minutes_today, unread_notifications, pending_todos, due_today_todos |
GET |
/ajax/dashboard/today-habits |
none | habits[], notifications_preview[] |
habits[] item shape:
id,title,frequency,target_count,reminder_timetoday_log(id,status,qty) ornullis_completed_today(boolean)
| Method | Path | Request Body | Success data |
|---|---|---|---|
POST |
/ajax/habit-logs/quick-checkin |
habit_id (required), status (completed/skipped/missed, optional), qty (optional), note (optional), log_date (optional) |
action (created/updated), log (HabitLogResource) |
Notes:
- Quick check-in always writes to today's date.
statusdefaults tocompletedandqtydefaults to1if omitted.
| Method | Path | Request Body | Success data |
|---|---|---|---|
POST |
/ajax/focus-sessions/start |
habit_id (optional, must belong to user), planned_duration_minutes (1..1440, optional), note (optional) |
session (FocusSessionResource), reused_existing_session (boolean) |
POST |
/ajax/focus-sessions/{focusSession}/stop |
focused_duration_seconds (required), unfocused_duration_seconds (required), interruption_count (required), status (completed/cancelled) |
session (FocusSessionResource) |
GET |
/ajax/focus-sessions/today-summary |
none | total_sessions, focus_minutes_today, background_minutes_today, interruption_count_today |
Notes:
startreturnsreused_existing_session=trueif a running session already exists.stopreturns422with messageSesi fokus sudah tidak aktif.if the session is no longer running.
| Method | Path | Request | Success data |
|---|---|---|---|
GET |
/ajax/notifications |
Query: limit (1..50, default 10) |
notifications[], unread_count |
GET |
/ajax/notifications/unread-count |
none | unread_count |
notifications[] item shape:
id,type,title,message,datais_read,read_at,scheduled_for,created_at,updated_at
These endpoints are in web routes and return redirect by default. If request expectsJson(), they return JSON envelope.
| Method | Path | Purpose |
|---|---|---|
POST |
/notifications/{notification}/read |
Mark one notification as read |
POST |
/notifications/read-all |
Mark all notifications as read |
Implementation docs are available in docs/, including:
habit-tracker-implementation-roadmap.mdhabit-tracker-project-structure-naming.mdhabit-tracker-laravel12-service-business-flow.mdhabit-tracker-api-contract.mdhabit-tracker-testing-strategy.mdshared-hosting-deploy-guide.md(deployment workflow for shared hosting)
Current test suite includes feature and unit tests across:
- auth flow,
- habits,
- habit logs,
- focus sessions,
- notifications,
- dashboard metrics,
- profile (including photo upload/remove).
MIT