Thanks for your interest in contributing! Takus is a free, privacy-first Knowledge OS that captures meetings, screens, and documents, then uses AI to build a knowledge graph connecting goals, tasks, people, and decisions.
- Fork and clone
git clone https://github.com/yourusername/takus.git cd takus - Install —
npm install - Configure — set your OAuth Client IDs in
public/config.js(see setup-guide.md) - Run —
npm run dev - Build —
npm run build
src/
├── main.js # Bootstrap
├── styles/ # Design system (CSS custom properties)
├── lib/ # Core libraries (state machine, recorder, cloud APIs, storage)
│ ├── graph/ # Knowledge graph subsystem (task-store, node-registry, vector-utils)
│ └── integrations/ # External service connectors (Slack, GitHub, Linear, Jira, Notion)
├── components/ # UI components (vanilla JS, no framework)
│ ├── insights-cards/ # Extracted insight card renderers (stats-helpers, status-cards)
│ └── history-cards/ # Extracted history item template (item-template)
└── apps/ # Pluggable app modules (WordPress-model architecture)
Key principles:
- 1 runtime dependency (
@netlify/blobs) — everything else is vanilla JS - 6 strategic chunks —
manualChunksinvite.config.jssplits core, AI, cloud, pipeline, integrations - State machine driven — recording lifecycle is a finite state machine
- Vanilla JS — no framework, ES modules, web standards
- CSS custom properties — design tokens for consistent theming
- WordPress-model architecture — App Shell + decoupled apps, each self-registering via
app-manager.js
- Modern JavaScript (ES2020+, ES modules)
- Meaningful variable names, short focused functions
- JSDoc comments for public APIs
- No
var, preferconstoverlet
Task/Step access — Always use task-helpers.js:
import { getTaskTitle, isStepDone, getStepDoneCount, areAllStepsDone, isTaskPending } from '../lib/task-helpers.js';
// ✅ Correct
const title = getTaskTitle(task);
const done = isStepDone(step);
// ❌ Never access directly
const title = task.title; // use getTaskTitle()
const done = step.status === 'completed'; // use isStepDone()Step text access — Steps can be objects { text, status } or plain strings:
// ✅ Always guard step text access
const text = typeof s === 'string' ? s : s.text;
// ❌ Never assume step is an object
const text = s.text; // breaks if s is a stringTime constants — Always use named exports from utils.js:
import { MS_PER_HOUR, MS_PER_DAY } from '../lib/utils.js';
// ❌ Never use magic numbers: 86400000, 3600000Takus uses Vitest with JSDOM and fake-indexeddb:
npm test # Run all 1,813 tests (109 files)
npm run test:watch # Watch mode during developmentAdding a new test:
- Create
src/lib/__tests__/your-module.test.js - Import from
vitest:import { describe, it, expect } from 'vitest' - The setup file (
src/lib/__tests__/setup.js) auto-loadsfake-indexeddbandcrypto.subtlemocks - Use
vi.mock()for modules with side effects (storage, API calls)
Test patterns:
- State machine: deterministic transition testing
- Storage: real IndexedDB operations via fake-indexeddb
- AI engine: mock API responses, test extraction logic
- Pure functions: direct input/output assertions
- Test in Chrome, Firefox, and Edge
- Test the full recording flow (start → pause → resume → stop → upload)
- Verify cloud upload works with real credentials (Google Drive and/or OneDrive)
- Check different quality settings and long recordings
- Test error states (denied permissions, offline, expired token)
- Create a feature branch:
git checkout -b feature/your-feature - Make focused, atomic commits
- Update documentation if adding features
- Test thoroughly
- Submit PR with a clear description of what and why
- 🌐 Browser compatibility improvements
- 🎨 UI/UX enhancements
- 📊 Recording quality optimizations
- 🛡️ Error handling and resilience
- 📝 Documentation and examples
- ♿ Accessibility improvements
- 🌍 Internationalization
If you find security issues, email the maintainer directly instead of opening a public issue.
By contributing, your work is licensed under the same MIT license as the project.