Thank you for your interest in contributing to Roots! This document provides guidelines and information to help you get started.
- Node.js 18+ (20+ recommended)
- npm 9+
git clone https://github.com/AbdAsh/FamilyTreeVisualizer.git
cd FamilyTreeVisualizer
npm install
npm run devThe dev server starts at http://localhost:5173.
| Command | Description |
|---|---|
npm run dev |
Start the development server |
npm run build |
Type-check and build for production |
npm run preview |
Preview the production build |
npm run typecheck |
Run TypeScript compiler (no emit) |
Roots is a zero-backend, client-only SPA. There is no database, no server, no accounts. The entire family tree is encrypted, compressed, and stored in the URL hash.
src/
├── app/ → Root component (App.tsx)
├── components/ → React components (editor/, tree/, ui/)
├── hooks/ → Zustand stores and custom hooks
├── lib/ → Core logic (crypto, compression, layout, i18n)
├── styles/ → Tailwind v4 theme
└── types/ → TypeScript type definitions
Path alias: @/ resolves to src/.
- All application state lives in Zustand stores (
useTree.ts,useAuth.ts). - Always call
pushSnapshot()before mutating the tree so undo/redo stays consistent. - Never mutate state directly — always use the store's action functions.
- Strict mode is enabled with
noUnusedLocalsandnoUnusedParameters. - All data structures are defined in
src/types/family.tsand validated with Zod schemas insrc/lib/validation.ts. - Use the
@/path alias for imports fromsrc/.
- Tailwind CSS v4 utility classes only — no CSS modules.
- The colour palette is defined as
@themecustom properties insrc/styles/globals.css. - Fonts: Playfair Display (headings), DM Sans (body).
- Icons: lucide-react exclusively.
The app supports three locales: English (en), Arabic (ar, RTL), and Turkish (tr).
- All UI strings are defined in the
Translationsinterface insrc/lib/i18n.tsx. - New strings must be added to all three locale objects — TypeScript will error if any locale is missing a key.
- Interpolation:
t(template, { key: value })for{key}placeholders. - Plurals:
tPlural(template, count)— templates use||separator:"{count} member||{count} members".
- Reusable UI primitives live in
src/components/ui/— prefer reusingButton,Input,Select,Modal,Panel, etc. - Animation: Framer Motion for panels/modals; CSS keyframes for subtle effects.
from= parent,to= child forparent-childrelationships.- Spouse and sibling relationships are symmetric but stored with a canonical direction.
hasDuplicate()inuseTree.tschecks both directions.
- Run
npm run build— this type-checks the entire project and builds for production. There should be zero errors. - Test your changes in the browser — create a tree, add members, verify the feature works.
- Check that the URL-based save/load cycle works (lock → unlock with same passphrase).
- Fork the repository and create a feature branch from
main. - Make your changes with clear, descriptive commit messages.
- Ensure
npm run buildpasses with no errors. - Open a pull request describing:
- What the change does
- Why it's needed
- Any trade-offs or limitations
- URL size limit: ~8 KB max. Be mindful when adding fields to
FamilyMember— every byte counts after compression + encryption. - No server dependencies: Everything must work client-side only.
- Brotli WASM is excluded from Vite's
optimizeDeps— don't change this.
Use GitHub Issues to report bugs or suggest features. For security vulnerabilities, see SECURITY.md.
This project follows the Contributor Covenant Code of Conduct. By participating, you agree to uphold this code.
By contributing, you agree that your contributions will be licensed under the Apache License 2.0.