Skip to content

architecture

github-actions[bot] edited this page Sep 16, 2026 · 11 revisions

Architecture

GitNotēs project structure, tech stack, data flow, and key modules. For detailed service docs see Services. For sync internals see Sync Architecture.

What is GitNotēs?

GitNotēs is a mobile notes/todos/canvases app backed by a Git repository (GitHub, GitLab, Gitea). Notes are plain Markdown/Neorg/Org/JSON files with YAML frontmatter — no database lock-in, full version history, works offline.

Core promise: Your data is in a git repo you own. Export by cloning. Edit with any text editor. Sync anywhere.

Local-first note storage: Notes are files on disk with YAML-ish frontmatter (--- block). A SQLite index (DocumentIndex) mirrors metadata for fast listing/search, but the file is always the source of truth. See Note File Format for full details.


Tech Stack

Framework & Runtime

Layer Technology
Framework Expo SDK 56
Runtime React Native 0.85.3
Language TypeScript 6 (strict mode, no any without justification)
Package manager Yarn 1.22
Node engine >= 20.18

Navigation

Technology Purpose
React Navigation v7 (@react-navigation/native, native-stack, bottom-tabs) Root native stack + bottom tabs
Deep linking gitnotes:// custom scheme

State Management

Technology Purpose
Zustand v5 All client state — notes, todos, canvases, repos, AI chat, Pro status, theme
React Context Auth, accounts, theme, view mode (wraps Zustand)
TanStack Query v5 Server state — git host API calls, GitHub GraphQL

Styling & UI

Technology Purpose
NativeWind v5 Tailwind CSS for React Native
Reanimated v4 Animations, gestures, shared transitions
FlashList v2 Performant list rendering
Expo Blur Frosted glass effects in Neumorphic UI
React Native Skia Canvas rendering (tiles, shapes)

Git

Technology Purpose
gitnotes-git-engine Custom Rust library (git2-based) — clone, stage, commit, push, pull
Turbo Modules (New Architecture) JS↔Rust bindings

AI

Technology Purpose
Vercel AI SDK v6 Provider abstraction (Anthropic, OpenAI, Apple Intelligence, Llama)
@react-native-ai/llama On-device Llama for offline AI
@react-native-ai/apple Apple Intelligence integration

Storage & Sync

Technology Purpose
AsyncStorage Local key-value storage
Expo Secure Store Auth tokens
Expo File System Working tree files
Expo SQLite Local document metadata and FTS5 body index

Platform Services

Technology Purpose
Expo Notifications Local + push notifications
Expo Background Task Background sync
Expo Local Authentication Biometric lock
Expo Document Picker Import files
RevenueCat / StoreKit 2 Pro subscription purchases
i18next Internationalization (EN, ES, FR, DE, JA, KO)

Build & Deploy

Technology Purpose
EAS Build / Expo Run Native iOS/Android builds
EAS Update Over-the-air JS updates
GitHub Actions CI + Wiki sync

Project Structure

gitnotes/
├── src/
│   ├── components/          # Reusable UI components
│   │   ├── ai/             # AI chat components (bubbles, input, provider picker)
│   │   ├── editor/         # Note editor components (toolbar, viewer, backlinks)
│   │   ├── git/            # Floating git button, sync progress
│   │   ├── home/           # Bento grid, daily quote
│   │   ├── notes/          # Note cards, filters, list header
│   │   ├── paywall/        # Paywall plan grid, feature grid
│   │   ├── repo/           # Repo tree, file browser
│   │   ├── settings/       # Settings modals, clone progress
│   │   ├── todos/          # Todo cards, editor modal
│   │   └── ...
│   ├── contexts/           # React Context providers (14 contexts)
│   ├── data/               # Static data (philosopher quotes JSON)
│   ├── hooks/              # Custom React hooks (25 hooks)
│   ├── i18n/               # i18n translations (6 languages)
│   ├── lib/                # Shared utilities — `cn()` (clsx + tailwind-merge for Tailwind class composition) |
│   ├── models/             # TypeScript interfaces (14 models)
│   ├── navigation/         # AppNavigator + TabNavigator
│   ├── screens/            # Screen components (30+ screens)
│   ├── services/           # Business logic (100+ service files)
│   │   ├── git/            # Git host services, commit ops, sync gate
│   │   ├── canvas/         # Sparse tile canvas, AI vision
│   │   ├── documents/      # Document service, working tree
│   │   ├── git/engine/GitEngine.ts  # Rust GitEngine TypeScript facade
│   ├── stores/             # Zustand stores (20 stores)
│   ├── theme/              # NativeWind theme, color tokens
│   └── types/              # Shared type definitions
├── modules/
│   └── GitEngine/           # Rust crate (git2-based native Git module)
│       ├── src/lib.rs
│       └── Cargo.toml
├── docs/wiki/               # THIS WIKI — source-controlled, auto-synced
├── scripts/                 # Build scripts (Rust build, asset regeneration)
├── __tests__/               # Jest tests
└── .github/workflows/       # CI + Wiki sync

