English • Русский • Беларуская
Journal for your child's life
Photos, videos, moments — stored in your Immich. Journal syncs via Supabase.
Screenshots • Features • Quick Start • Setup • License
- Self-hosted — photos in your Immich, data in your Supabase
- Family sharing — invite household members, share children and entries
- EXIF magic — date and location auto-filled from photo metadata
- AI descriptions — generate journal text from photos (OpenAI, Gemini, Claude, or DeepSeek with on-device labels); see docs/ai-providers.md
- Offline-ready — cached journal list when offline
- Batch import — add many photos at once
flutter pub get
flutter run --dart-define-from-file=.envSee Setup for Supabase and Immich configuration.
This section provides a full technical and functional overview for AI assistants working with the codebase.
MyKid is a Flutter (Dart) mobile app for parents to keep a journal of their child's life. Each journal entry can contain: date, text description, place (location), photos/videos (stored as references to Immich assets), and an optional link to a child profile.
- Backend: Supabase (auth, Postgres) — journal entries and children profiles.
- Media: Immich — all photos/videos are uploaded to the user's own Immich instance; only asset IDs are stored in Supabase.
- Offline: Hive cache for journal list when offline; pull-to-refresh to sync when back online.
- Flutter (Dart)
- Supabase (auth, PostgREST)
- Immich (self-hosted photo server; REST API)
- Hive (local cache)
- image_picker, file_picker, exif, geocoding, cached_network_image, share_plus, path_provider
- AI (optional): user API keys for OpenAI, Gemini, Claude, DeepSeek; http for API calls; google_mlkit_image_labeling for DeepSeek path (on-device labels → text prompt)
Children (children table): id, user_id, name, date_of_birth, immich_album_id (optional; album created in Immich for this child).
Journal entries (journal_entries table): id, user_id, date, text, assets (JSONB array of {immichAssetId, caption?}), child_id (optional FK to children), location (optional text), created_at, updated_at.
RLS: users can access only their own rows.
-
Auth
- Supabase Auth (email/password). AuthGuard redirects to LoginScreen if not authenticated.
- Login, signup, sign out. Session persists.
-
Journal list (
JournalListScreen, route/)- Lists all entries (from Supabase), ordered by date descending.
- Pull-to-refresh; on network error falls back to Hive cache.
- FAB: create entry via modal: From camera | From gallery | Empty entry.
- From camera: take photo → upload to Immich → open new entry with today's date, no location.
- From gallery: pick one photo → read EXIF (date, GPS → reverse geocode for place) → upload to Immich → open new entry with inferred date/location.
- Empty entry: open new entry with today, no assets.
- AppBar: batch import button, settings button.
- Tap entry → open
JournalEntryScreen.
-
Journal entry (
JournalEntryScreen)- View mode (default for existing entries): large photo preview, swipe between photos, tap photo → fullscreen with Share/Back. Edit button to switch to edit mode.
- Edit mode: date picker, child selector (ChoiceChips), place field, description text, photo grid. Add photos (camera/gallery) → upload to Immich → add to entry; optionally add to selected child's Immich album.
- Generate description: button sends first photo to selected AI provider (OpenAI/Gemini/Claude vision, or DeepSeek via on-device ML Kit labels + text API) and fills description field. Configure in Settings → AI providers.
- When child is selected and photos are added, app creates Immich album "MyKid: {name}" for the child (if needed) and adds assets to it.
- Save creates/updates entry in Supabase. Delete: optionally remove photos from child's Immich album.
- New entries open in edit mode; existing ones open in view mode.
-
Children (Settings → Manage children, route
/children)- List, add, edit, delete child profiles (name, date of birth).
- Children used in journal entries to link entries to a child and to organize photos in Immich albums per child.
- Age displayed as "X лет Y мес Z дн" (Russian) or similar.
-
Batch import (route
/import)- Pick multiple photos/videos (FilePicker) → upload all to Immich → create one journal entry with all assets.
- Opens
JournalEntryScreenin create mode.
-
Settings (route
/settings)- AI providers (route
/settings-ai-providers): API keys for OpenAI, Gemini, Claude, DeepSeek; select default provider for "Generate description" in journal entries. - Immich: server URL and API key; Test connection (saves on success).
- Link to Manage children, Family invites.
- Legal: Privacy Policy, Terms of Use, Support, Open Source Licenses (App Store / Google Play compliance).
- Account: Export my data (GDPR), Delete account, Sign out.
- AI providers (route
lib/core/: config (Supabase URL/key), ImmichClient/ImmichService/ImmichStorage, photo_metadata (EXIF date/GPS→place), ai_provider_storage (API keys + selected provider), ai_vision_service (Vision / DeepSeek text), on_device_image_labels (ML Kit labels for DeepSeek on Android/iOS).lib/data/: Child, JournalEntry, JournalEntryAsset; JournalRepository (Supabase CRUD), ChildrenRepository; JournalCache (Hive).lib/features/auth/: AuthGuard, LoginScreen, SignUpScreen.lib/features/journal/: JournalListScreen, JournalEntryScreen.lib/features/children/: ChildrenListScreen, ChildEditScreen.lib/features/import/: BatchImportScreen.lib/features/settings/: SettingsScreen, AiProviderSettingsScreen.
/— journal list (guarded)/login— login/signup— signup/settings— settings/settings-ai-providers— AI provider API keys and default provider/children— children list/import— batch import
SUPABASE_URL,SUPABASE_ANON_KEY— from.envor--dart-define-from-file=.env.
- Flutter SDK (stable)
- Android Studio / Xcode for running on device or simulator
- Supabase project (free tier is enough)
- Your own Immich instance or public Immich server
Create a .env or use --dart-define so the app can reach Supabase. Do not commit real keys.
SUPABASE_URL— your Supabase project URL (e.g.https://xxxx.supabase.co)SUPABASE_ANON_KEY— Supabase anonymous (public) key
Example .env.example:
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-anon-keyThe app also supports loading these from a config file or build-time defines; see lib/core/config.dart.
- Create a project at supabase.com.
- Apply the schema: in Supabase Dashboard → SQL Editor run docs/full_schema.sql.
- In Supabase Dashboard → Authentication → enable Email (or other providers you want).
Table journal_entries and API are described in docs/backend.md.
In the app: Settings → Immich: set your Immich server URL and API key (create the key in your Immich instance). All photo/video uploads and thumbnails use this connection.
To use "Generate description" in journal entries, go to Settings → AI providers: add one or more API keys (OpenAI, Gemini, Claude, DeepSeek) and select the default provider. Keys are stored only on device. See docs/ai-providers.md for details and how DeepSeek uses on-device labels.
Copy .env.example to .env, fill in your Supabase URL and anon key, then:
flutter pub get
flutter run --dart-define-from-file=.envOr pass defines explicitly:
flutter run --dart-define=SUPABASE_URL=https://your-project.supabase.co --dart-define=SUPABASE_ANON_KEY=your-anon-key(Use an Android device/emulator first; iOS requires a Mac and proper signing. If the ios/ folder is incomplete, run flutter create . to regenerate platform files; camera/photo usage descriptions are already in ios/Runner/Info.plist.)
When the app cannot reach Supabase, the journal list falls back to the last cached entries (Hive). After going back online, pull-to-refresh to sync again.
lib/— Flutter appmain.dart— entry, Supabase init, Hive cache initcore/— config, Immich client, secure storage, AI provider storage & vision service, on-device image labels (ML Kit)data/— models, Supabase repository, local cache (Hive)features/— auth, journal list/detail, settings, AI provider settings, batch import
docs/— full_schema.sql (apply once in SQL Editor), backend.md (schema, API), ai-providers.md, immich-api.md, edge-function-setup.md
For store compliance, the app includes links to Privacy Policy, Terms of Use, Support, Account Deletion, and Data Export. Configure in .env:
PRIVACY_POLICY_URL=https://scroodge.github.io/MyKid/privacy.html
TERMS_OF_SERVICE_URL=https://scroodge.github.io/MyKid/terms.html
SUPPORT_URL=mailto:scroodgemac@gmail.com
ACCOUNT_DELETION_URL=mailto:scroodgemac@gmail.com?subject=Account%20Deletion%20Request
DATA_EXPORT_URL=mailto:scroodgemac@gmail.com?subject=Data%20Export%20Request
SOURCE_CODE_URL=https://github.com/scroodge/MyKid
SPONSOR_URL=https://github.com/sponsors/scroodge
Or use --dart-define=PRIVACY_POLICY_URL=... etc. when building.
The app calls the delete-account Edge Function, which removes the user and cascades to children, journal entries, household data. Deploy:
supabase functions deploy delete-accountRegenerate lib/oss_licenses.dart after changing pubspec.yaml dependencies:
dart run dart_pubspec_licenses:generateThanks to everyone who contributes to MyKid. See CONTRIBUTING.md for how to get involved.
If you find MyKid useful, consider supporting its development:
- GitHub Sponsors
- Or spread the word and star the repo







