# Contributing to Oikos Thanks for your interest in contributing. Oikos is a small, opinionated project with deliberate architectural constraints. This guide covers what you need to know before submitting code. --- ## Hard Constraints **Oikos enforces a strict "no frameworks, no build tools" policy.** This is a permanent architectural decision, not a temporary limitation. Specifically — the following will **not** be merged: - Frontend frameworks (React, Vue, Svelte, Angular, etc.) - Bundlers or transpilers (Webpack, Vite, Rollup, esbuild, TypeScript, etc.) - CSS libraries (Tailwind, Bootstrap, etc.) - External frontend dependencies of any kind (except Lucide Icons as self-hosted SVG sprite) Backend dependencies are evaluated case-by-case but must remain minimal. When in doubt, open an issue before writing code. --- ## Development Setup ### Prerequisites - Node.js ≥ 22 (required for `--experimental-sqlite` in tests) - Git ### Getting started ```bash git clone https://github.com/ulsklyc/oikos.git cd oikos npm install cp .env.example .env # Set SESSION_SECRET — leave DB_ENCRYPTION_KEY empty (no SQLCipher needed locally) npm run dev ``` `npm run dev` starts the server with `--watch` for automatic restarts on file changes. ### Running tests ```bash npm test # All suites ``` Tests use the Node.js built-in test runner with in-memory SQLite. No running server or database required — tests import route handlers directly. --- ## Project Structure Understanding where things live helps you find the right place for your changes: ``` server/ index.js # Express entry point, middleware chain db.js # SQLite connection + migration runner (append-only) auth.js # Session auth + user management routes/ # API route handlers — one file per module services/ # Business logic (calendar sync, recurrence engine) public/ index.html # SPA shell (single entry point) router.js # Client-side History API router api.js # Fetch wrapper (auth, CSRF, error handling) styles/ tokens.css # Design tokens — all colors, radii, shadows, fonts components/ # Reusable Web Components (oikos-* prefix) pages/ # Page modules — each exports a render() function sw.js # Service worker tests/ # One test file per module docs/ # Product spec, screenshots ``` **Key patterns:** - Every API route lives in `server/routes/` and follows the same `try/catch` → JSON response pattern - Every frontend page is an ES module in `public/pages/` that exports `render()` - All design values come from `tokens.css` — never hardcode colors, radii, or shadows - Database migrations are appended to the `migrations` array in `server/db.js` — never modify existing entries --- ## Workflow ### 1. Find or create an issue Before starting work, check the [existing issues](https://github.com/ulsklyc/oikos/issues). For anything beyond a trivial fix, open an issue first to discuss the approach. This avoids wasted effort on changes that conflict with the project's direction. ### 2. Fork and branch ```bash # Fork on GitHub, then: git clone https://github.com/YOUR-USERNAME/oikos.git cd oikos git remote add upstream https://github.com/ulsklyc/oikos.git git checkout -b feat/your-feature-name ``` **Branch naming:** | Prefix | Use for | Example | |--------|---------|---------| | `feat/` | New features | `feat/csv-import-budget` | | `fix/` | Bug fixes | `fix/calendar-sync-timezone` | | `refactor/` | Internal changes (no behavior change) | `refactor/extract-date-utils` | | `docs/` | Documentation only | `docs/improve-setup-guide` | | `chore/` | Maintenance, CI, dependencies | `chore/update-helmet` | ### 3. Keep your fork in sync ```bash git fetch upstream git rebase upstream/main ``` Rebase before opening a PR. Merge commits will be squashed. ### 4. Commit Follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/): ``` (): [optional body] [optional footer] ``` **Types:** `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, `style` (formatting, not CSS) **Scope:** The module or area affected — `tasks`, `shopping`, `meals`, `calendar`, `budget`, `notes`, `contacts`, `auth`, `db`, `ui`, `pwa` **Examples:** ``` feat(meals): add drag & drop between day slots fix(calendar): handle timezone offset in recurring events docs(readme): add Apple CalDAV setup instructions refactor(auth): extract session validation into middleware test(budget): add CSV export edge cases chore: update express to 4.21 ``` **Rules:** - Subject line: imperative mood, lowercase, no period, max 72 characters - Body (optional): explain *why*, not *what* — the diff shows the what - One logical change per commit — don't mix features with formatting ### 5. Open a pull request - Target branch: `main` - Title: follows the same Conventional Commits format as your commits - Description: explain what the PR does, why, and link the related issue (`Closes #123`) - Keep PRs focused — one feature or fix per PR **Before opening:** ```bash npm test # All tests pass ``` ### 6. Review and merge PRs are reviewed by the maintainer. Expect feedback within a few days. Once approved, PRs are squash-merged into `main`. --- ## Code Conventions ### General - ES modules everywhere (`import`/`export`, never `require`) - Semicolons: **yes** - Header comment in every file: purpose, module, dependencies - `try/catch` in every route handler — no unhandled promise rejections - No `eval()`, no `innerHTML` with user input — use `textContent` or DOM API ### Frontend - Web Component prefix: `oikos-` (one component per file) - All UI text in **German** (the app targets German-speaking families) - Date format: `DD.MM.YYYY` — Time format: `HH:MM` (24h) - CSS uses design tokens from `public/styles/tokens.css` — never hardcode values - Pages export a `render()` function, no side effects on import ### Backend - One route file per module in `server/routes/` - API responses: `{ data: ... }` on success, `{ error: string, code: number }` on failure - Database migrations: append to the `migrations` array in `server/db.js` — **never modify existing entries** - Every table: `id INTEGER PRIMARY KEY`, `created_at TEXT`, `updated_at TEXT` (ISO 8601) ### Testing - One test file per module in `tests/` - Tests use in-memory SQLite via `--experimental-sqlite` - Import route handlers directly — no HTTP calls, no running server --- ## Changelog User-facing changes should be reflected in [`CHANGELOG.md`](CHANGELOG.md). If your PR adds a feature, fixes a bug, or changes behavior, add an entry under `[Unreleased]` in the appropriate category (`Added`, `Changed`, `Fixed`, `Removed`, `Security`). Format: imperative mood, one line per change, user-oriented language. ```markdown ### Added - Add CSV import for budget entries ``` --- ## Reporting Issues ### Bugs [Open an issue](https://github.com/ulsklyc/oikos/issues/new) with: - What you expected vs. what happened - Steps to reproduce - Environment (browser, OS, Docker version if relevant) - Screenshots if applicable ### Feature requests Describe the **use case** before proposing a solution. There might be a simpler approach that fits the existing architecture. Features that conflict with the project's [hard constraints](#hard-constraints) or significantly expand scope will likely be declined. When in doubt, ask first. ### Security vulnerabilities Do **not** open a public issue. See [`SECURITY.md`](SECURITY.md) for responsible disclosure. --- ## License By contributing, you agree that your contributions will be licensed under the [MIT License](LICENSE).