Skip to content

Commit aa58f41

Browse files
committed
Initial commit
0 parents  commit aa58f41

129 files changed

Lines changed: 17628 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# ─── Backend (.env at repo root — consumed by FastAPI + seed + Vercel) ─────
2+
# Your Supabase project. Create one at https://supabase.com (free tier works).
3+
SUPABASE_URL=https://YOUR-PROJECT.supabase.co
4+
SUPABASE_SERVICE_KEY=your-service-role-key
5+
6+
# Argon2id hash of the password that gates the app. Generate with:
7+
# uv run python -m app.tools.hashpw 'your-strong-password'
8+
APP_PASSWORD_HASH=
9+
10+
# Random secret for session signing. Generate with:
11+
# python -c 'import secrets; print(secrets.token_urlsafe(48))'
12+
SESSION_SECRET=
13+
14+
# Comma-separated list of origins allowed to hit the API.
15+
CORS_ORIGINS=http://localhost:5173
16+
17+
# Optional: public URL of the deployed app (for OAuth/MCP callback URLs).
18+
# In local dev you can leave this blank — it's derived from the request.
19+
PUBLIC_URL=
20+
21+
# Optional: only needed to run `psql` migrations locally.
22+
SUPABASE_DB_PASSWORD=
23+
24+
# Optional: local directory that mirrors the course_files bucket (for scripts/sync.py).
25+
STUDY_ROOT=
26+
27+
# ─── Frontend (web/.env.local) ─────────────────────────────────────────────
28+
VITE_API_BASE_URL=http://localhost:8000

.gitignore

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# dependencies
2+
node_modules/
3+
.pnpm-store/
4+
web/.vite/
5+
6+
# builds
7+
dist/
8+
build/
9+
out/
10+
web/dist/
11+
*.tsbuildinfo
12+
13+
# env
14+
.env
15+
.env.local
16+
.env.*.local
17+
!.env.example
18+
19+
# python
20+
__pycache__/
21+
*.py[cod]
22+
*$py.class
23+
.venv/
24+
venv/
25+
.pytest_cache/
26+
.mypy_cache/
27+
.ruff_cache/
28+
api/.venv/
29+
mcp/.venv/
30+
31+
# editors
32+
.vscode/
33+
.idea/
34+
*.swp
35+
.DS_Store
36+
Thumbs.db
37+
38+
# vercel
39+
.vercel/
40+
41+
# logs
42+
*.log
43+
npm-debug.log*
44+
pnpm-debug.log*
45+
46+
.vercel
47+
48+
# tool-local state
49+
.claude/
50+
supabase/

CLAUDE.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# CLAUDE.md
2+
3+
Notes for Claude Code working in this repo. See `README.md` for stack basics and `INSTALL.md` for self-host setup.
4+
5+
## Deployment
6+
7+
**Hosting:** Vercel (frontend + Python API functions). Project is linked in `.vercel/project.json`.
8+
9+
**How deploys happen:** Vercel auto-deploys on every push to `main` via the GitHub integration. Nothing deploys from your local working copy — code changes stay local until pushed.
10+
11+
**Implication:** Edits to files under `app/` (Python backend / MCP tools) and `web/src/` (frontend) only affect the live site at `<your-deployment>.vercel.app` after a `git push` to `main`. The MCP server the user connects to from Claude.ai runs on the deployed Vercel instance — so MCP tool behavior won't change for them until a push.
12+
13+
**When to push:** don't deploy after every fix. Push when:
14+
- The user asks you to deploy / push / "ship it"
15+
- A batch of changes is ready and tested locally
16+
- A bug fix is urgent enough that the live site needs it now
17+
18+
When in doubt, ask. Don't `git push` on your own for routine fixes.
19+
20+
**Deploy commands:**
21+
```bash
22+
git push origin main # triggers auto-deploy
23+
vercel --prod # manual deploy (rarely needed)
24+
vercel logs <url> # inspect a deployment
25+
```
26+
27+
**Local verification before pushing:**
28+
```bash
29+
cd web && pnpm build # frontend builds clean
30+
uv run pytest # if/when backend tests exist
31+
```
32+
33+
## Two copies of the fall-behind logic
34+
35+
`app/services/fall_behind.py` (Python, runs on Vercel / MCP) and `web/src/lib/fall-behind.ts` (TS, runs in the browser) are intentional mirrors. Keep them in sync when changing rules — constants, grace periods, severity thresholds.

