@meadow-studio/platform 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/MeadowPlatform.podspec +17 -0
  2. package/Package.swift +23 -0
  3. package/README.md +147 -2
  4. package/android/build.gradle +42 -0
  5. package/android/src/main/AndroidManifest.xml +1 -0
  6. package/android/src/main/java/app/meadow/platform/MeadowAppRatingPlugin.java +38 -0
  7. package/dist/cli/app-skill.d.ts +3 -0
  8. package/dist/cli/app-skill.d.ts.map +1 -0
  9. package/dist/cli/app-skill.js +38 -0
  10. package/dist/cli/app-skill.js.map +1 -0
  11. package/dist/cli/commands.d.ts +74 -0
  12. package/dist/cli/commands.d.ts.map +1 -0
  13. package/dist/cli/commands.js +1095 -0
  14. package/dist/cli/commands.js.map +1 -0
  15. package/dist/cli/config.d.ts +123 -0
  16. package/dist/cli/config.d.ts.map +1 -0
  17. package/dist/cli/config.js +428 -0
  18. package/dist/cli/config.js.map +1 -0
  19. package/dist/cli/inspiration.d.ts +3 -0
  20. package/dist/cli/inspiration.d.ts.map +1 -0
  21. package/dist/cli/inspiration.js +12 -0
  22. package/dist/cli/inspiration.js.map +1 -0
  23. package/dist/cli/meadow.d.ts +8 -0
  24. package/dist/cli/meadow.d.ts.map +1 -0
  25. package/dist/cli/meadow.js +466 -0
  26. package/dist/cli/meadow.js.map +1 -0
  27. package/dist/cli/product-brief.d.ts +3 -0
  28. package/dist/cli/product-brief.d.ts.map +1 -0
  29. package/dist/cli/product-brief.js +38 -0
  30. package/dist/cli/product-brief.js.map +1 -0
  31. package/dist/cli/recipes.d.ts +10 -0
  32. package/dist/cli/recipes.d.ts.map +1 -0
  33. package/dist/cli/recipes.js +575 -0
  34. package/dist/cli/recipes.js.map +1 -0
  35. package/dist/cli/sync.d.ts +14 -0
  36. package/dist/cli/sync.d.ts.map +1 -0
  37. package/dist/cli/sync.js +310 -0
  38. package/dist/cli/sync.js.map +1 -0
  39. package/dist/cli/templates.d.ts +27 -0
  40. package/dist/cli/templates.d.ts.map +1 -0
  41. package/dist/cli/templates.js +1292 -0
  42. package/dist/cli/templates.js.map +1 -0
  43. package/dist/cli/website.d.ts +5 -0
  44. package/dist/cli/website.d.ts.map +1 -0
  45. package/dist/cli/website.js +262 -0
  46. package/dist/cli/website.js.map +1 -0
  47. package/dist/index.d.ts +5 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +5 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/notifications.d.ts +119 -0
  52. package/dist/notifications.d.ts.map +1 -0
  53. package/dist/notifications.js +320 -0
  54. package/dist/notifications.js.map +1 -0
  55. package/dist/platform.d.ts +163 -0
  56. package/dist/platform.d.ts.map +1 -0
  57. package/dist/platform.js +623 -0
  58. package/dist/platform.js.map +1 -0
  59. package/dist/purchases.d.ts +88 -0
  60. package/dist/purchases.d.ts.map +1 -0
  61. package/dist/purchases.js +296 -0
  62. package/dist/purchases.js.map +1 -0
  63. package/dist/ui/app-build.component.d.ts +18 -0
  64. package/dist/ui/app-build.component.d.ts.map +1 -0
  65. package/dist/ui/app-build.component.js +56 -0
  66. package/dist/ui/app-build.component.js.map +1 -0
  67. package/dist/ui/app-build.model.d.ts +11 -0
  68. package/dist/ui/app-build.model.d.ts.map +1 -0
  69. package/dist/ui/app-build.model.js +18 -0
  70. package/dist/ui/app-build.model.js.map +1 -0
  71. package/dist/ui/app-links.component.d.ts +14 -0
  72. package/dist/ui/app-links.component.d.ts.map +1 -0
  73. package/dist/ui/app-links.component.js +77 -0
  74. package/dist/ui/app-links.component.js.map +1 -0
  75. package/dist/ui/app-links.model.d.ts +18 -0
  76. package/dist/ui/app-links.model.d.ts.map +1 -0
  77. package/dist/ui/app-links.model.js +17 -0
  78. package/dist/ui/app-links.model.js.map +1 -0
  79. package/dist/ui/index.d.ts +5 -0
  80. package/dist/ui/index.d.ts.map +1 -0
  81. package/dist/ui/index.js +5 -0
  82. package/dist/ui/index.js.map +1 -0
  83. package/docs/CLI.md +389 -0
  84. package/docs/PLATFORM_GUIDE.md +423 -0
  85. package/docs/POC_FINDINGS.md +218 -0
  86. package/docs/PROJECT_BRIEF.md +501 -0
  87. package/docs/RELEASING.md +49 -0
  88. package/docs/V0.1_PATH.md +310 -0
  89. package/ios/Sources/MeadowPlatformPlugin/MeadowAppRatingPlugin.swift +39 -0
  90. package/package.json +89 -4
  91. package/schema/meadow-config.schema.json +250 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-links.component.js","sourceRoot":"","sources":["../../src/ui/app-links.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EACL,8BAA8B,EAC9B,cAAc,GAEf,MAAM,sBAAsB,CAAC;;;;IAUpB,+BAIC;IACC,YACF;IAAA,oBAAI;;;IALF,wDAAkB;;IAIlB,cACF;IADE,8CACF;;;IARJ,8BAAqC;IACnC,sGAQC;IACH,oBAAM;;;;IATJ,cAQC;IARD,cAAA,cAAO,CAQN;;AAfT,2EAA2E;AA4C3E,MAAM,OAAO,uBAAuB;IACjB,MAAM,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC;IAEhD,SAAS,GAAG,KAAK,CAAC,iBAAiB;kFAAC,CAAC;IACrC,YAAY,GAAG,KAAK,CAAC,8BAA8B,CAAC,OAAO;qFAAC,CAAC;IAC7D,YAAY,GAAG,KAAK,CAAC,8BAA8B,CAAC,OAAO;qFAAC,CAAC;IAC7D,UAAU,GAAG,KAAK,CAA4B,SAAS;mFAAC,CAAC;IACzD,YAAY,GAAG,KAAK,CAA4B,SAAS;qFAAC,CAAC;IAEjD,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE;QACvC,MAAM,MAAM,GAAwB;YAClC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE;YAC5B,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE;SAC7B,CAAC;QACF,OAAO,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE;YAC7C,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE;YAC7B,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE;SAClC,CAAC,CAAC;IACL,CAAC;8EAAC,CAAC;iHAlBQ,uBAAuB;6DAAvB,uBAAuB;YAvChC,sFAAsB;;YAAtB,6CAYC;;;iFA2BQ,uBAAuB;cA3CnC,SAAS;2BACE,kBAAkB,cAChB,IAAI,YACN;;;;;;;;;;;;;;GAcT;;kFA0BU,uBAAuB"}
