Skip to content

Latest commit

 

History

History
98 lines (69 loc) · 3.22 KB

File metadata and controls

98 lines (69 loc) · 3.22 KB

graphnote

A web app for creating, sharing, and exploring interactive node-based graphs. Users can sign up, build graphs with a visual editor, make them public or private, like and comment on other people's graphs, and customize their profile.

Screenshots

Graph View Node Editor Home Page
Graph Editor Home

Running

Docker (recommended)

docker compose up --build -d

Open http://localhost:5173.

To stop and wipe the database:

docker compose down -v

Local development

Backend:

cd backend
python3 -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install -r ../requirements.txt
# create a .env with DATABASE_URL and JWT_SECRET_KEY
python3 app.py

Frontend (from project root):

npm install
npm run dev

Tests

Backend tests run against an in-memory SQLite database — no Docker needed:

pip install -r requirements.txt
python -m pytest tests.py -v

Note: Front-end tests are not functional at the moment.

Optimizations

  • In-memory TTL cache — graph and paginated list responses are cached process-locally with configurable expiry, avoiding repeated DB queries for hot data.
  • Rate limiting — node saves and avatar updates enforce a short cooldown per user to prevent spam writes.
  • Pagination — the public graph listing supports page / page_size query params so only a slice is loaded at a time.
  • Join-based comment loading — comments are fetched with an outerjoin to the users table in a single query, avoiding N+1.
  • Two-stage Docker build — the frontend Dockerfile uses a Node build stage then copies only the static output into a slim nginx image.

Security

  • Password hashing — passwords are stored as bcrypt hashes; plain-text passwords never touch the database.
  • JWT in httpOnly cookies — access tokens are stored in cookies with CSRF double-submit protection enabled in production.
  • Ownership enforcement — every mutating endpoint verifies the caller owns the target resource before allowing changes.
  • Private graph access control — private graphs (and their comments/likes) return 404 for anyone who is not the owner.
  • Input validation & sanitization — graph names are restricted to alphanumeric + spaces (max 40 chars), node fields are clamped (radius 8–100, font size 8–100, title ≤40, data ≤2000), comments are capped at 200 chars, and avatar URLs are validated against an allowlist of schemes.
  • Account deletion — deleting an account cascades through graphs, comments, and likes so no orphaned data remains.

Dependencies

Backend (Python — see requirements.txt):

  • Flask ≥ 2.0
  • Flask-JWT-Extended ≥ 4.0
  • Flask-Cors ≥ 3.0
  • Flask-SQLAlchemy ≥ 2.5
  • Flask-Bcrypt ≥ 0.7
  • psycopg2-binary ≥ 2.8
  • python-dotenv ≥ 0.20
  • SQLAlchemy ≥ 1.4

Frontend (npm — see package.json):

  • react ^19.2.0
  • react-dom ^19.2.0
  • react-router-dom ^7.13.1
  • tailwindcss ^4.2.1
  • vite ^7.3.1

Credits

Some icons used in this project are sourced from game-icons.net.