6.8 KiB
Welcome — Junior Developer Onboarding
Welcome to Föräldraledigplannerare, a web app that helps Swedish parents plan their parental leave (föräldrapenning) and vacation days — alone or together with a partner — and see how many days they'll have left when their child turns 4. This guide gets you productive quickly on well-scoped pieces while the senior-owned, higher-risk parts are handled separately.
Read first: ARCHITECTURE.md — at least the overview (§0–§1), the data model (§3), and the section for whatever you pick up. Don't worry about absorbing all of it at once.
Foundation status — ready to build on. The senior has finished the project foundation and the cross-cutting patterns, so you can start straight away. In place:
- ✅ Backend reference slice (
VacationDays) — tests intests/unit/test_vacation_days_repository.py- ✅ Full schema + Alembic migrations (
migrations/versions/001_initial_schema.py)- ✅ Auth (register/login/JWT) —
services/auth_service.py,routers/auth.py- ✅ Workspace + invitation flow —
services/workspace_service.py,routers/workspace.py- ✅ All 9 entities and their SQLite repos
- ✅
FetchDataServicecontract + manual entry path (services/fetch_data_service.py)- ✅ Analytics service with days-left-at-age-4 (
services/analytics_service.py)- ✅ Tips engine skeleton (
services/tips_service.py) — rules ready to wire- ✅
BreakPeriodService(services/break_period_service.py)- ✅ Frontend project scaffolded + reference hook/component/test (
hooks/useVacationDays.ts,components/vacation-days/)- ✅ CI pipeline (
.github/workflows/ci.yml)First step:
cd backend && uv sync && uv run pytest— confirm the suite is green, then pick up Task 1.
1. Tech stack & the big picture
- Backend: Python 3.14, FastAPI,
uvfor packages. Layered:entities → repositories → services → routers, wired with dependency injection. - Frontend: TypeScript + React + Vite, tested with Vitest.
The single most useful thing you can do is study the reference vertical slice for the VacationDays entity. It shows every layer once, end-to-end. You'll build new features by copying its shape.
backend/app/
entities/vacation_days.py # 1. plain dataclass (the domain object)
models/vacation_days.py # 2. pydantic request/response schemas
repositories/vacation_days_repository.py # 3. abstract interface
repositories_impl/sqlite/vacation_days_repository.py # 4. SQLite implementation
services/vacation_days_service.py # 5. business rules
routers/vacation_days.py # 6. HTTP endpoints
backend/tests/unit/test_vacation_days_repository.py # 7. tests
2. Getting set up
Backend
cd backend
uv sync # install dependencies
uv run pytest # run tests (should pass)
uv run uvicorn app.main:app --reload # dev server on http://localhost:8000 (/health, /docs)
uv run ruff check . # lint
Frontend
cd frontend
npm install
npm run dev # dev server
npm test # Vitest
3. Your starter tasks
Work in small PRs, lowest number first. Each task says which existing file to copy.
Backend — copy the VacationDays slice
BreakPeriodtests (great first task — all layers already exist, study and test them). Entity, schema, SQLite repo, service (services/break_period_service.py), and router (routers/break_periods.py) are all in place. Your job: writetests/unit/test_break_period_repository.pyfollowing thetest_vacation_days_repository.pypattern. Remember to use theseeded_idsfixture (seetests/conftest.py) so FK constraints pass.ChildCRUD + settings endpoints (incl.preschool_start_date). Same pattern; wire thePUT /api/settings/child/{child_id}endpoint from§5.- Parent-profile settings (
salary_type,employment_status) and workspaceplanning_goalendpoints from§5.
Backend — pure utility functions (very test-friendly, no framework)
- Date helpers in
app/utils/dates.py: e.g.add_months(date, n),age_in_months(birth_date, on),fourth_birthday(birth_date). Pure functions with thorough unit tests — the calculation engine will depend on these, so correctness matters (mind leap years / month-end). - Swedish public-holiday helper (
§6.2): given a year, return the röda dagar (use theholidayslibrary, Sweden locale; cache per year). Unit-test a few known dates. The calendar UI and the "wrap red days with vacation" tip both need this.
Frontend
- Transcribe the TypeScript types from
ARCHITECTURE.md §7intofrontend/src/types/. Mechanical but valuable — everything else builds on these. - Presentational components (take props, render UI, no business logic):
LoadingSpinner,Header,Footer,Layout,CalendarDay,CalendarEvent,OverviewMetrics,DaysBreakdown,ProgressChart,TipCard, and the settings inputs (VacationDaysInput,ChildBirthdayInput,ParentProfileInput,PlanningGoalSelector,BreakPeriodsInput). Each with a Vitest render test. - Frontend utils
dates.ts/formatting.ts(e.g. format day counts, sv-SE dates) with tests. - Simple data hooks following the reference hook the senior provides (e.g.
useVacationDays,useBreakPeriods) — fetch + loading/error state.
4. Definition of done (every PR)
- Fully typed — no
anyin TS without a written reason; type hints on all Python. - Tests added, ≥90% coverage on the code you wrote; happy path and error cases.
ruff check(backend) / ESLint (frontend) clean.- Errors raised as
DomainErrorsubclasses (backend) — never a bareexcept, never a silent failure. - Magic numbers for Swedish rules come from
config.py::LeaveRules, not hard-coded. - Keep PRs small and focused; a draft PR with questions is very welcome.
5. Out of scope — owned by the senior developer
These are higher-risk or high-ambiguity and belong to the senior. They're not blocking you — they're simply someone else's lane. You can build the presentational pieces around them (e.g. a TipCard component), just not the core logic:
- The Försäkringskassan scraper / BankID flow (legal + security sensitive).
- Auth & security (password hashing, tokens, sessions, invitation tokens).
- The "days left at age 4" calculation and planned-vs-actual reconciliation (
§6.5). - The tips engine logic — the SGI / payroll / red-day rules themselves (
§6). - Database migrations and the connection/pool setup.
6. Getting help
If a task is ambiguous, the data model is unclear, or a test is hard to write — ask early rather than guessing. Note what you tried and where you got stuck; that makes it quick for a senior to unblock you. Welcome aboard!