Warning
This repo is in development and is NOT considered prodution ready.
A personal CRM for maintaining meaningful relationships. Built with Elixir, Phoenix LiveView, and PostgreSQL.
Kith helps you keep track of the people who matter most — their birthdays, how you met, conversations you've had, gifts you've exchanged, and when you last reached out. Think of it as a personal relationship manager that respects your privacy and runs entirely on your own infrastructure.
- Contact management — addresses, tags, notes, custom fields, relationships, pets, and more
- Activities and life events — track calls, meetings, and milestones
- Conversations and journal — log interactions and personal reflections
- Reminders — birthday alerts, stay-in-touch nudges, and recurring reminders
- Photo sync — read-only integration with Immich photo servers
- Import/export — vCard and Monica CRM import support
- CardDAV/CalDAV — sync contacts with your phone or email client
- REST API — bearer token auth, cursor pagination, compound documents
- Multi-account — account-scoped multitenancy with full data isolation
- Background jobs — powered by Oban with 9 queues and nightly cron tasks
- Security — WebAuthn/passkeys, TOTP 2FA, OAuth (GitHub, Google), encrypted sensitive fields
- Erlang 26+ and Elixir 1.15+
- PostgreSQL 15+
- Node.js 18+ (for asset compilation and Playwright tests)
-
Clone the repo
git clone https://github.com/yourusername/kith.git cd kith -
Copy the environment file
cp .env.example .env chmod 600 .env
Edit
.envand fill in at minimum:SECRET_KEY_BASE— generate withmix phx.gen.secretDATABASE_URL— your local PostgreSQL connection string (e.g.,ecto://postgres:postgres@localhost:5432/kith_dev)CLOAK_KEY— generate a 32-byte base64 key:openssl rand -base64 32
-
Install dependencies and set up the database
mix setup
This runs
deps.get,ecto.setup(create + migrate + seed),assets.setup, andassets.build. -
Start the dev server
mix phx.server
Or with an interactive Elixir shell:
iex -S mix phx.server
Visit localhost:4000 in your browser.
For production or isolated local development, Docker Compose files are provided:
# Development
docker compose -f docker-compose.dev.yml up
# Production
docker compose -f docker-compose.prod.yml up -d# All tests
mix test
# Single file or line
mix test test/path/to_test.exs
mix test test/path/to_test.exs:42
# Playwright E2E (requires a running server in another terminal)
mix phx.server # Terminal 1
npx playwright test --project=e2e # Terminal 2
# Browser tests with Wallaby
WALLABY=1 mix test --only wallaby| Tag | Purpose | How to run |
|---|---|---|
:integration |
DB-touching tests (most tests) | mix test (default) |
:external |
Hits real APIs (Immich, LocationIQ) | EXTERNAL_TESTS=true mix test --only external |
:wallaby |
Browser E2E via Wallaby | WALLABY=1 mix test --only wallaby |
:slow |
Large dataset performance tests | mix test --only slow |
mix format # Format code
mix compile --warnings-as-errors # Strict compilation
mix precommit # All checks: compile + format + testlib/kith/ # Domain layer — contexts and schemas
lib/kith_web/ # Web layer — LiveView, controllers, components
config/ # Environment configs (dev/test/prod/runtime)
priv/repo/ # Ecto migrations
test/ # ExUnit tests
test/playwright/ # Playwright E2E specs
Key architectural decisions are documented in docs/adr/.
See .env.example for the full list. Key variables:
| Variable | Required | Description |
|---|---|---|
SECRET_KEY_BASE |
Yes | Phoenix secret key |
DATABASE_URL |
Yes | PostgreSQL connection string |
CLOAK_KEY |
Yes | Encryption key for sensitive data |
KITH_HOSTNAME |
No | Hostname for URL generation (default: localhost) |
KITH_MODE |
No | web (full app) or worker (Oban only) |
MAILER_ADAPTER |
No | smtp, mailgun, ses, or postmark |
IMMICH_ENABLED |
No | Enable Immich photo sync integration |