A full-stack discipline tracking app with strict, irreversible streak rules.
- Multiple targets: Create unlimited fixed-duration goals
- Daily check-ins: Mark each day complete (or fail permanently)
- Strict rules: Miss any day → target fails immediately
- Independent streaks: Each target has its own streak counter
- Locked targets: No edits allowed once started
- 2 users only: Private app for you and one other person
Backend
- FastAPI
- PostgreSQL
- SQLAlchemy ORM
- JWT authentication
- Python 3.9+
Frontend
- Next.js 13 (App Router)
- TypeScript
- Tailwind CSS
- React
IRONSTREAK/
├── backend/
│ ├── app/
│ │ ├── main.py # FastAPI app & endpoints
│ │ ├── models.py # SQLAlchemy models
│ │ ├── schemas.py # Pydantic schemas
│ │ ├── crud.py # Business logic
│ │ ├── auth.py # JWT & password hashing
│ │ ├── deps.py # Dependencies
│ │ └── database.py # DB config
│ ├── requirements.txt
│ ├── .env.example
│ └── README.md
├── frontend/
│ ├── app/
│ │ ├── page.tsx # Main dashboard
│ │ ├── layout.tsx
│ │ └── globals.css
│ ├── package.json
│ └── README.md
└── README.md
- Create virtual environment:
cd backend
python -m venv .venv
.venv\Scripts\Activate # Windows
# source .venv/bin/activate # Linux/Mac- Install dependencies:
pip install -r requirements.txt- Configure environment variables (copy
.env.exampleto.env):
DATABASE_URL=postgresql://postgres:password@localhost:5432/ironstreak
JWT_SECRET=your-secret-key-here
FRONTEND_ORIGIN=http://localhost:3000
USER1_EMAIL=me@example.com
USER1_PASSWORD=password
USER2_EMAIL=brother@example.com
USER2_PASSWORD=password- Run the backend:
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000Backend runs at: http://localhost:8000
- Install dependencies:
cd frontend
npm install- Set backend URL (optional, defaults to
http://localhost:8000):
# Create .env.local
NEXT_PUBLIC_BACKEND_URL=http://localhost:8000- Run the frontend:
npm run devFrontend runs at: http://localhost:3000
Users
- id, email, hashed_password, created_at
Targets
- id, user_id, target_text, start_date, end_date, duration_in_days, status (ACTIVE/FAILED/SUCCESS), locked
DailyCheckin
- id, target_id, date, completed, completed_at
Streak
- target_id, current_streak, last_completed_date
Default credentials (development):
- User 1:
me@example.com/password - User 2:
brother@example.com/password
Change these in .env before deployment!
POST /auth/login- Get JWT tokenGET /me- Get current user
POST /target/create- Create new targetGET /target/active- List active targetsGET /target/history- List completed/failed targets
POST /checkin/today?target_id=X- Mark today complete
GET /streak/{target_id}- Get streak info
- One check-in per day per target (UTC timezone)
- Must check in consecutively: Missing any day → target fails
- Check-in only for today: Cannot mark past/future dates
- Targets are immutable: Cannot edit after creation
- Success = complete all days: Auto-marked when duration reached
- Failed = permanent: No recovery, must create new target