@@ -0,0 +1,18 @@
1
+ import type { MeadowAppConfig } from '../platform.js';
2
+ export type MeadowAppLinkKind = 'privacy' | 'support';
3
+ export interface MeadowAppLink {
4
+ readonly kind: MeadowAppLinkKind;
5
+ readonly label: string;
6
+ readonly href: string;
7
+ }
8
+ export interface MeadowAppLinkLabels {
9
+ readonly privacy: string;
10
+ readonly support: string;
11
+ }
12
+ export interface MeadowAppLinkOverrides {
13
+ readonly privacyUrl?: string | null;
14
+ readonly supportEmail?: string | null;
15
+ }
16
+ export declare const DEFAULT_MEADOW_APP_LINK_LABELS: Readonly<MeadowAppLinkLabels>;
17
+ export declare function meadowAppLinks(app: Readonly<MeadowAppConfig>, labels?: Readonly<MeadowAppLinkLabels>, overrides?: Readonly<MeadowAppLinkOverrides>): readonly Readonly<MeadowAppLink>[];
18
+ //# sourceMappingURL=app-links.model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-links.model.d.ts","sourceRoot":"","sources":["../../src/ui/app-links.model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,SAAS,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AAED,eAAO,MAAM,8BAA8B,EAAE,QAAQ,CAAC,mBAAmB,CAGvE,CAAC;AAEH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,QAAQ,CAAC,eAAe,CAAC,EAC9B,MAAM,GAAE,QAAQ,CAAC,mBAAmB,CAAkC,EACtE,SAAS,GAAE,QAAQ,CAAC,sBAAsB,CAAM,GAC/C,SAAS,QAAQ,CAAC,aAAa,CAAC,EAAE,CAcpC"}
@@ -0,0 +1,17 @@
1
+ export const DEFAULT_MEADOW_APP_LINK_LABELS = Object.freeze({
2
+ privacy: 'Privacy',
3
+ support: 'Contact support',
4
+ });
5
+ export function meadowAppLinks(app, labels = DEFAULT_MEADOW_APP_LINK_LABELS, overrides = {}) {
6
+ const privacyUrl = overrides.privacyUrl === undefined ? app.privacyUrl : overrides.privacyUrl;
7
+ const supportEmail = overrides.supportEmail === undefined ? app.supportEmail : overrides.supportEmail;
8
+ const links = [];
9
+ if (privacyUrl && /^https?:\/\//i.test(privacyUrl)) {
10
+ links.push({ kind: 'privacy', label: labels.privacy, href: privacyUrl });
11
+ }
12
+ if (supportEmail && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(supportEmail)) {
13
+ links.push({ kind: 'support', label: labels.support, href: `mailto:${supportEmail}` });
14
+ }
15
+ return Object.freeze(links.map((link) => Object.freeze(link)));
16
+ }
17
+ //# sourceMappingURL=app-links.model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-links.model.js","sourceRoot":"","sources":["../../src/ui/app-links.model.ts"],"names":[],"mappings":"AAoBA,MAAM,CAAC,MAAM,8BAA8B,GAAkC,MAAM,CAAC,MAAM,CAAC;IACzF,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,iBAAiB;CAC3B,CAAC,CAAC;AAEH,MAAM,UAAU,cAAc,CAC5B,GAA8B,EAC9B,SAAwC,8BAA8B,EACtE,YAA8C,EAAE;IAEhD,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC;IAC9F,MAAM,YAAY,GAChB,SAAS,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC;IACnF,MAAM,KAAK,GAAoB,EAAE,CAAC;IAElC,IAAI,UAAU,IAAI,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACnD,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,YAAY,IAAI,4BAA4B,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QACpE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,UAAU,YAAY,EAAE,EAAE,CAAC,CAAC;IACzF,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { MeadowAppBuildComponent } from './app-build.component.js';
2
+ export { DEFAULT_MEADOW_APP_BUILD_LABELS, formatMeadowAppBuild, type MeadowAppBuildLabels, } from './app-build.model.js';
3
+ export { MeadowAppLinksComponent } from './app-links.component.js';
4
+ export { DEFAULT_MEADOW_APP_LINK_LABELS, meadowAppLinks, type MeadowAppLink, type MeadowAppLinkKind, type MeadowAppLinkLabels, type MeadowAppLinkOverrides, } from './app-links.model.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EACL,+BAA+B,EAC/B,oBAAoB,EACpB,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EACL,8BAA8B,EAC9B,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,GAC5B,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { MeadowAppBuildComponent } from './app-build.component.js';
2
+ export { DEFAULT_MEADOW_APP_BUILD_LABELS, formatMeadowAppBuild, } from './app-build.model.js';
3
+ export { MeadowAppLinksComponent } from './app-links.component.js';
4
+ export { DEFAULT_MEADOW_APP_LINK_LABELS, meadowAppLinks, } from './app-links.model.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EACL,+BAA+B,EAC/B,oBAAoB,GAErB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EACL,8BAA8B,EAC9B,cAAc,GAKf,MAAM,sBAAsB,CAAC"}
package/docs/CLI.md ADDED
@@ -0,0 +1,389 @@
1
+ # Meadow CLI
2
+
3
+ The Meadow CLI turns an app idea into a validated standalone repository with the repetitive mobile
4
+ foundation already installed. It intentionally generates ordinary project files: the app owns its
5
+ product code and design, while Meadow supplies the common toolchain, integrations, checks, and release
6
+ guardrails.
7
+
8
+ Read the [Meadow Platform guide](PLATFORM_GUIDE.md) first for the overall idea-to-release system,
9
+ capability map, ownership boundaries, and current maturity limits.
10
+
11
+ ## Requirements
12
+
13
+ - Node 24.15.x and npm 11
14
+ - Git
15
+ - Xcode for local iOS builds
16
+ - Android Studio/JDK 21 for local Android builds
17
+ - GitHub CLI only when creating a remote repository
18
+
19
+ Install `@meadow-studio/platform` from npm at an exact version, then run `meadow` through its package
20
+ binary. During platform development, a local file installation is supported.
21
+
22
+ ## Create an app
23
+
24
+ ```sh
25
+ meadow new <name>
26
+ ```
27
+
28
+ The app stays at the repository root. A second, static project is created in `website/` with home,
29
+ support, privacy, and terms pages. Both projects share one Git repository. To plan a subdomain, pass
30
+ `--website-base-domain meadow-development.app`; Flockbook then gets
31
+ `https://flockbook.meadow-development.app/` in `links.websiteUrl`. The domain is optional until it
32
+ is purchased. DNS, hosting, TLS, and publication are separate setup steps.
33
+
34
+ The privacy page starts with Meadow Development's publisher and support details, and reusable
35
+ explanations of the separately consented Firebase Analytics and Crashlytics services. New app
36
+ configs use `oestbalmer@gmail.com` as the support email unless another address is supplied.
37
+ The page is a draft with `noindex`: review the final app's data, events, retention, deletion,
38
+ website hosting, publisher address, and effective date before publication. The generated page
39
+ must match actual native behavior and store privacy disclosures.
40
+
41
+ Interactive creation asks for the display name, bundle/application ID, optional website base domain,
42
+ store links, supported orientation and device classes, and whether the app needs RevenueCat or Supabase. Firebase
43
+ Analytics and Crashlytics are part of the base stack but remain unconfigured until app-owned native
44
+ configuration is supplied.
45
+
46
+ Useful options:
47
+
48
+ ```text
49
+ --yes Use safe defaults without prompts
50
+ --config <file> Read answers or a full Meadow config from JSON
51
+ --website-base-domain <name> Derive the companion subdomain from the app slug
52
+ --directory <path> Choose the parent directory
53
+ --github Create and push a GitHub repository
54
+ --github-owner <owner> Choose a GitHub account or organization
55
+ --visibility <value> private, internal, or public; defaults to private
56
+ --no-install Write files without installing or validating
57
+ --no-git Do not create the local Git repository
58
+ --skip-visual-baselines Defer baseline screenshot generation
59
+ ```
60
+
61
+ Creation is atomic. The final directory appears only after dependency installation, formatting,
62
+ native-project generation, unit tests, linting, and production/device builds succeed. A normal
63
+ creation also installs Chromium and creates initial phone and tablet screenshot baselines. The
64
+ repository receives an initial gitmoji commit unless `--no-git` is used.
65
+
66
+ Each generated repository includes:
67
+
68
+ - Angular 22 standalone application code and strict TypeScript;
69
+ - a separate, dependency-free `website/` project with editable home, support, privacy, and terms pages;
70
+ - Capacitor 8 iOS and Android projects;
71
+ - Firebase Analytics and Crashlytics native dependencies;
72
+ - optional RevenueCat and Supabase client dependencies;
73
+ - provider-neutral `@meadow-studio/platform` runtime APIs;
74
+ - Vitest unit tests with 80% line/function/statement and 70% branch thresholds;
75
+ - Playwright phone and tablet screenshot tests;
76
+ - formatting, linting, web, device, Android, and unsigned iOS build commands;
77
+ - GitHub Actions for pull-request verification and manual visual-baseline generation;
78
+ - exact dependency versions, immutable GitHub Action hashes, and dependency auditing;
79
+ - release, CI, signing, and store checklists;
80
+ - an editable root-level `PRODUCT_BRIEF.md` template for audience, core jobs, product rules,
81
+ experience, the first usable flow, and deferred ideas;
82
+ - an `inspiration/README.md` where app owners can add visual references with notes about what to
83
+ borrow for specific screens or flows;
84
+ - an `AGENTS.md` pointer to the capability guide bundled with the app's pinned platform version and
85
+ a repository-local `.agents/skills/meadow-app-development/SKILL.md` for normal app development; and
86
+ - a `.gitignore` that excludes generated web/native output, local configuration, signing files,
87
+ and test reports.
88
+
89
+ The template deliberately does not include Ionic or Meadow Design. An app may adopt either as an
90
+ app-owned decision, but neither is part of the Meadow foundation.
91
+
92
+ ## Adopt an existing app
93
+
94
+ In a newly created, empty Git checkout, `meadow init` generates the full app and companion website
95
+ directly in that repository. The checkout must contain only `.git`; Meadow preserves its Git history
96
+ and remote and does not create or push another repository. The display name defaults to the checkout
97
+ directory name, and the command prompts for app details unless `--yes` is supplied. Use
98
+ `--website-base-domain meadow-development.app` to plan the app's subdomain. `--dry-run` lists the
99
+ files without writing. With installation enabled, initialization runs the same app, native, and
100
+ visual validation as `meadow new`. Build tools may print paths inside a temporary `.meadow-init-*`
101
+ directory during validation; Meadow moves the completed project into the existing checkout only after
102
+ every step succeeds.
103
+
104
+ The generated project includes Firebase Analytics and Crashlytics dependencies by default. Both
105
+ native collection switches start disabled; production collection requires each service's separate
106
+ consent and app-owned Firebase configuration. The app must provide the actual consent interface.
107
+
108
+ For an existing Angular and Capacitor application, `init` follows the adoption flow below.
109
+
110
+ Use `init` inside an existing Angular 22 and Capacitor 8 application:
111
+
112
+ ```sh
113
+ meadow init --dry-run
114
+ meadow init
115
+ ```
116
+
117
+ Initialization also creates `website/` if it is missing. If the app already has a website project
118
+ in that directory, Meadow leaves it intact. `--dry-run` includes the website plan without writing.
119
+ It also adds `PRODUCT_BRIEF.md` when missing and preserves an existing brief.
120
+ It creates `inspiration/README.md` when missing and preserves existing reference notes and images.
121
+ The optional `--website-base-domain` sets a missing planned website URL; it does not replace an
122
+ existing URL in `meadow.config.json`.
123
+
124
+ The command inspects `package.json`, `angular.json`, and the Capacitor configuration before making
125
+ changes. It infers the display name, application ID, package version, and whether RevenueCat or
126
+ Supabase is already in use. Unsupported Angular or Capacitor major versions are rejected before any
127
+ file is written. Interactive mode asks for a missing website base domain and whether to add optional
128
+ providers that are not already detectable; use `--config` to override other inferred metadata.
129
+
130
+ The adoption plan can:
131
+
132
+ - create `meadow.config.json` when it is missing, while preserving an existing valid configuration;
133
+ - install a pinned `@meadow-studio/platform` and missing shared provider dependencies;
134
+ - add only missing Meadow-owned package scripts, leaving existing scripts unchanged;
135
+ - create `.nvmrc` only when the app does not already have one;
136
+ - add or refresh marked Meadow sections in `AGENTS.md`, `.gitignore`, and `.env.example`;
137
+ - add the app-development skill when it is missing, preserving any existing copy; and
138
+ - install dependencies and finish by printing the complete `meadow doctor` result.
139
+
140
+ Useful options:
141
+
142
+ ```text
143
+ --dry-run Print the complete plan without writing or installing
144
+ --yes Accept inferred values without prompts
145
+ --config <file> Override inferred answers with JSON
146
+ --website-base-domain <name> Set a missing planned companion website URL
147
+ --directory <path> Initialize a project outside the current directory
148
+ --platform-spec <value> Install or intentionally replace the platform dependency spec
149
+ --no-install Update files without running npm install
150
+ ```
151
+
152
+ Managed sections are delimited by `meadow-platform:start` and `meadow-platform:end`. Re-running `init`
153
+ updates only those sections and is otherwise idempotent. A malformed or half-present marker pair is
154
+ treated as an error rather than risking app-owned content.
155
+
156
+ `init` establishes the Meadow control plane; it does not blindly replace application code, existing
157
+ CI, test configuration, Angular or Capacitor versions, or app-specific architecture. `meadow doctor`
158
+ reports missing pieces of the complete release-oriented foundation so they can be adopted
159
+ deliberately. Ionic and other app-owned dependencies are retained and reported without becoming
160
+ Meadow Platform dependencies.
161
+
162
+ ## Synchronize typed configuration
163
+
164
+ `meadow.config.json` version 2 is the source of truth for durable application and release intent:
165
+
166
+ - display name, slug, and separate iOS and Android identifiers;
167
+ - enabled platforms, device classes, and orientation;
168
+ - semantic version, build number, and release channel;
169
+ - development, test, and production runtime behavior;
170
+ - support, privacy, terms, website, App Store, and Play Store links;
171
+ - enabled Firebase, RevenueCat, Supabase, local-data, and local-notification capabilities;
172
+ - RevenueCat entitlement, offering, and product identifiers;
173
+ - the Supabase project reference and names of variables containing public client configuration;
174
+ - analytics events and typed property definitions; and
175
+ - CI screenshot viewports.
176
+
177
+ For a Meadow-generated companion site, `meadow sync` also updates `website/site.config.json` with
178
+ the app name, description, planned URL, and support email. Website page content and styling stay
179
+ app-owned. Use `npm run website:start` to preview the site and `npm run website:check` to build it.
180
+ Draft support and legal content must be replaced and `noindex` removed before publication.
181
+
182
+ After editing the config, run:
183
+
184
+ ```sh
185
+ meadow sync
186
+ ```
187
+
188
+ Synchronization updates:
189
+
190
+ - `package.json` release metadata, platform/capability dependencies, and Meadow scripts;
191
+ - `capacitor.config.ts` app identity and generated environment files;
192
+ - app-owned generated runtime configuration and typed analytics APIs under `src/app/meadow/`;
193
+ - the local-service configuration generator used before development and production builds;
194
+ - Playwright viewport projects;
195
+ - Android application ID, display name, orientation, version, and build metadata when present; and
196
+ - iOS bundle ID, display name, orientation, version, and build metadata when present.
197
+
198
+ When dependencies change, the command runs `npm install`; use `--no-install` when a separate process
199
+ will update the lockfile. Generated TypeScript and configuration files carry a warning header. Meadow
200
+ will not replace a conflicting unmarked file at one of those paths.
201
+
202
+ Use the read-only form locally and in CI:
203
+
204
+ ```sh
205
+ meadow sync --check
206
+ ```
207
+
208
+ It exits unsuccessfully when normalized configuration, dependencies, generated source, native
209
+ metadata, or testing viewports have drifted. `meadow doctor` includes the same drift check.
210
+
211
+ Analytics definitions generate an app-owned, compile-time API. For example:
212
+
213
+ ```json
214
+ {
215
+ "analytics": {
216
+ "events": {
217
+ "pushups_logged": {
218
+ "properties": {
219
+ "reps": { "type": "integer", "required": true },
220
+ "source": {
221
+ "type": "string",
222
+ "required": false,
223
+ "values": ["home", "notification"]
224
+ }
225
+ }
226
+ }
227
+ }
228
+ }
229
+ }
230
+ ```
231
+
232
+ This produces an `AppAnalytics` wrapper that rejects unknown events, missing required properties,
233
+ wrong value types, and invalid enumerated strings during TypeScript compilation.
234
+
235
+ Never put credentials, service-role keys, signing material, or other secrets in
236
+ `meadow.config.json`. Supabase and RevenueCat configuration records variable names and public product
237
+ identifiers; actual environment values remain external. Generated apps run `npm run
238
+ services:config` before serving or building. It reads local public client values and writes the
239
+ ignored `public/meadow-service-config.js` runtime asset.
240
+
241
+ ## Add local notifications
242
+
243
+ From a generated app, add native local notifications with:
244
+
245
+ ```sh
246
+ meadow add notifications
247
+ ```
248
+
249
+ The recipe pins `@capacitor/local-notifications`, updates `meadow.config.json`, installs the package,
250
+ synchronizes each existing native project, updates the generated runtime and release checklist,
251
+ and runs the app checks before marking the capability configured. If installation or native sync
252
+ is interrupted, rerun the same command; an enabled but unconfigured capability is resumable.
253
+
254
+ The runtime does not request permission during initialization or scheduling. The app explains the
255
+ benefit and calls `MeadowNotificationService.requestPermission()` from a user action. The app also
256
+ owns notification IDs, copy, schedule rules, Android channels, tap navigation, and analytics.
257
+ Meadow owns provider adaptation, permission state, one-off and recurring calendar scheduling,
258
+ replace/cancel/pending operations, tap events, safe web behavior, and normalized failures.
259
+
260
+ Android schedules are inexact by default. Do not add exact-alarm permission unless a concrete app
261
+ requires exact timing and its store/disclosure implications have been reviewed. Before release,
262
+ test grant and denial behavior, scheduling, replacement, cancellation, the Android channel, and
263
+ tap navigation on both enabled platforms.
264
+
265
+ ## Add local data
266
+
267
+ From a generated app, add the proven local-data foundation with:
268
+
269
+ ```sh
270
+ meadow add local-data
271
+ ```
272
+
273
+ The recipe installs pinned SQLite dependencies, synchronizes both native projects, and generates:
274
+
275
+ - a Meadow-owned `LocalDatabase` wrapper with parameterized queries, writes, and transactions;
276
+ - sequential, immutable database migrations;
277
+ - a small typed JSON document store for settings and other simple records;
278
+ - an example unit test and app-repository guidance;
279
+ - the SQLite WebAssembly runtime for browser development; and
280
+ - Android backup exclusions plus local-data release checks.
281
+
282
+ iOS and Android use native SQLite. Browser development uses the same SQLite engine persisted in
283
+ IndexedDB, avoiding a second storage behavior just for web previews. Application-specific tables,
284
+ models, validation, and repositories stay in the app rather than `@meadow-studio/platform`.
285
+
286
+ If installation or validation is interrupted, rerun the same command. Meadow records the incomplete
287
+ recipe, preserves any generated file you changed while fixing the problem, fills in missing files,
288
+ and validates the capability again before marking it configured.
289
+
290
+ After adding a migration, update `services.localData.databaseVersion` in `meadow.config.json` to match
291
+ the final migration. Never edit a migration that has shipped. Before release, test both a fresh
292
+ database and an upgrade from the previous app version, verify deletion/reset behavior, and review
293
+ the generated SQLCipher export-compliance checklist item.
294
+
295
+ ## Configure integrations
296
+
297
+ Run configuration commands from the generated app directory:
298
+
299
+ ```sh
300
+ meadow configure firebase \
301
+ --google-services /path/to/google-services.json \
302
+ --google-service-info /path/to/GoogleService-Info.plist
303
+
304
+ meadow configure revenuecat \
305
+ --ios-key <public-sdk-key> \
306
+ --android-key <public-sdk-key> \
307
+ --entitlement <id> \
308
+ --offering <id>
309
+
310
+ meadow configure supabase \
311
+ --url https://<project>.supabase.co \
312
+ --publishable-key <publishable-key>
313
+
314
+ meadow configure assets --source /path/to/icon.png
315
+ meadow configure signing
316
+ meadow configure store --support-email <email> --support-url <url> \
317
+ --privacy-url <url> --terms-url <url> --website-url <url> \
318
+ --apple-app-id <id> --app-store-url <url> --play-store-url <url>
319
+ meadow configure github --owner <owner> --visibility private
320
+ ```
321
+
322
+ RevenueCat and Supabase client values go in the ignored `.env.meadow.local`. RevenueCat configuration
323
+ requires a public key only for each enabled native platform, validates the `appl_`, `goog_`, or
324
+ `test_` key prefix, installs the pinned SDK, synchronizes Capacitor, and records the app-owned
325
+ offering and entitlement identifiers. Builds convert those keys into the ignored runtime asset;
326
+ `MeadowPurchaseService` then owns initialization, product loading, entitlement state, purchase,
327
+ restore, and provider-error normalization.
328
+
329
+ The Supabase command rejects service-role and secret keys; release readiness still requires
330
+ explicit grants, row-level security, storage policies, and database tests. Firebase configuration
331
+ is required only for the enabled native platforms. The command validates and copies those
332
+ app-owned files, synchronizes Capacitor, installs the Android build plugins, registers the iOS
333
+ configuration file as an app resource, and keeps Analytics and Crashlytics collection off at the
334
+ native layer until the user grants consent. Firebase files are never added to the platform
335
+ package.
336
+
337
+ The application owns the consent screen and copy. Apply the resulting choices through
338
+ `MeadowAnalyticsService.setConsent(...)` and `MeadowCrashReportingService.setConsent(...)`. Choices are
339
+ persisted separately. Development and test environments remain disabled even when a stored
340
+ production consent choice exists.
341
+
342
+ ## Diagnose and release
343
+
344
+ ```sh
345
+ meadow doctor
346
+ meadow doctor --json
347
+ meadow version patch test
348
+ meadow release-check all
349
+ ```
350
+
351
+ `meadow doctor` checks the pinned stack, required files and scripts, native projects, Meadow-generated
352
+ website pages, the local-data
353
+ runtime when enabled, Firebase dependencies, native opt-in defaults, the bundled iOS Firebase
354
+ resource, RevenueCat dependency, platform keys and catalog identifiers, local-notification
355
+ dependency and native synchronization, visual baselines, and integration state. `meadow version`
356
+ increments or sets the semantic app version, increments the build
357
+ number, and synchronizes web, Android, and iOS metadata.
358
+
359
+ `meadow release-check` turns missing native projects, baselines, or enabled-service configuration into
360
+ failures and then runs the complete quality, visual, and selected native build gates. Production
361
+ also requires a website URL plus support, privacy, and terms information.
362
+
363
+ ## Pull-request CI
364
+
365
+ Every generated pull request runs four independent jobs:
366
+
367
+ 1. formatting, linting, dependency audit, coverage-gated unit tests, production app web build,
368
+ and companion website build;
369
+ 2. deterministic Playwright screenshot comparisons at phone and tablet sizes;
370
+ 3. Android debug compilation on Linux with JDK 21; and
371
+ 4. an unsigned iOS simulator build on macOS.
372
+
373
+ Successful Android jobs upload `android-debug-apk`, a downloadable debug APK in the Actions run.
374
+ The visual job uploads `playwright-report` with the HTML report and screenshot results. Playwright
375
+ also adds GitHub test annotations; a separate trusted workflow comments on a PR when screenshot
376
+ comparisons fail, naming the failures and linking to the downloadable report. This reports failures
377
+ without requiring a preview host or a custom token for inline image attachments.
378
+
379
+ CI installs the exact public `@meadow-studio/platform` version from npm using the committed lockfile. No
380
+ Meadow package secret or source-repository access is needed, including for fork pull requests. The
381
+ version must be published before a default `meadow init` install can run.
382
+
383
+ CI never updates screenshots implicitly. The visual comparison and baseline workflow both use the
384
+ same pinned macOS runner family as the local Meadow development environment. Use the manual **Generate
385
+ visual baselines** workflow to produce candidates, inspect the artifact, then commit intentional
386
+ changes. Generated visual test commands select an available local port for their Angular server, so
387
+ an unrelated process on Angular's default port 4200 does not block initialization or local screenshot
388
+ tests. Playwright never reuses an existing server for these checks.
389
+ When Playwright is invoked directly, its generated configuration defaults to port 4400.