feat(mobile): NativeScript + Vue 3 scaffold (#484)#495
Merged
Conversation
- Add mobile/ with NativeScript + Vue 3 project structure - Port Frappe UI design tokens (ink/surface/outline, typography, spacing) into a NativeScript-compatible Tailwind config - Set up Pinia stores mirroring the web frontend shape (site, session, user) - Add Frappe API client with Bearer token auth - Add pure formatting utilities shared with the web app - Extract shared TypeScript types into packages/types (@mail/types workspace) - Add minimal App_Resources for Android and iOS - Configure ESLint, Prettier, and TypeScript matching the frontend setup - Document generic vs. Mail-specific code for future frappe-nativescript extraction Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Get the scaffolded NativeScript app actually building and launching on a device, and replace the placeholder launcher icon with the Frappe Mail logo. - Enable yarn workspaces by marking the root package private, so the `mobile` workspace (and `@mail/types`) resolves via `yarn install` - Add `webpack.config.cjs` + point `webpackConfigPath` at it; the root is `type: module`, so a plain `.js` config is loaded as ESM and the NativeScript CLI's `require()` cannot call its default export - Set `main` to `app/app.ts` so webpack can resolve the entry point - Add `shims-vue.d.ts` and `import type` for NativeScriptConfig to clear the type-check errors; drop the non-existent `dayjs/plugin/isThisYear` in favor of a year comparison - Add adaptive launcher icons (vector background + foreground) and set `minSdkVersion 26`; no legacy raster icons, single source of truth Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Drop unused READ_/WRITE_EXTERNAL_STORAGE Android permissions; the app only needs INTERNET, and WRITE_EXTERNAL_STORAGE is ignored on API 26+ - Fix stale README: yarn (not bun) is the package manager, and the launcher icon is already an adaptive icon (no manual icon generation); drop the not-yet-existent components/ dir from the tree - Disable vue/attribute-hyphenation — NativeScript view props are camelCase (e.g. flexDirection), so the HTML-oriented rule misfires - Apply prettier formatting to clear the two outstanding lint errors - Remove the inert eslint-disable header from nativescript.config.ts Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Consolidate the mobile workspace onto the root ESLint + Prettier setup instead of maintaining parallel configs under mobile/. - Add a mobile/** override to the root eslint.config.mjs (resolver alias for @ -> mobile/app and @mail/types, and vue/attribute-hyphenation off for NativeScript camelCase view props); set tsconfigRootDir so the parser stops erroring on the multiple tsconfig candidates - Delete mobile/eslint.config.mjs and mobile/.prettierrc; the root .prettierrc already auto-detects each tailwind.config, so mobile files format identically - Reformat mobile sources under the root rules (import ordering, tailwind class sorting) Also fixes a pre-existing broken dependency this surfaced: the scaffold pinned @nativescript/tailwind ^1.0.0, which does not exist on the registry (a clean yarn install fails). Pin ^2.0.0 — the line built for Tailwind 3, which this project uses — replacing the stale 4.0.9 that had pulled in the Tailwind 4 postcss toolchain. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Frappe Linter (pre-commit eslint) ran the root config over mobile's
build configs once the mobile-local config was removed, failing on:
- @typescript-eslint/no-require-imports in postcss.config.js,
tailwind.config.js, and webpack.config.cjs — these are CommonJS by
necessity (their loaders need require()/module.exports). Disable the
rule for mobile/*.{js,cjs}.
- prettier wanting 2-space indent in webpack.config.cjs: .editorconfig
enforces tabs for *.js/*.ts/*.vue but omitted *.cjs, so add it — the
repo's lone .cjs file now matches every other JS-family file.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- AppIcon: single-size 1024×1024 opaque app icon in Assets.xcassets/AppIcon.appiconset (iOS rounds corners; Xcode derives the smaller sizes) - Launch screen: LaunchScreen.storyboard + AppIconBackground/Center image sets — white background with the centered blue-circle envelope, to match the Android 12+ splash - build.xcconfig: set ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon. Without it NativeScript's generated Xcode project never designates the app icon, so actool ships a blank icon and no CFBundleIcons Verified on simulator: home-screen icon and launch-screen logo both render; actool/ibtool compile the catalog and storyboard with no warnings. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
mobile/— full NativeScript + Vue 3 project with Pinia, TypeScript, Tailwind, ESLint/Prettiertailwind.config.jspackages/types/(@mail/typesworkspace) with shared TypeScript types extracted from the frontend — no copy-pasting between appssite(saved servers),session(OAuth tokens),user(accounts, mailboxes)utils/api.ts) that injectsAuthorization: Bearerheadersutils/format.ts) reusable across web and mobileApp_Resources/for Android and iOS with OAuth redirect URI stubsmobile/README.mdfor futurefrappe-nativescriptextractionBuild & tooling
mobileis a yarn workspace off the repo root (root is markedprivateso workspaces are enabled);yarn installfrom the root resolves@mail/mobileand@mail/typeswebpack.config.cjs(referenced viawebpackConfigPath) — the root istype: module, so the NativeScript CLI'srequire()of a plain.jsconfig fails;.cjsforces CommonJSminSdkVersionis26Test plan
yarn installfrom repo root resolves all workspace packages without errorsmobile/type-checks with no errors (verified duringnsbuild)ns build androidsucceeds (resource linking + Gradle)ns run androidbuilds, installs, and boots the placeholder LandingPage on a device with the Frappe Mail launcher iconns run iosbuilds, installs, and boots on the simulator; app icon + launch screen render (white splash with centered blue-circle logo, matching Android)Closes #484
🤖 Generated with Claude Code