CODE_OF_CONDUCT.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Code of Conduct
2+
3+
## Our Pledge
4+
5+
In the interest of fostering an open and welcoming environment, we as
6+
contributors and maintainers pledge to make participation in our project and
7+
our community a respectful experience for everyone, regardless of age, body
8+
size, disability, ethnicity, gender identity and expression, level of
9+
experience, nationality, personal appearance, race, religion, or sexual
10+
identity and orientation.
11+
12+
## Our Standards
13+
14+
Examples of behavior that contributes to a positive environment:
15+
16+
- Using welcoming and inclusive language
17+
- Being respectful of differing viewpoints and experiences
18+
- Gracefully accepting constructive criticism
19+
- Focusing on what is best for the community
20+
- Showing empathy towards other community members
21+
22+
Examples of unacceptable behavior:
23+
24+
- The use of sexualized language or imagery
25+
- Trolling, insulting or derogatory comments, and personal or political attacks
26+
- Public or private harassment
27+
- Publishing others' private information without explicit permission
28+
- Other conduct which could reasonably be considered inappropriate in a
29+
professional setting
30+
31+
## Our Responsibilities
32+
33+
Project maintainers are responsible for clarifying the standards of acceptable
34+
behavior and are expected to take appropriate and fair corrective action in
35+
response to any instances of unacceptable behavior.
36+
37+
Project maintainers have the right and responsibility to remove, edit, or
38+
reject comments, commits, code, wiki edits, issues, and other contributions
39+
that are not aligned to this Code of Conduct, or to ban temporarily or
40+
permanently any contributor for other behaviors that they deem inappropriate,
41+
threatening, offensive, or harmful.
42+
43+
## Scope
44+
45+
This Code of Conduct applies both within project spaces and in public spaces
46+
when an individual is representing the project or its community.
47+
48+
## Enforcement
49+
50+
Instances of unacceptable behavior may be reported by opening a private
51+
GitHub Security Advisory on the repository, or by contacting the project
52+
maintainer directly via the email listed on the maintainer's GitHub profile.
53+
All complaints will be reviewed and investigated and will result in a response
54+
that is deemed necessary and appropriate to the circumstances. The project
55+
team is obligated to maintain confidentiality with regard to the reporter of
56+
an incident.
57+
58+
## Attribution
59+
60+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
61+
version 1.4, available at
62+
https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
63+
64+
[homepage]: https://www.contributor-covenant.org

