From 63e7cc36ef8e16038b9241dcbf59f8c3e48447a9 Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Sun, 16 Aug 2026 11:28:36 +0300 Subject: [PATCH] document mobile app strategy --- docs/mobile-app-strategy.md | 202 ++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 docs/mobile-app-strategy.md diff --git a/docs/mobile-app-strategy.md b/docs/mobile-app-strategy.md new file mode 100644 index 0000000..46c6e17 --- /dev/null +++ b/docs/mobile-app-strategy.md @@ -0,0 +1,202 @@ +# Mobile App Strategy + +## Recommendation + +Attainly should keep one Vue application, make it properly mobile-first, and +package it for iOS and Android with Capacitor. + +Capacitor can be added to an existing Vue and Vite project. It generates real +Xcode and Android Studio projects while allowing the application to continue +using its Vue views, router, Pinia stores, Zod schemas, and Laravel API. + +This is a better fit than rewriting the frontend in Flutter or React Native. +Attainly's main interactions are forms, lists, schedules, and assignment +completion controls. A native rewrite would introduce another UI codebase +without providing a proportionate product benefit. + +A Progressive Web App can be offered as an interim installation option, but +Capacitor should be the App Store and Google Play distribution strategy. + +## Why the Existing Architecture Is a Good Fit + +Attainly already has the important separation needed for this approach: + +- The Vue and Vite frontend is independent from Laravel. +- Laravel exposes a JSON API. +- Pinia owns shared client state and API boundaries. +- Zod validates responses received from the backend. +- Existing screens include responsive breakpoints. + +Capacitor should be added to the existing frontend rather than creating a +second Vue application. The resulting layout would be similar to: + +```text +frontend/website/ +|-- src/ shared Vue application +|-- capacitor.config.ts +|-- ios/ Xcode project +`-- android/ Android Studio project +``` + +The built Vue assets should be bundled inside each native release. The native +application should not simply open the deployed website remotely. + +## Mobile Experience + +### Navigation + +The desktop dashboard currently combines today's work, schedules, and +available sets into one long page. The mobile layout should separate the core +areas with bottom navigation: + +- Today +- Plans +- Library +- Settings + +The web and native applications can use the same underlying Vue components and +stores while presenting navigation appropriate to each form factor. + +### Native Capabilities + +The first store release should provide useful mobile behavior beyond a website +wrapper: + +- Daily assignment reminders +- Deep links from confirmation emails and notifications +- An application badge for unfinished work +- Cached access to today's assignments during a temporary network outage +- Safe-area, keyboard, status-bar, and Android back-button handling +- Optional haptic feedback when an assignment is completed + +Reminders directly support Attainly's daily-use purpose. Capacitor provides +native push-notification support through Apple Push Notification service on +iOS and Firebase Cloud Messaging on Android. + +Universal Links on iOS and App Links on Android should use Attainly's HTTPS +domain. A confirmation or schedule link can then open the installed app at the +correct Vue route and fall back to the website when the app is not installed. + +## Authentication + +The website currently uses an HttpOnly session cookie and sends API requests +with browser credentials. That remains a good security model for the website, +but a native WebView should not depend on a cross-origin cookie. In particular, +iOS restricts third-party cookies in WebViews. + +The native application should use an opaque bearer session token: + +1. A mobile login endpoint authenticates the user and creates a server-side + session. +2. Laravel returns the opaque token to the native application. +3. The application stores the token in iOS Keychain or Android Keystore using + a maintained secure-storage plugin. +4. The native API client sends the token in the `Authorization` header. +5. The browser API client continues using the HttpOnly cookie. + +The token must not be stored in `localStorage`. The existing session domain and +repository can likely be extended to support both transports without changing +the rest of the protected API. + +A shared API client should hide the platform difference from Pinia stores: + +```text +Vue views and Pinia stores + | + shared API client + / \ +browser transport native transport +HttpOnly cookie secure bearer token + \ / + Laravel API +``` + +All production traffic must use HTTPS. Native application bundles must not +contain backend secrets or privileged API keys. + +## Store Readiness + +### Account and Privacy Requirements + +Attainly supports account creation, so it must add the following before store +submission: + +- An account-deletion action in Settings +- A backend endpoint and policy for deleting the account and associated data +- A public web resource through which former users can request deletion +- An accessible privacy policy and terms of use +- Accurate Apple App Privacy and Google Play Data Safety declarations +- An iOS privacy manifest covering the application and relevant SDKs + +Apple requires applications that support account creation to offer account +deletion within the application. Google Play requires an in-app deletion path +and a web deletion resource that remains available after the application is +uninstalled. + +### Application Quality + +Apple expects an application to provide functionality and UI beyond a +repackaged website. The daily reminders, deep links, offline state, mobile +navigation, and device-appropriate behavior help make Attainly useful and +app-like. + +The submitted build must be stable and complete. The production backend must +remain available during review, and the reviewer must receive a working demo +account or a fully featured demo mode. + +### Platform Tooling + +The iOS project is built and submitted with Xcode on macOS. The Android project +is built and submitted through Android Studio or its command-line tooling. + +As of August 2026, Google Play states that new applications and updates must +target Android 16, API level 36, or higher. Store SDK and tool requirements +change regularly and must be checked again immediately before implementation +and each release. + +## Suggested Delivery Sequence + +1. Finish and production-harden the core web product. +2. Refactor the Vue interface into responsive Today, Plans, Library, and + Settings screens. +3. Introduce the shared API client and native authentication transport. +4. Add Capacitor and generate the iOS and Android projects. +5. Implement Universal Links, App Links, and daily reminders. +6. Add offline caching for today's assignments and queued completion updates. +7. Add account deletion, privacy documents, and store disclosures. +8. Test through TestFlight and Google Play internal testing on real devices. +9. Prepare icons, splash screens, screenshots, review credentials, and store + metadata. +10. Submit to Google Play and the App Store. + +Existing Cypress coverage should continue to verify the shared browser-facing +behavior. Native releases also need smoke testing on real iOS and Android +devices, particularly for authentication, deep links, notifications, offline +recovery, keyboard behavior, and operating-system navigation. + +## Expected Effort + +A basic Capacitor wrapper could be made to run in a few days. A polished, +secure, and review-ready mobile MVP is more realistically four to six weeks of +focused work, assuming the core web product and production backend are ready. + +The largest pieces are not generating the native projects. They are mobile +authentication, mobile navigation, notifications, deep links, offline +behavior, account deletion, device testing, and store compliance. + +## References + +The following requirements were reviewed on August 16, 2026: + +- [Capacitor documentation](https://capacitorjs.com/docs) +- [Capacitor iOS documentation](https://capacitorjs.com/docs/ios) +- [Capacitor Android documentation](https://capacitorjs.com/docs/android) +- [Capacitor security guidance](https://capacitorjs.com/docs/guides/security) +- [Capacitor cookie behavior](https://capacitorjs.com/docs/apis/cookies) +- [Capacitor deep links](https://capacitorjs.com/docs/guides/deep-links) +- [Capacitor push notifications](https://capacitorjs.com/docs/apis/push-notifications) +- [Apple App Review Guidelines](https://developer.apple.com/app-store/review/guidelines/) +- [Apple account-deletion guidance](https://developer.apple.com/support/offering-account-deletion-in-your-app/) +- [Apple app privacy management](https://developer.apple.com/help/app-store-connect/manage-app-information/manage-app-privacy/) +- [Google Play account-deletion requirements](https://support.google.com/googleplay/android-developer/answer/13327111?hl=en-EN) +- [Google Play target API requirements](https://support.google.com/googleplay/android-developer/answer/11926878?hl=en)