Split domain/models/mod.rs (630 lines) into focused files: movie.rs, review.rs, user.rs, stats.rs, enrichment.rs, feed.rs. Move URL/date formatting from application use cases to presentation mappers — use cases now return raw domain data. Delete watchlist/get_page.rs (was pure presentation logic), replace with presentation/mappers/watchlist.rs. Document signature conventions in CONTRIBUTING.md.
3.4 KiB
Contributing
Thanks for your interest in Movies Diary! This is a personal project but contributions are welcome — bug fixes, new features, docs improvements, or picking up the deprecated TUI.
Getting started
- Fork and clone the repo
- Copy
.env.exampleto.envand fill in at leastJWT_SECRETandOMDB_API_KEY - Install Rust (stable, 2024 edition) and Bun (for the SPA)
- Run the backend and worker:
cargo run -p presentation # HTTP server on :3000
cargo run -p worker # event worker (separate terminal)
- Run the SPA dev server:
cd spa && bun install && bun run dev
Before submitting a PR
make # runs fmt-check + clippy + test
Or individually:
cargo fmt --check
cargo clippy -- -D warnings
cargo test
cd spa && bunx tsc --noEmit
All four must pass. PRs with clippy warnings or failing tests won't be merged.
Architecture
The project follows hexagonal (ports & adapters) architecture. See architecture.mmd for the full diagram.
Key rules:
- Presentation handlers never touch repositories directly — all domain logic goes through use cases in the
applicationcrate - Application use cases return raw domain data — URL formatting, date display, and view model assembly belong in presentation mappers (
presentation/src/mappers/) - Use cases called from presentation handlers take
&AppContext. Functions called from adapter event handlers take individualArc<dyn Trait>params to keep adapter dependencies explicit
domain → pure types, traits (ports), zero deps
application → use cases, orchestration
presentation → Axum handlers, routes, OpenAPI
worker → event consumer, background jobs
adapters/* → implements domain ports (sqlite, postgres, AP, etc.)
spa/ → React SPA (TanStack Router + shadcn/ui)
Adding a new feature
- Domain first — models in
domain/src/models/, ports inports.rs, events inevents.rs - Adapters — implement ports in both
sqliteandpostgresadapters, add migration - Application — use cases in
application/src/<domain>/, wire intocontext.rs - API types — DTOs in
api-types/src/ - Presentation — handler file in
handlers/<domain>.rs, routes inroutes.rs - SPA — API client in
spa/src/lib/api/, hook inspa/src/hooks/, components - Classic HTML — Askama template + CSS in
static/style.css
Database adapters
Both SQLite and PostgreSQL are supported. If you add a migration or repository, implement it for both. The postgres adapter uses $1, $2 params and TIMESTAMPTZ; SQLite uses ? and text datetimes.
Federation (ActivityPub)
Federation is feature-gated (#[cfg(feature = "federation")]). If your feature should federate, add domain events, handle them in activitypub/src/event_handler.rs, and create an AP object + inbound handler.
Code style
- No comments unless the why is non-obvious
- Concise commit messages
- One feature per PR — don't bundle unrelated changes
- Follow existing patterns (check a similar feature for reference)
Areas seeking help
- TUI (
crates/tui) — deprecated, needs a maintainer to bring it up to feature parity - Tests — the domain and application crates have 400+ unit tests; integration tests for the presentation layer are welcome
- Docs — API usage examples, deployment guides