diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index 5474fba..d2e5f41 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -29,13 +29,10 @@ jobs: ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} run: nix develop --command task build-android-bundle - # Placeholder for Play Store upload. - # Once you have the Service Account JSON and everything is ready, - # you can uncomment this or use a specialized action. + # Play Store upload disabled for now # - name: Upload to Play Store # env: # PLAY_STORE_CONFIG_JSON: ${{ secrets.PLAY_STORE_CONFIG_JSON }} # run: | # echo "$PLAY_STORE_CONFIG_JSON" > play-store-key.json - # # Example using a tool like 'fastlane supply' or a dedicated flutter package - # # nix develop --command fvm flutter pub run ... + # # nix develop --command fvm flutter pub run supply ... diff --git a/.forgejo/workflows/website.yml b/.forgejo/workflows/website.yml new file mode 100644 index 0000000..2dbbce1 --- /dev/null +++ b/.forgejo/workflows/website.yml @@ -0,0 +1,38 @@ +name: Deploy Website + +on: + push: + branches: [main] + paths: + - 'website/**' + - '.forgejo/workflows/website.yml' + +jobs: + deploy: + name: Build & Deploy Website + runs-on: self-hosted + if: github.ref == 'refs/heads/main' + + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup SSH + env: + SSH_PRIVATE_KEY: ${{ secrets.WEBSITE_SSH_PRIVATE_KEY }} + run: | + if [ -n "$SSH_PRIVATE_KEY" ]; then + mkdir -p ~/.ssh + echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + else + echo "Error: WEBSITE_SSH_PRIVATE_KEY secret is not set." + exit 1 + fi + + - name: Deploy + env: + SSH_USER: ${{ secrets.WEBSITE_SSH_USER }} + SSH_HOST: ${{ secrets.WEBSITE_SSH_HOST }} + run: nix develop --command task website-deploy diff --git a/.gitignore b/.gitignore index 8aec262..9245ac0 100644 --- a/.gitignore +++ b/.gitignore @@ -94,6 +94,11 @@ sharedinbox-runner/runner-data/ .gemini/ .rustup/ +# --- Hugo --- +website/public/ +website/resources/ +website/.hugo_build.lock + .copilot/ .dotnet/ .vscode-server/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..761237f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "website/themes/PaperMod"] + path = website/themes/PaperMod + url = https://github.com/adityatelange/hugo-PaperMod.git diff --git a/Taskfile.yml b/Taskfile.yml index e134fd1..5d19d28 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -322,6 +322,27 @@ tasks: cmds: - fvm dart run scripts/check_coverage.dart + website-dev: + desc: Run Hugo development server + cmds: + - fvm flutter pub global run # Just a placeholder if nix shell hook isn't active + - nix develop --command hugo server --source website -D + + website-build: + desc: Build the static website + cmds: + - nix develop --command hugo --source website --minify + + website-deploy: + desc: Deploy the website via rsync to public_html + deps: [website-build] + cmds: + - | + rsync -avz --delete \ + -e "ssh -o StrictHostKeyChecking=no" \ + website/public/ \ + ${SSH_USER}@${SSH_HOST}:public_html/ + check-fast: desc: Pre-commit checks — analyze + unit tests + widget tests (no build, no integration) deps: [analyze, test, test-widget, check-hygiene] diff --git a/before-playstore.md b/before-playstore.md new file mode 100644 index 0000000..64f9e0b --- /dev/null +++ b/before-playstore.md @@ -0,0 +1,33 @@ +# Technical Audit for Play Store Readiness + +Your generated `.aab` (App Bundle) is technically valid, but to be fully "Play Store ready," you should verify these four areas: + +## 1. Target SDK Version +Google requires apps to target at least **Android 14 (API level 34)**. +Current status: **PASS** (Flutter defaults to 34+ in recent versions). + +## 2. Versioning +* **`versionName`**: Currently `0.1.1`. This is visible to users. +* **`versionCode`**: This must be a **unique integer** for every single upload to the Play Console. + * If you need to re-upload the same version because of a fix, you must increment the code (e.g., from `1` to `2`). + * Set this in `pubspec.yaml`: `version: 0.1.1+1` (the number after the `+` is the `versionCode`). + +## 3. App Icon +Check your icons in `android/app/src/main/res/mipmap-*`. +* **Status:** Currently using default `ic_launcher.png`. +* **Requirement:** Replace these with your own branding before submission. Google may reject apps that use default placeholder logos for being "Low Quality." + +## 4. Privacy & Data Safety (Crucial) +Google requires these before you can move to production: +* **Privacy Policy:** You **must** provide a public URL to a privacy policy. +* **Data Safety Section:** You must complete the questionnaire in the Play Console. + * Since this is an **Email app**, you must declare that it handles "Personal Communications" and potentially "User IDs" or "Contact Info." + +## 5. Helpful Commands +To inspect your bundle's manifest (to verify permissions or package name): +```bash +# requires bundletool +bundletool dump manifest --bundle build/app/outputs/bundle/release/app-release.aab +``` + +**Next Step Recommendation:** Complete the Privacy Policy and Data Safety questionnaire in the Play Console as they often take the longest to be approved. diff --git a/flake.lock b/flake.lock index 5a1fd9d..2210c77 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1776221942, - "narHash": "sha256-FbQAeVNi7G4v3QCSThrSAAvzQTmrmyDLiHNPvTF2qFM=", + "lastModified": 1778430510, + "narHash": "sha256-Ti+ZBvW6yrWWAg2szExVTwCd4qOJ3KlVr1tFHfyfi8Q=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1766437c5509f444c1b15331e82b8b6a9b967000", + "rev": "8fd9daa3db09ced9700431c5b7ad0e8ba199b575", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 25ec446..72d57b3 100644 --- a/flake.nix +++ b/flake.nix @@ -59,6 +59,9 @@ # Coverage merging (flutter test --merge-coverage requires lcov) lcov + # Website + hugo + # Utilities git curl diff --git a/t.sh b/t.sh new file mode 100755 index 0000000..bb9758c --- /dev/null +++ b/t.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Helper script to generate a production Android Keystore. +# Run this from the project root. + +# Define the path relative to the project root +KEYSTORE_PATH="android/app/upload-keystore.jks" + +echo "Generating keystore at: $KEYSTORE_PATH" + +keytool -genkey -v \ + -keystore "$KEYSTORE_PATH" \ + -alias upload \ + -keyalg RSA \ + -keysize 2048 \ + -validity 10000 + +echo "" +echo "Done." +echo "1. Remember your password!" +echo "2. Back up $KEYSTORE_PATH safely." +echo "3. Do NOT commit the .jks file or passwords to git." diff --git a/to-playstore.md b/to-playstore.md new file mode 100644 index 0000000..5c65605 --- /dev/null +++ b/to-playstore.md @@ -0,0 +1,51 @@ +# Play Store Publishing Roadmap + +To publish the Flutter app to the Play Store, you need to transition from a "development" state to a "production-ready" state. + +## 1. What has been done +* **Application ID:** Changed to `de.sharedinbox.mua` (verified in `build.gradle.kts`, `MainActivity.kt`, and integration tests). +* **Build Logic:** `android/app/build.gradle.kts` now supports: + * **Local builds:** Using `key.properties` (ignored by git). + * **CI builds:** Using environment variables (`ANDROID_KEY_ALIAS`, `ANDROID_KEY_PASSWORD`, `ANDROID_KEYSTORE_PASSWORD`). +* **Taskfile:** Added `task build-android-bundle` to generate the `.aab` file. +* **CI Workflow:** Created `.forgejo/workflows/release.yml` which triggers on merge to `main`. + +## 2. What you need to do next +### A. Create the Keystore +Run the helper script I created for you: +```bash +./t.sh +``` +Follow the prompts and use a strong password (24-32 chars). + +### B. Configure Codeberg Secrets +Go to **Settings > Actions > Secrets** in your Codeberg repo and add: +1. **`ANDROID_KEYSTORE_BASE64`**: The output of `base64 -w 0 android/app/upload-keystore.jks`. +2. **`ANDROID_KEYSTORE_PASSWORD`**: Your keystore password. +3. **`PLAY_STORE_CONFIG_JSON`**: The JSON key from your Google Play Service Account. + +### C. First Manual Upload +Google Play requires the **very first upload** to be done manually through the web console: +1. Generate your keystore using `./t.sh`. +2. Run the build locally using temporary environment variables: + ```bash + export ANDROID_KEYSTORE_PASSWORD=your_password + nix develop --command task build-android-bundle + ``` +3. Upload the resulting `.aab` from `build/app/outputs/bundle/release/app-release.aab` to the Play Console (Internal Testing or Production track). +4. This "locks in" your signing key. + +## 3. Firebase Test Lab +Once you have the Service Account JSON, you can add a task to `Taskfile.yml` to run automated tests on real devices: +```yaml +test-lab: + desc: Run integration tests in Firebase Test Lab + cmds: + - gcloud firebase test android run \ + --type instrumentation \ + --app build/app/outputs/apk/debug/app-debug.apk \ + --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk \ + --device model=virtuall1,version=30 +``` + +**Recommendation:** Complete step **A** (Keystore) and **B** (Secrets) first. Once the first manual upload is done, the CI will take over for all future merges to `main`. diff --git a/website/archetypes/default.md b/website/archetypes/default.md new file mode 100644 index 0000000..25b6752 --- /dev/null +++ b/website/archetypes/default.md @@ -0,0 +1,5 @@ ++++ +date = '{{ .Date }}' +draft = true +title = '{{ replace .File.ContentBaseName "-" " " | title }}' ++++ diff --git a/website/content/posts/welcome.md b/website/content/posts/welcome.md new file mode 100644 index 0000000..66a6631 --- /dev/null +++ b/website/content/posts/welcome.md @@ -0,0 +1,7 @@ +--- +title: 'Welcome to SharedInbox' +date: 2026-05-12T08:00:00Z +draft: false +--- + +Welcome to the official website of SharedInbox! diff --git a/website/hugo.toml b/website/hugo.toml new file mode 100644 index 0000000..f3b362e --- /dev/null +++ b/website/hugo.toml @@ -0,0 +1,18 @@ +baseURL = 'https://sharedinbox.de/' +languageCode = 'en-us' +title = 'SharedInbox' +theme = 'PaperMod' + +[params] + env = 'production' + title = 'SharedInbox' + description = 'IMAP/SMTP Email Client' + author = 'SharedInbox Team' + + [params.homeInfoParams] + Title = "SharedInbox" + Content = "The modern IMAP/SMTP email client for your desktop and mobile." + + [[params.socialIcons]] + name = "github" + url = "https://codeberg.org/guettli/sharedinbox" diff --git a/website/themes/PaperMod b/website/themes/PaperMod new file mode 160000 index 0000000..154d006 --- /dev/null +++ b/website/themes/PaperMod @@ -0,0 +1 @@ +Subproject commit 154d006e0182dfc7da38008323976b02e6bfab4a