Revise contributing guidelines for clarity and detail
Updated contributing guidelines to clarify architectural constraints and development setup instructions.
This commit is contained in:
+183
-33
@@ -1,36 +1,173 @@
|
||||
# Contributing to Oikos
|
||||
|
||||
Thanks for your interest in contributing. Oikos is a small, opinionated project — this guide covers the constraints and conventions you need to know before submitting code.
|
||||
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.
|
||||
|
||||
## Ground Rules
|
||||
---
|
||||
|
||||
**Oikos has a hard "no frameworks, no build tools" constraint.** This is not a temporary limitation — it's an architectural decision. Specifically:
|
||||
## Hard Constraints
|
||||
|
||||
- No React, Vue, Svelte, Angular, or any frontend framework
|
||||
- No Webpack, Vite, Rollup, esbuild, or any bundler
|
||||
- No TypeScript (plain JavaScript with ES modules)
|
||||
- No CSS libraries (Tailwind, Bootstrap, etc.)
|
||||
- No external frontend dependencies except Lucide Icons (self-hosted SVG sprite)
|
||||
**Oikos enforces a strict "no frameworks, no build tools" policy.** This is a permanent architectural decision, not a temporary limitation.
|
||||
|
||||
If your contribution requires adding a frontend dependency, it will not be merged. Backend dependencies are evaluated case-by-case but should remain minimal.
|
||||
Specifically — the following will **not** be merged:
|
||||
|
||||
## Getting Started
|
||||
- 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 — skip DB_ENCRYPTION_KEY for local dev
|
||||
# Set SESSION_SECRET — leave DB_ENCRYPTION_KEY empty (no SQLCipher needed locally)
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Run tests before submitting:
|
||||
`npm run dev` starts the server with `--watch` for automatic restarts on file changes.
|
||||
|
||||
### Running tests
|
||||
|
||||
```bash
|
||||
npm test # Requires Node >=22 (uses --experimental-sqlite)
|
||||
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/):
|
||||
|
||||
```
|
||||
<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:**
|
||||
|
||||
```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
|
||||
@@ -46,46 +183,59 @@ npm test # Requires Node >=22 (uses --experimental-sqlite)
|
||||
- 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)
|
||||
- Pages are ES modules in `public/pages/` that export a `render()` function
|
||||
- CSS uses design tokens from `public/styles/tokens.css` — don't hardcode colors or radii
|
||||
- CSS uses design tokens from `public/styles/tokens.css` — never hardcode values
|
||||
- Pages export a `render()` function, no side effects on import
|
||||
|
||||
### Backend
|
||||
|
||||
- API routes live in `server/routes/`, one file per module
|
||||
- One route file per module in `server/routes/`
|
||||
- API responses: `{ data: ... }` on success, `{ error: string, code: number }` on failure
|
||||
- Database migrations go in the `migrations` array in `server/db.js` — **append only, never modify existing entries**
|
||||
- Every table: `id INTEGER PRIMARY KEY`, `created_at TEXT`, `updated_at TEXT`
|
||||
- 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
|
||||
|
||||
- Tests use the Node.js built-in test runner with in-memory SQLite (`--experimental-sqlite`)
|
||||
- One test file per module in `tests/`
|
||||
- No running server needed — tests import route handlers directly
|
||||
- Tests use in-memory SQLite via `--experimental-sqlite`
|
||||
- Import route handlers directly — no HTTP calls, no running server
|
||||
|
||||
## Submitting Changes
|
||||
---
|
||||
|
||||
1. Fork the repo and create a branch from `main`
|
||||
2. Make your changes following the conventions above
|
||||
3. Add or update tests if applicable
|
||||
4. Run `npm test` and make sure all tests pass
|
||||
5. Open a pull request with a clear description of what and why
|
||||
## Changelog
|
||||
|
||||
Keep PRs focused. One feature or fix per PR. Large refactors should be discussed in an issue first.
|
||||
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`).
|
||||
|
||||
## Reporting Bugs
|
||||
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 to happen
|
||||
- What actually happened
|
||||
- What you expected vs. what happened
|
||||
- Steps to reproduce
|
||||
- Environment (browser, OS, Docker version if relevant)
|
||||
- Screenshots if applicable
|
||||
|
||||
## Feature Requests
|
||||
### Feature requests
|
||||
|
||||
[Open an issue](https://github.com/ulsklyc/oikos/issues/new) describing the use case. Explain the problem before proposing a solution — there might be a simpler approach that fits the existing architecture.
|
||||
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 constraints (see above) or significantly expand scope will likely be declined. When in doubt, ask first.
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user