Files
oikos/CONTRIBUTING.md
T
ulsklyc 29c9292d2d Revise contributing guidelines for clarity and detail
Updated contributing guidelines to clarify architectural constraints and development setup instructions.
2026-03-29 15:43:49 +02:00

7.7 KiB

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

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

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. 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

# 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

git fetch upstream
git rebase upstream/main

Rebase before opening a PR. Merge commits will be squashed.

4. Commit

Follow Conventional Commits:

<type>(<scope>): <description>

[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:

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.jsnever 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. 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.

### Added
- Add CSV import for budget entries

Reporting Issues

Bugs

Open an issue 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 or significantly expand scope will likely be declined. When in doubt, ask first.

Security vulnerabilities

Do not open a public issue. See SECURITY.md for responsible disclosure.


License

By contributing, you agree that your contributions will be licensed under the MIT License.