Thanks for wanting to contribute to Kaneo! Whether you're fixing bugs, adding features, or improving docs, we appreciate your help.
We want everyone to feel welcome here. Please be respectful and follow our Code of Conduct.
- Node.js (18 or newer)
- pnpm (we use this instead of npm/yarn)
- Git
- Docker (optional, for testing full deployments)
- Fork and clone the repo:
git clone https://github.com/yourusername/kaneo.git
cd kaneo- Install dependencies:
pnpm install-
Set up environment variables: Create
.envfiles for both the API and web apps. See ENVIRONMENT_SETUP.md for detailed instructions on all required environment variables. -
Start everything up:
pnpm run devThis starts both the API (port 1337) and web app (port 5173). Both will automatically reload when you make changes.
Tip: The web app at http://localhost:5173 will automatically connect to the API at http://localhost:1337
Need help with setup? See our Environment Setup Guide for detailed instructions and troubleshooting tips.
- Browse open issues - look for "good first issue" labels
- Check our Discord - we often discuss features and bugs there
- Found a bug? Feel free to fix it and open a PR
- Create a branch for your work:
git checkout -b fix/whatever-youre-fixing
# or
git checkout -b feat/cool-new-feature-
Make your changes and test them locally (
pnpm testfor unit tests;pnpm test:integrationfor API integration tests with PostgreSQL) -
Commit using conventional commits:
git commit -m "fix: resolve calendar date selection bug"
git commit -m "feat: add bulk task operations"
git commit -m "docs: update deployment guide"- Push and create a PR:
git push origin your-branch-nameThen open a pull request on GitHub with a clear description of what you changed and why.
We use Biome for formatting and linting. Before you commit:
pnpm run lintThis will check and automatically fix formatting issues. Most editors can auto-format on save if you install the Biome extension.
We use conventional commits to keep our history clean:
feat:- New featuresfix:- Bug fixesdocs:- Documentation changesrefactor:- Code changes that don't add features or fix bugstest:- Adding or updating testschore:- Maintenance tasks
Kaneo uses i18next with react-i18next in the web app. We want user-facing copy to stay consistent, translatable, and easy to maintain.
- Use translation keys for all user-facing strings instead of hardcoded copy
- In React components, call
t("namespace:key.path")fromuseTranslation() - Translation files live in
i18n/and use locale-style filenames such asen-US.jsonandde-DE.json i18n/en-US.jsonis the source of truth for translation keys- Locale selection comes from the signed-in user's saved preference when available, otherwise from the browser locale
The root package.json includes scripts to keep locale files in sync:
| Command | Description |
|---|---|
pnpm i18n:check [locale] |
Compares en-US.json with the other locale files and reports missing or extra keys. You can filter by locale, for example pnpm i18n:check de-DE. |
pnpm i18n:check:fix [locale] |
Adds missing keys to other locale files using the English source text from en-US.json. |
pnpm i18n:report |
Scans .ts and .tsx files in the React app and reports missing keys, unused locale keys, and dynamic translation calls that static analysis cannot verify. |
pnpm i18n:report:fix |
Removes unused keys from en-US.json and the other locale files. |
pnpm i18n:schema |
Generates i18n/schema.json from en-US.json for editor and tooling validation. |
- Create a new file in
i18n/using a locale code filename such asfr-FR.json. - Copy
i18n/en-US.jsonand translate the values. - Register the locale in
i18n/resources.tsby updatingsupportedLocalesandresources. - If the locale should be selectable in the UI, add it to the language picker in
apps/web/src/routes/_layout/_authenticated/dashboard/settings/account/preferences.tsx. - Run
pnpm i18n:check,pnpm i18n:report, andpnpm i18n:schemabefore opening your PR.
- Add the new key to
i18n/en-US.jsonfirst. - Use it in code with a static key:
const { t } = useTranslation();
return <p>{t("common:actions.close")}</p>;- Use interpolation for dynamic values instead of concatenating translated strings:
t("projects:greeting", { name: userName });- Keep translation keys static. Calls like
t(someVariable)ort(`tasks:${key}`)cannot be validated by the i18n report and will be flagged.
- Use namespaces at the top level such as
common,settings, andtasks - Use dot notation inside each namespace, for example
settings.preferencesPage.title - Keep keys descriptive and stable
- Put widely shared labels in
common - Group feature-specific keys under the feature or component they belong to
- If you change UI copy, update the locale files in the same PR
- If you remove or rename translation keys, run
pnpm i18n:report:fixto keep locale files clean - If a locale is not fully translated yet, leaving the English source text as a placeholder is fine
kaneo/
├── apps/
│ ├── api/ # Backend API (Node.js/Hono)
│ ├── docs/ # Documentation site (Next.js)
│ └── web/ # Frontend app (React/Vite)
├── packages/ # Shared code and configs
└── charts/ # Kubernetes Helm charts
- Discord: Join our Discord server for real-time help
- Issues: Open a GitHub issue for bugs or feature requests
- Discussions: Use GitHub Discussions for questions about contributing
- Bug fixes - Found something broken? Fix it!
- New features - Have an idea? Let's discuss it first
- Documentation - Help others understand how to use Kaneo
- Performance improvements - Make things faster
- Accessibility - Help make Kaneo usable for everyone
Thanks for contributing to Kaneo! 🚀