Data Flow

Note Save → Sync (Clone Mode)

User edits note
  → NoteEditorScreen.save()
    → noteStore.updateNote()
      → CloneSyncService.save({ intent: 'upsert', content, filePath, ... })
        → FileSystem.writeAsStringAsync(fullPath, content)
          → User stages and commits from the Git workspace or floating Git button
      → ForegroundSyncService / BackgroundSyncService triggers push
        → GitEngine.push(repoDir, 'origin', branch)
          → 409 Conflict → ConflictResolverScreen

Note: CloneSyncService.save() writes the working-tree file without staging it. Users stage and commit from the Git workspace or floating Git button, then push through the normal clone-mode triggers. See Sync Architecture for full push trigger details.

Note Load

User opens NotesListScreen
  → noteStore.loadNotes()
    → DocumentIndex.scan(repoDir)        # Walk working tree
      → DocumentService.readNote(filePath)  # Read + parse .md files
        → noteStore.setNotes(notes)

AI Chat

User sends message in ChatScreen
  → chatStore.sendMessage()
    → aiStore.provider.chat()              # Vercel AI SDK call
      → Render streamed response
        → chatStore.appendMessage()
          → ChatStorageService.persist()  # Save to AsyncStorage

Navigation

AppNavigator (src/navigation/AppNavigator.tsx)

Root native stack. Handles:

  • Deep linking (gitnotes:// scheme)
  • Onboarding flow
  • Deferred paywall interstitial
  • Floating overlays (AI button, git button)

TabNavigator (src/navigation/TabNavigator.tsx)

Bottom tab bar with 5 tabs: Home, Notes, Explore, Todos, Settings.

Three tab bar variants:

  • Neumorphic (iPhone, flat style off) — raised button look
  • Flat (iPhone, flat style on) — standard iOS tab bar
  • Tablet rail (iPad) — horizontal rail along the side

Theme System

Two styles, each with light + dark:

Style Description
neumorphic Soft "pressed clay" look — light gray surface, off-white background, subtle shadows
flat Standard iOS look — system colors, clean

Color tokens (defined in src/theme/tokens.ts): bg, surface, highlight, shadow, text, textSecondary, accent, accentMuted, error, success, warning, background, surfaceSecondary, primary, border, card, elevated

Note color palette (user-assignable labels, not theme-aware): red, orange, yellow, green, blue, purple, pink, gray


Sync Architecture

GitNotēs uses clone mode: local git working tree with commit-on-save and write-through push. See Sync Architecture for full details.


Pro / Paywall

GitNotēs Pro is powered by RevenueCat with StoreKit 2 on iOS.

  • Entitlement ID: GitNotēs Pro
  • Packages: Monthly, Yearly, Lifetime (configurable in RevenueCat dashboard)
  • Feature gates: useProGate(), useProScreenGuard()
  • Simulator override: EXPO_PUBLIC_FORCE_ENABLE_PRO_ON_SIMULATOR env var

See Paywall & Pro Tier for full details.


i18n

Six languages: English, Spanish, French, German, Japanese, Korean.

Translation files in src/i18n/. i18next framework. User preference stored in AsyncStorage.


Key Conventions

Convention Rule
TypeScript Strict mode — no any without justification
State Zustand for all client state; React Context only for auth/theme
Services Single-responsibility; all business logic in src/services/
Git worktrees All agent work in .worktrees/<branch> — never edit main directly
Tests Jest; new features get __tests__/ mirrors of src/ structure
Commits Conventional Commits (feat:, fix:, docs:, etc.)
Lint ESLint + Prettier; lint-staged on pre-commit

See Also

Clone this wiki locally