Offline digital model-release signing for portrait photographers.
Capture shoot details and a finger/stylus signature, then export a PDF stamped with UTC time and GPS (when available) into Documents/ReleaseCanvas/ via MediaStore.
Legal disclaimer: the included release wording is a generic template, not legal advice. Have counsel review language for your jurisdiction before commercial use.
AI-assisted development: most of this codebase was produced with AI coding assistance. All changes were reviewed, tested, and approved by humans before merge. AI does not replace maintainer responsibility for quality or fitness for purpose.
| Surface | Status |
|---|---|
| Android app | Full product (API 29+) — preferred when available |
| Web companion | Sign & export only (static site, GitHub Pages) — fills the gap for iPhone/desktop browsers |
| Native iOS app | Not available yet — we do not have an Apple device for proper testing |
Web scope intentionally excludes history, profile/branding, batch, and full localization. Prefer Android for the complete workflow.
- Source:
web/· local:cd web && python3 -m http.server 8080 - Live site (after Pages is enabled):
https://arianar.github.io/ReleaseCanvas/
- Form fields: model name, email, photographer name, shoot description
- Optional shoot metadata (shoot ID, contacts, client, notes)
- Release template picker (generic, 500px-style unofficial, stock RF-style, editorial, social/web)
- Two language pickers: app UI language × release wording language (en, es, fr, it, de, fa; Persian RTL)
- Batch multi-model: shared shoot details, then sign/export one PDF per model in sequence
- Share / save to cloud via the system share sheet (Drive, Dropbox, email, …) — no automatic sync
- Optional city / country (manual) or best-effort reverse geocode from GPS when online
- Interactive signature pad (clear / undo)
- Best-effort GPS via Fused Location Provider (export works without location)
- PDF via Android
PdfDocument(terms + signature image + metadata) - Local history of recent exports
- Photographer name remembered between sessions (DataStore)
- Fully offline after install (location optional; geocode needs network when used)
ReleaseCanvas does not redistribute third-party platform forms. Official model-release text is typically copyrighted, may be trademark-branded, and is governed by each platform’s terms of service. Shipping those documents as if they were “the official form” would imply endorsement and create legal risk for users and maintainers.
What we provide instead:
- Inspired, unofficial sample templates (e.g. “500px-style (unofficial)”, stock RF-style) clearly labeled as samples, not legal advice
- Custom template import and editing so you can use wording you have the right to use (counsel-reviewed text, your studio’s form, etc.)
- Export as your own PDF with signature and metadata
If a platform ever grants an explicit redistribution license, we could revisit embedding their form. Until then, treat built-ins as starting points and import official text only when you are licensed to use it.
Not yet. Native iOS is blocked on testing access (no Apple hardware in the maintainer setup). Photographers on iOS can use the web companion (GitHub Pages) for form → sign → download/share PDF. The full feature set remains on Android.
Exports go to shared storage: Documents/ReleaseCanvas/ (MediaStore). That means other apps and anyone using the system Files app can open them. They contain model name, email, signature image, and (only if you opt in on Review) GPS. Treat them as sensitive.
App preferences (history list, profile, custom templates) are excluded from Auto Backup via backup/data-extraction rules where the OS supports them.
ReleaseCanvas is offline-first: every release is written under Documents/ReleaseCanvas on the device. There is no automatic cloud sync and no multi-vendor storage SDK.
To keep a copy off-device:
- After export, tap Share / save to cloud (or use the share icon on a history row).
- Pick Drive, Dropbox, Files, email, etc. from the system share sheet.
- The file leaves the device only under your account and the app you choose.
Device captures (Android). EXIF stripped; location redacted in review/success.
| Home | Form | Terms | Signature |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
| Review | Success | History |
|---|---|---|
![]() |
![]() |
![]() |
| Tool | Notes |
|---|---|
| Android Studio | Quail 2 / recent stable |
| JDK | 17+ (Studio jbr-21 recommended) |
| Android SDK | Platform 36, build-tools |
| Device / emulator | API 29+ |
- File → Open → this repository root
- Trust the Gradle project and wait for sync (wrapper 8.11.1, AGP 8.7.3)
- Gradle JDK: Settings → Build Tools → Gradle → Gradle JDK → jbr-21
- Run configuration app → device/emulator → Run
Studio will create local.properties with your SDK path (gitignored).
export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))
export ANDROID_HOME=$HOME/Android/Sdk # or your Studio SDK path
./gradlew :app:assembleDebug
./gradlew :app:testDebugUnitTestDebug APK: app/build/outputs/apk/debug/app-debug.apk
Signing does not require Google Play or any fee. Use a local keystore that is never committed.
- Keystore file at repo root:
release-canvas.jks(already gitignored via*.jks) - Copy
keystore.properties.example→keystore.propertiesand set passwords/alias - Build:
./gradlew :app:assembleReleaseOutput: app/build/outputs/apk/release/app-release.apk
If keystore.properties is missing, the release build is unsigned/debug-signed depending on the toolchain — always keep keystore.properties local for real installs.
Workflow: .github/workflows/release-apk.yml
| Trigger | Result |
|---|---|
Push tag v* (e.g. v1.6.1) |
Build signed APK → attach ReleaseCanvas-vX.Y.Z.apk to that GitHub Release |
| Actions → Release signed APK → Run workflow | Build only; APK as workflow artifact (no Release attach) |
Repository secrets (Settings → Secrets and variables → Actions):
RELEASE_KEYSTORE_BASE64—base64 -w0 release-canvas.jksRELEASE_STORE_PASSWORDRELEASE_KEY_ALIASRELEASE_KEY_PASSWORD(usually same as store password)
Never commit the keystore or keystore.properties.
- New release → fill form
- Sign on the canvas
- Review → grant location if desired → Sign & export
- Open, share, or start another release
Metadata (UTC instant + location) is captured when export starts, not when the pad opens.
| Permission | Why |
|---|---|
| Fine / coarse location | Optional GPS stamp at sign time |
No legacy storage permission on API 29+. PDFs are created through MediaStore under Documents/ReleaseCanvas.
app/src/main/java/com/releasecanvas/app/
├── ui/ # Compose screens, theme, navigation, signature pad
├── data/ # Location, PDF, MediaStore, DataStore
└── util/ # Formatters, validation
- Kotlin · Jetpack Compose · Material 3
- Navigation Compose · ViewModel · Coroutines · DataStore
- Play Services Location
PdfDocument+ MediaStore
See CONTRIBUTING.md. Please read the Code of Conduct.
- Bug reports & features: Issues
- Security: SECURITY.md (private reporting preferred)
See ROADMAP.md for shipped versions, current focus, and non-goals.
Active tracking: milestones · issues
GNU General Public License v3.0
Copyright (C) ReleaseCanvas contributors






