A cross-platform Getting Things Done (GTD) app built with React Native, TypeScript, and Expo. All data is stored in JSON Lines (JSONL) format for maximum portability, sync capability, and crash safety.
The entire code, including the README.md files outside of this section, is AI generated. This is an experiment of mine to see how far I can get with AI tools. The code is specifically written in TypeScript because I have no prior experience in that language or ecosystem. It goes without saying that I do not recommend anyone to use this for any real scenario at this time.
Tools used:
- Claude Code
- GitHub Copilot (various models)
I switch tools when I run out of tokens on one. I switch models in Copilot for the same reason.
- ✅ JSON Lines Storage: Append-only JSONL format for data safety
- ✅ Cross-Platform: Runs on iOS, macOS, Linux, and web
- ✅ GTD Methodology: Follows David Allen's Getting Things Done system
- ✅ Hierarchical Tasks: Tasks can have subtasks (project breakdown)
- ✅ Multiple Contexts: Assign tasks to multiple contexts (@home, @computer, etc.)
- ✅ File-based Routing: Modern navigation with Expo Router
- ✅ TypeScript: Fully typed for better development experience
- ✅ Comprehensive Tests: 60+ unit tests with Vitest
- ✅ ESLint + Prettier: Code quality and formatting
- React Native 0.81 - Latest React Native version
- React 19.1 - Latest React version
- TypeScript 5.9 - Static typing with strict mode
- Expo 54 - Development and build tooling
- Expo Router 6 - File-based navigation (like Next.js)
- Expo File System - Local file storage for JSONL database
- Vitest 4 - Fast unit testing framework
- JSON Lines - Append-only data format
gtd/
├── app/ # Expo Router file-based routing
│ ├── _layout.tsx # Root layout
│ ├── index.tsx # Root redirect to tabs
│ └── (tabs)/ # Tab navigation
│ ├── _layout.tsx # Tabs layout
│ ├── index.tsx # Inbox screen
│ ├── tasks.tsx # All tasks (projects & actions)
│ └── more.tsx # More options screen
├── src/
│ ├── types/ # TypeScript type definitions
│ │ ├── gtd.ts # GTD domain types & helpers
│ │ └── gtd.test.ts # Type helper tests
│ ├── services/ # Business logic services
│ │ ├── jsonlStorage.ts # JSON Lines storage
│ │ └── jsonlStorage.test.ts # Storage tests
│ └── constants/ # App constants
│ └── storage.ts # Storage configuration
├── assets/ # Images, fonts, etc.
├── eslint.config.js # ESLint 9 flat config
├── vitest.config.ts # Vitest configuration
├── tsconfig.json # TypeScript configuration
└── package.json # Dependencies and scripts
All GTD data is stored in a single JSON Lines file for simplicity and safety:
gtd/
├── README.md # System overview
├── gtd.jsonl # Main database (all tasks & contexts)
├── backups/ # Automatic backups
│ └── gtd-YYYYMMDD.jsonl
├── reference/ # Supporting information
└── reviews/ # Weekly review notes
Each line in gtd.jsonl is a complete JSON object representing one entity:
{"type":"task","id":"task-1","title":"Write README","parentId":null,"contexts":["@computer"],"tags":["docs"],"status":"active"}
{"type":"task","id":"task-2","title":"Buy groceries","parentId":"__INBOX__","contexts":[],"tags":[],"status":"active"}
{"type":"context","id":"@computer","name":"Computer","icon":"💻"}
{"type":"context","id":"@home","name":"Home","icon":"🏠"}Task (GTDTask):
{
id: string; // Unique identifier
title: string; // Task title
description?: string; // Optional details
parentId?: string; // Parent task ID (null = root, __INBOX__ = inbox)
contexts: string[]; // Context IDs (e.g., ["@computer", "@home"])
tags?: string[]; // Optional tags
status: "active" | "completed" | "on_hold" | "cancelled";
}Context (GTDContext):
{
id: string; // Context ID (e.g., "@computer")
name: string; // Display name
icon?: string; // Optional emoji icon
}- New entities: Append new line
- Updates: Append new version (old kept for history)
- Deletes: Append tombstone marker (empty title)
- Compaction: Automatically removes old versions when file > 10MB
Benefits:
- ✅ Crash-safe (atomic appends)
- ✅ Built-in version history
- ✅ Easy to sync across devices
- ✅ Simple conflict resolution
- ✅ Works with standard Unix tools (grep, jq)
- Node.js 18+ installed
- npm or yarn
- iOS Simulator (for macOS) or Android Emulator
- Expo Go app (for testing on physical devices)
# Install dependencies
npm install
# Start the development server
npm start# iOS (macOS only)
npm run ios
# Android
npm run android
# Web (for testing)
npm run web# Type checking
npm run type-check
# Testing
npm test # Run tests in watch mode
npm run test:run # Run tests once (CI mode)
npm run test:ui # Open visual test UI
npm run test:coverage # Generate coverage report
# Linting
npm run lint
npm run lint:fix
# Formatting
npm run format
npm run format:checkThis app implements the five steps of GTD:
- Capture - Add items to your inbox
- Clarify - Process inbox items (coming soon)
- Organize - Move items to appropriate lists (coming soon)
- Reflect - Weekly review (coming soon)
- Engage - Do your next actions (coming soon)
- Data Model: Hierarchical tasks with multiple contexts
- Storage: JSON Lines format with append-only writes
- Inbox: Capture and view inbox items
- Tasks: Unified view of projects and actions
- Type System: Comprehensive TypeScript types with helper functions
- Testing: 60+ unit tests covering core functionality
- Navigation: Tab-based navigation with Expo Router
- Auto-compaction: Database optimization when > 10MB
- Context-based task filtering
- Task editing and completion
- Project breakdown UI
- Search and filtering
- Weekly Review
- Quick capture widget
- File sync configuration
- Dark mode
The JSONL database file can be synced across devices using:
- iCloud Drive - Built-in on Apple devices
- Syncthing - Open source, cross-platform sync
- Git - Version control (excellent for append-only format)
- Dropbox/Google Drive - Cloud storage
Sync-Friendly Design:
- Single file reduces sync conflicts
- Append-only format works well with file-based sync
- Automatic compaction keeps file size manageable
- Text format works with all sync tools
- Built-in version history via append-only writes
Recommended: Use Git for best version control and conflict resolution.
This is a personal learning project, but contributions and suggestions are welcome!
MIT License - feel free to use this code for your own projects.
- David Allen for the GTD methodology
- Expo team for excellent React Native tooling
- React Native community