Canonical Flutter mobile controller and library app for FF1 and The Digital Art System.
This repository is the canonical source for the Feral File mobile app. The app is a Band 4 presentation surface in the broader Feral File stack: it browses DP-1 Channels, Playlists, and Works, helps users build a personal collection, pairs and controls FF1 devices, and sends play and control requests into the rest of the system.
FF1is the art computer that plays art on a screen.FFPis the reference panel for the full system experience.- This mobile app is the handheld setup, library, and remote-control surface.
- The app consumes discovery, indexing, and device-control services, but it does not own publication backoffice, device runtime, or private operational policy.
In product terms: FF1 is the engine, the mobile app is setup plus remote control plus library, and DP-1 is the compatibility layer that keeps Channels, Playlists, and Works portable.
- Domain vocabulary is locked to
Channel,Playlist, andWork. - The app is offline-first: a local seed database is the default read path.
- The app focuses on browsing, personal collection, pairing, and playback control.
- Exhibitions and programs are expressed through channel and playlist presentation, not new protocol object types.
This repo is prepared to be the public, canonical app repository.
- Public here: Flutter source, tests, public contributor docs, example configuration, and CI workflows.
- Not public here: secrets, production credentials, private strategy docs, unpublished operational runbooks, or internal service data.
- If a change depends on private infrastructure, document the interface and expected contract without committing secret values or private documents.
- Flutter stable
- Xcode for iOS builds
- Android Studio and Android SDK for Android builds
- Optional FF1 hardware for end-to-end pairing and playback checks
git clone https://github.com/feral-file/ff-app.git
cd ff-app
cp .env.example .env
flutter pub getRun the app:
# Android (development flavor)
flutter run --flavor development
# iOS
flutter runFor iOS CocoaPods setup:
cd ios
pod install --repo-update
cd ..Copy .env.example to .env and fill only the values needed for your workflow.
Required for app startup:
INDEXER_API_URLINDEXER_API_KEYFF1_RELAYER_URLFF1_RELAYER_API_KEY
Optional runtime integrations:
DP1_FEED_URLandDP1_FEED_API_KEYfor feed-backed or integration flowsDOMAIN_RESOLVER_URLandDOMAIN_RESOLVER_API_KEYfor ENS and TNS resolutionREMOTE_CONFIG_URLto override the default remote-config documentRELEASE_NOTES_MARKDOWN_URLorPUBDOC_URLto load release notesFERALFILE_DOCS_URLto override the default public legal-docs baseSUPPORT_API_KEY,SENTRY_DSN,ASSET_URL,INDEXER_ENRICHMENT_MAX_THREADS
Integration and seed-database tests:
S3_BUCKETS3_ACCESS_KEY_IDS3_SECRET_ACCESS_KEYS3_REGIONS3_SEED_DATABASE_OBJECT_KEY
If the required startup keys are missing, the app will show a configuration error screen instead of booting into a broken state.
Use the CI-aligned verification path before opening a pull request:
./scripts/verify_ci.shThat script is non-mutating except for standard dependency/cache updates and coverage output. It runs:
flutter pub getflutter analyzedart format --output=none --set-exit-if-changed lib testdart run custom_lintwhencustom_lint.yamlexistsflutter test --coverage
GitHub Actions reuses the same script for Flutter static checks and unit coverage. For narrower local loops or CI changed-file static checks, the same entrypoint supports:
./scripts/verify_ci.sh --static-only
./scripts/verify_ci.sh --static-only --changed-static origin/main
./scripts/verify_ci.sh --tests-onlyChanged-file static mode falls back to full static checks when analyzer or package config changes, because those files can change diagnostics outside the touched Dart files.
For a quick public setup smoke check, run:
./scripts/verify_local_setup.shThat script runs:
flutter pub getflutter test test/unit/infra/services/release_notes_service_test.dart
It is intentionally a lightweight smoke test for public contributors: dependency resolution plus a public-safe unit-test path that does not require private credentials or hardware.
Hardware-dependent FF1 flows, S3-backed seed tests, and broader integration checks need additional environment variables and are not part of the default public setup verification.
Pull requests run compact checks that mirror the local verification path where practical:
Run unit tests: creates.envfrom repository secrets, runs./scripts/verify_ci.sh --tests-only, reports coverage, and uploadscoverage/lcov.info.Lint the code: creates.envfrom repository secrets and runs the shared script in changed-file static mode; separate jobs run gitleaks and dotenv-linter. This preserves the existing PR lint scope while making the command non-mutating.
Heavier workflows are intentionally separate from the default local gate:
Nightly integrationrunsflutter test test/integration --concurrency=1with private integration configuration.Gold Path UI Testruns FF1/hardware-oriented patrol checks on self-hosted infrastructure.- Release and database snapshot workflows are manual operational workflows, not contributor verification gates.
- Keep terminology aligned with
Channel,Playlist, andWork. - Keep changes scoped; this repo is the canonical mobile app repo, not a place for speculative system rewrites.
- Add or update tests for behavior changes.
- Keep
README.mdand.env.examplein sync when setup or configuration changes. - Do not commit
.env, secrets, private planning docs, or generated artifacts. - Use the GitHub issue and pull-request templates when opening work.
See CONTRIBUTING.md for the lightweight contributor checklist.
- display-protocol/dp1 for the protocol and schemas
- feral-file/docs for public product and legal reference material
- feral-file/ff-indexer-v2 for indexing and enrichment
- feral-file/ff-relayer for device relay and connectivity
Released under the BSD-2-Clause Plus Patent License. See LICENSE.