Turn words found in real reading into a personal vocabulary library, graded AI stories, and a spaced-review routine.
简体中文 · Contributing · Supabase · Trusted server · App Store checklist
CiJing has four focused top-level areas. Home brings the daily plan, accumulated progress, persistent reading history, and real learning entry points together in one glance.
The top-level navigation stays simple, while each reading opens a focused sequence: choose target words, read with optional translations, practise retrieval, shadow sentence by sentence, review progress, and resume saved readings after relaunch.
- Captures words and source context from a Chrome Manifest V3 extension.
- Keeps a private, user-scoped word library with notes and learning states.
- Generates coherent bilingual readings from weak, due, and new words.
- Persists every generated reading to
reading_sessions, so history survives relaunches and sign-ins. - Schedules review with strength, ease factor, interval, lapse, and due-date signals.
- Provides system pronunciation, shadowing, and short reading-based exercises.
- Protects all user data with Supabase Row Level Security.
- Follows the system appearance before sign-in and for unset accounts; signed-in appearance and local learning switches are isolated by user UUID, and the App Icon includes light/dark system variants.
- Requires email verification for new accounts and rejects an unexpected session returned directly from sign-up.
.
├── client/ # SwiftUI iOS app
├── extension/ # Chrome extension for contextual lookup and saving
├── supabase/ # PostgreSQL migrations, RLS, RPCs, and Edge Functions
├── server/ # Trusted Flask boundary and health checks
├── scripts/ # Configuration, audit, and smoke-test utilities
├── docs/ # Policies, operations guides, model notes, and store assets
└── website/ # Privacy policy and support pages for public hosting
iOS app ─────┐
├─ Supabase Auth / PostgREST ── PostgreSQL + RLS + RPC
Chrome ──────┘ └────────── Edge Functions ── OpenRouter / Qwen
Physical iPhone ── local Flask integration gateway ── hosted Supabase
Flask server ── trusted health and operations boundary
The iOS app and extension share a Supabase account and user-scoped learning data. Every business table has Row Level Security, and database functions execute in the authenticated user's scope. During physical-device testing, iOS Auth, PostgREST, and Edge Functions requests pass through the local Flask gateway before reaching hosted Supabase; the Chrome extension continues to call hosted Supabase directly. The gateway preserves the user's access token and RLS boundary and never injects a server secret into client requests.
The root .env is the only local configuration source. Generated iOS and extension configuration is ignored by Git. Client bundles contain only the Supabase URL and publishable key; Supabase secret keys and the OpenRouter API key stay in trusted runtimes. See Supabase architecture and operations and the trusted server guide for component details.
Requirements: macOS, Xcode 16 or newer, Node.js 20+, Docker Desktop, and Chrome. The repository wrapper downloads and caches its pinned Supabase CLI version on first use.
cp .env.example .env
# Fill the environment values in .env
make config
./scripts/supabase.sh start
./scripts/supabase.sh db reset
make functionsOpen client/CiJing.xcodeproj, select the CiJing scheme and an iOS 17+ simulator, then run. Load extension/ as an unpacked extension from chrome://extensions.
Configuration, database, Edge Function, and production instructions live in supabase/README.md. Contribution workflow and physical-device troubleshooting live in CONTRIBUTING.md.
Once the iPhone has a device-integration build generated with make device-config and rebuilt in Xcode, routine local testing only requires this command from the repository root:
make server-startKeep that terminal running and keep the iPhone and Mac on the same LAN. The device uses the Mac's Bonjour .local hostname, so a Wi-Fi IP change does not require regenerating configuration. For the first device setup, after switching back from release configuration, or after generated files were cleaned, run make device-config first and rebuild/reinstall the app in Xcode; starting Flask alone cannot change the URL embedded in an installed app.
Before creating an Archive, TestFlight build, or App Store build, verify that SUPABASE_URL in the root .env is the hosted production HTTPS URL, then run:
make config
make config-checkmake device-config never changes the root .env, so make config restores the iOS client to the hosted URL from .env; make config-check verifies that generated files match it. Rebuild the Archive after both commands succeed—do not reuse a local device build that points to Flask. The release app does not require the local Flask server.
make config-check
make extension-test
make server-test
make ios-buildWith Supabase running, make smoke verifies the cross-client API flow. Production environments can use make production-audit and make production-smoke after deployment.
- Supabase architecture, local development, and production operations
- Database migration guide and Qwen3.6 Flash integration
- Trusted Flask server and public website
- Privacy policy, terms of service, and support
Please read CONTRIBUTING.md and CODE_OF_CONDUCT.md before opening a contribution. Report vulnerabilities privately by following SECURITY.md, not through a public issue.
This project is available under the MIT License.








