A journal to write what you're thankful for. Contributions welcome!
Presently is built on the idea that gratitude journaling should be free, private, and available to all. It will never have ads, never have a premium version, and will always be open source. Entries are kept on device and can be exported to CSV.
Presently is also built with the best Android practices in mind. It follows MVVM to separate concerns and ensure we write testable code. We require 80%+ code coverage and rely on both unit tests and instrumented tests (with a heavier weight towards unit tests). Instrumented tests are run on Firebase Test Lab, crashes are reported through Crashlytics, and analytics are reported with Firebase Analytics.
We support several languages currently and are always looking for translators to help us! We support French, Spanish, Italian, German, Finnish, Arabic, Dutch, Polish, Portuguese, Slovakian, Croatian, Romanian, Turkish, Russian, Afrikaans.
- MVVM with architecture components
- ViewModel
- Room (with FTS and Paging v3)
- Mavericks
- CircleCI
- Jacoco coverage reports (integrated with CI)
- Firebase Crashlytics Crash Reporting
- Dagger + Hilt
- Espresso
- Firebase Test Lab
- WorkManager
- Dropbox Java SDK
The app currently has over 40 themes to choose from! Here's a few:
Contributions are welcome! Please fork the repo and make a PR. Forked PRs will build the app and run unit tests but will not run instrumented tests. A repo owner will run those tests as they require secret keys. You can set DROPBOX_KEY in local.properties if you want to test Dropbox features locally.
Presently is translated by volunteers. All translatable app copy now lives under
app/src/main/res, so translators only need to work in that tree.
- Fork this repository.
- In your fork, create a new directory in
app/src/main/res/namedvalues-XX, whereXXis your language locale code. For locale codes and special variants such as Brazilian Portuguese, refer to the IANA language subtag registry. - Create
app/src/main/res/values-XX/presently_strings.xmland copy the contents ofapp/src/main/res/values/presently_strings.xmlinto it. - Translate every string except the ones marked
translatable="false". - Create
app/src/main/res/values-XX/presently_prompts.xmland copy the contents ofapp/src/main/res/values/presently_prompts.xmlinto it. - Translate every item in that file.
- Add your Play Store listing translation to the end of
StoreListing.md. Please keep the first line under 50 characters and the second under 80:
[NOTE TO TRANSLATORS: please keep the following line under 50 characters long]
Presently: A gratitude journal
[NOTE TO TRANSLATORS: please keep the following line under 80 characters long]
Celebrate your daily life with Presently, a free & private gratitude journal
[NOTE TO TRANSLATORS: no length limits below this point, translate however you like!]
Practice gratitude with this simple, always free, and private gratitude journaling app.
Presently lets you: ⁕ Record daily entries of gratitude ⁕ Reflect back on your past moments of gratitude ⁕ Find motivation through quotes and prompts ⁕ Set daily reminders to continue your gratitude practice ⁕ Lock your entries with fingerprint or face id ⁕ Automatically back up your entries to Dropbox ⁕ Search your old entries ⁕ Share your entries with family and friends ⁕ Export/import your entries ⁕ Switch to your favorite color scheme
Presently is 100% free and ad free. All of your entries stay on your device and in your control.
- Optional: create
app/src/main/res/values-XX/presently_inspirations.xmlfromapp/src/main/res/values/presently_inspirations.xmland translate it. This file contains gratitude quotes, so it is appreciated but not required. - Add your language label to
app/src/main/res/values/strings.xml:
<string name="language_XX" translatable="false">LANGUAGE</string>Replace XX with your locale code and LANGUAGE with the language name written in that language
such as Français, English, or русский.
- Add your language to the
AppLanguageandAppLanguageValuesarrays inapp/src/main/res/values/array.xml. - Open a pull request with a short description of the translation.
- Respond to review comments if needed. Once approved, the translation will ship in a future release.
If you do not want to use GitHub, email your translated files to
[email protected].
Send:
presently_strings.xmlpresently_prompts.xml- your translated Play Store listing text
- optional
presently_inspirations.xml
Use these source files as the starting point:
app/src/main/res/values/presently_strings.xmlapp/src/main/res/values/presently_prompts.xmlapp/src/main/res/values/presently_inspirations.xml
String resources look like this:
<string name="key_name">Translate me!</string>Only translate the text between the tags. Some characters such as ' must be escaped in Android
XML. See the Android docs on string resource escaping.
String arrays look like this:
<resources>
<string-array name="prompts">
<item>What is something that made you smile?</item>
</string-array>
</resources>Only translate the text inside each <item>...</item>.
Use the local coverage helper script:
- Unit tests only:
./scripts/local_coverage.sh - Unit tests + connected Android tests for
app:./scripts/local_coverage.sh --connected
Reports are written to:
- HTML:
build/reports/jacoco/html/index.html - XML:
build/reports/jacoco/jacocoFullReport/jacocoFullReport.xml
The repo now includes local release helpers:
./scripts/release_job.sh
./scripts/promote_release.sh
It handles the release-only steps that should not live in git:
- stages
app/google-services.json - loads Dropbox + signing secrets from a local
release.properties - optionally overlays paid fonts for the
releasesource set only - optionally bumps
versionName/versionCode - runs unit tests
- runs connected Android tests or Firebase Test Lab tests
- builds a signed release bundle, plus an APK if requested
- optionally uploads the built AAB to a Play track
Create a local release-secrets/ directory like this:
release-secrets/
google-services.json
gcloud-service-key.json # only if using --instrumented firebase
release.properties
fonts/
larsseit_medium.ttf
value_serif.ttf
Start from scripts/release.properties.example and copy it to release-secrets/release.properties.
Examples:
./scripts/release_job.sh --bump patch./scripts/release_job.sh --version-name 1.22.3 --version-code 91 --instrumented connected./scripts/release_job.sh --bump minor --instrumented firebase --build-apk./scripts/release_job.sh --bump patch --instrumented firebase --play-track internal
To promote an existing Play release:
./scripts/promote_release.sh --from-track internal --to-track production
The script cleans up staged secret files when it exits, so you do not need to stash or swap tracked files for a release build.
CircleCI is set up so you can trigger a release pipeline manually.
The release workflow is intended to run with a restricted CircleCI context named presently-release.
In CircleCI, use Trigger Pipeline and pass:
run_release: true- optional
release_bump: patch|minor|major|none - optional
release_version_name: X.Y.Z - optional
release_version_code: N - optional
release_instrumented: firebase|connected|skip - optional
release_build_apk: true|false - optional
release_play_track: internal|production|... - optional
release_play_release_name: your label - optional
release_commit_version: true|false
To promote an existing uploaded release, trigger a pipeline with:
run_promote_release: true- optional
promote_from_track: internal|beta|... - optional
promote_to_track: production|beta|... - optional
promote_release_status: completed|draft|halted|inProgress - optional
promote_user_fraction: 0.1
Required CircleCI environment variables:
GOOGLE_SERVICES_JSON_B64orGOOGLE_SERVICES_JSONDROPBOX_APP_KEYANDROID_KEYSTORE_B64RELEASE_STORE_PASSWORDRELEASE_KEY_ALIASRELEASE_KEY_PASSWORDGITHUB_BOT_TOKENif you userelease_commit_version: true
Optional CircleCI environment variables:
GCLOUD_SERVICE_KEYforrelease_instrumented=firebaseor for GCS-hosted fontsGOOGLE_PLAY_SERVICE_ACCOUNT_B64for Play upload/promotion. If absent, the workflow falls back toGCLOUD_SERVICE_KEYLARSSEIT_MEDIUM_TTF_GCS_URIandVALUE_SERIF_TTF_GCS_URIif you want CI to swap in paid fonts from private Cloud Storage objects
The CircleCI release job will:
- materialize the release-only files into
release-secrets/ - run
./scripts/release_job.sh - store the generated AAB and optional APK as CircleCI artifacts
- optionally upload the AAB to Google Play
Important: version bumping in CI changes the workspace used for that build unless you also enable release_commit_version. With release_commit_version: true, the job will push the bumped version file back to the triggering branch after the release succeeds.
Recommended production flow:
run_release: truewithrelease_bump: patch,release_play_track: internal, andrelease_commit_version: true- verify the internal release in Play
run_promote_release: trueto move the existing artifact frominternaltoproduction
When release_commit_version is enabled, the release job will:
- commit the bumped version in
buildSrc/src/main/java/Dependencies.kt - push that commit back to the triggering branch
This requires a GITHUB_BOT_TOKEN with push access to the repository. If the branch is protected against direct pushes from that token, the release job will fail at the final push step.
To host paid fonts privately for CircleCI:
- upload each font to a private GCS bucket
- grant the CircleCI service account
roles/storage.objectVieweron that bucket - set
LARSSEIT_MEDIUM_TTF_GCS_URIandVALUE_SERIF_TTF_GCS_URIto thegs://...object URIs
To restrict who can run releases:
- create a CircleCI context named
presently-release - move the release-only secrets into that context instead of plain project env vars
- restrict that context to the GitHub team or project that should be allowed to run releases
If a user triggers the release pipeline without access to that context, the release_build job will fail with Unauthorized.















