Yuyao Huang ab000bcd41 fix: delay scroll handler binding to skip queued scroll event
scrollTop assignment triggers an async scroll event. When all tasks
fit in the viewport, handleScrollFocus recalculates center-aligned
task and picks the last one instead of the saved one. Using setTimeout(0)
defers handler binding to after the queued event fires.
2026-05-09 15:59:13 +08:00
2026-05-08 12:41:19 +08:00

GoalsBreakDown

A web-based task management application focused on goal-oriented task tracking with a scroll-view interface.

Features

  • Multi-user support with registration and authentication
  • Goal management with activation/deactivation
  • Task management with status tracking (todo/doing/pending/done)
  • Focus rule: Only one "doing" task per goal
  • Scroll-view task selector with drag-and-drop reordering
  • Admin panel for user management
  • Per-user goal limits

Quick Start

Prerequisites

  • Python 3.10+
  • uv package manager

Installation

# Clone the repository
git clone <repository-url>
cd GoalsBreakDown

# Create your local configuration from the example
cp config.example.py config.py

# Install dependencies with uv
uv sync

# Run the application
uv run python app.py

The application will start at http://127.0.0.1:5000

Default Admin Account

  • Username: admin
  • Password: admin123

Important: Change the default admin password after first login.

Configuration

Local configuration is managed via config.py (not tracked in git). Use config.example.py as a template:

# Copy the example config and edit it
cp config.example.py config.py

Available settings in config.py:

Setting Description Default
DB_PATH SQLite database path data/db.sqlite
DEFAULT_ADMIN_USERNAME Default admin username admin
DEFAULT_ADMIN_PASSWORD Default admin password admin123
DEFAULT_MAX_GOALS Max goals per new user 5
SECRET_KEY Flask session secret (change in production!)
DEBUG Debug mode True
HOST Server bind address 0.0.0.0
PORT Server port 5000

Production Deployment

  1. Copy config.example.py to config.py
  2. Change SECRET_KEY to a random secure string
  3. Set DEBUG = False
  4. Change default admin credentials
  5. Use a production WSGI server (e.g., gunicorn):
uv run gunicorn -w 4 -b 0.0.0.0:5000 app:app

Note: The -b flag is required because gunicorn is a separate WSGI server and does not read Flask's config.py. The values in config.py (HOST, PORT) only apply to Flask's built-in dev server (app.run()).

Project Structure

GoalsBreakDown/
├── app.py              # Flask application
├── config.example.py   # Configuration template (tracked in git)
├── config.py           # Local configuration (NOT tracked in git)
├── database.py         # SQLite operations
├── auth.py             # Authentication helpers
├── schema.py           # Database schema & migration
├── templates/          # HTML templates
├── static/
│   ├── css/           # Stylesheets
│   └── js/            # JavaScript files
└── data/              # Database (auto-created, not tracked in git)

Tech Stack

  • Backend: Python + Flask
  • Database: SQLite
  • Frontend: Vanilla JS + HTML/CSS
  • Drag-and-Drop: SortableJS
  • Markdown: marked.js
  • Authentication: bcrypt + Flask sessions
  • Environment: uv
Description
No description provided
Readme 270 KiB
Languages
JavaScript 32.6%
Python 30%
CSS 19.9%
HTML 17.5%