CONTRIBUTING.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Contributing
2+
3+
Thanks for considering a contribution — genuinely. Whether it's a one-line typo fix, a new MCP tool, or just an issue saying "this didn't work on my machine, here's what I saw" — all of it helps.
4+
5+
This file just has a couple of notes so you know what to expect and we can keep the back-and-forth short.
6+
7+
## What's in scope
8+
9+
Basically anything that makes the app better for someone self-hosting it. A non-exhaustive list of things I'd love help with:
10+
11+
- **Bug fixes** — obvious one. If you hit a bug, please file an issue even if you can't fix it yourself.
12+
- **Self-host polish** — clearer docs, better error messages when an env var is missing, a `docker-compose.yml`, one-click deploy buttons for hosts other than Vercel (Fly, Railway, self-hosted Postgres, etc.).
13+
- **Accessibility + keyboard shortcuts** — the UI is dark, dense, and keyboard-navigable-ish, but could be better.
14+
- **i18n / localization** — the Slot `kind` labels are German (`Vorlesung`, `Übung`) by default. Making those user-configurable or translatable would help non-EU users a lot.
15+
- **New MCP tools** — if you find yourself wishing Claude could do `X` and there's a natural way to expose it, just add it. Pattern is in `app/mcp_tools.py`.
16+
- **Performance / bundle size** — the frontend chunk is bigger than it needs to be; someone who knows their way around Vite code-splitting could shave a lot.
17+
- **Tests** — there's no suite yet. Adding pytest + Vitest scaffolding is its own welcome PR.
18+
19+
## Things worth a quick issue first
20+
21+
Not "no" — just "let's talk first so you don't waste a weekend":
22+
23+
- Major framework swaps (React → Svelte, FastAPI → Django).
24+
- Removing Supabase (doable, but touches auth + storage + Postgres all at once).
25+
- New top-level entities beyond the current data model (Course / Schedule slot / Lecture / Study topic / Deliverable / Task / Klausur).
26+
- Multi-user / team / sharing features — the single-user-per-deploy assumption is load-bearing in a bunch of places, and shifting it is a big project.
27+
28+
A one-liner issue like *"would you take a PR that X?"* is all it takes.
29+
30+
## Dev setup
31+
32+
See [INSTALL.md](./INSTALL.md) for the full walkthrough. TL;DR:
33+
34+
```bash
35+
uv sync
36+
cp .env.example .env # fill in Supabase creds, APP_PASSWORD_HASH, SESSION_SECRET
37+
uv run python -m db.seed
38+
uv run uvicorn app.main:app --reload
39+
40+
cd web && pnpm install && pnpm dev
41+
```
42+
43+
## Code conventions
44+
45+
- **Python:** `ruff` is configured in `pyproject.toml` (line-length 100, py312 target). Run `uv run ruff check .` and `uv run ruff format .` before pushing.
46+
- **TypeScript/React:** `eslint` is configured in `web/`. Run `pnpm lint` from `web/`. Components are function components + hooks; state via React Query for server state and `useState`/`useReducer` for local.
47+
- **Commit messages:** short imperative subject line (≤70 chars), optional body explaining the *why*. See `git log` for the house style.
48+
- **Scope per PR:** one logical change. A bug fix + a refactor + a new feature should be three PRs.
49+
50+
## The fall-behind mirror
51+
52+
`app/services/fall_behind.py` (Python, runs on the server / in MCP) and `web/src/lib/fall-behind.ts` (TypeScript, runs in the browser) are **intentional mirrors**. Any change to the rules — severity thresholds, grace periods, which topics count — must be applied to both. PRs that only touch one side will get a request for the other.
53+
54+
## Testing
55+
56+
There's no automated test suite yet (honest). Until there is:
57+
58+
- For backend changes: exercise the changed endpoint(s) manually via `curl` or the `/api/docs` Swagger UI, and check that the data round-trips through Supabase.
59+
- For frontend changes: run `pnpm build` to make sure TypeScript is still happy, then manually click through the affected views in `pnpm dev`.
60+
- For MCP tool changes: start the backend (`uv run uvicorn app.main:app --reload`), then either hit the tool via a `POST /mcp` JSON-RPC request with your bearer token (see `curl` snippet in `INSTALL.md`), or register the local endpoint with Claude Code (`claude mcp add --transport http study-dashboard-dev http://localhost:8000/mcp`) and call the tool in chat.
61+
62+
If you're up for adding test infrastructure (pytest + a Supabase mock, Vitest for the frontend), that itself is a welcome PR.
63+
64+
## Submitting a PR
65+
66+
1. Fork, branch, commit.
67+
2. Run the relevant linter/build (`ruff`, `pnpm lint`, `pnpm build`).
68+
3. Push and open a PR against `main`.
69+
4. In the PR description, include: what the change does, how you tested it, anything reviewers should pay attention to.
70+
5. Be patient — this is a side project. Responses may take a few days.
71+
72+
## License
73+
74+
By submitting a PR you agree that your contribution is licensed under the same MIT license as the rest of the project (see [LICENSE](./LICENSE)).

0 commit comments

Comments
 (0)