Skip to content

Latest commit

 

History

History
879 lines (694 loc) · 62.8 KB

File metadata and controls

879 lines (694 loc) · 62.8 KB

Appllama

React Native Expo Paywalls — 10 Interactive Subscription Screens

An open-source collection of stateful paywall, subscription-plan, free-trial, downsell, and in-app purchase UI studies inspired by leading mobile apps.

CI 10 paywall studies 19 registered variants Expo SDK 57 React Native 0.86 TypeScript strict GPL-3.0 License

Explore paywalls · Copy a prompt · Run locally · Use the API · Legal notice

React Native Expo paywall showcase featuring ChatGPT, Cleanup, Facetune, Flo, and Learna studies

React Native Expo paywall showcase featuring MyFitnessPal, Perplexity, PictureThis, Strava, and YAZIO studies

Important

Educational reference only. This is an independent, unofficial Appllama project and is not affiliated with or endorsed by any referenced company. The repository grants no permission to use third-party commercial intellectual property. Do not ship these screens unchanged. Before public or commercial use, replace every third-party name, logo, image, phrase, price presentation, color system, and other brand element, then make the final design meaningfully unique. Read the full intellectual-property notice.

10 studies. 19 variants. One Expo project.

Top Paywalls is a React Native Expo UI kit for studying how polished subscription experiences behave—not merely how they look. The examples include real local plan selection, tier switching, scrollable comparison content, a native testimonial pager, nested horizontal and vertical scrolling, trial toggles, animated sheets, a sequential downsell, static blur surfaces, accessible controls, haptics, and typed semantic action IDs.

You can:

  • run all ten studies from one Expo Router gallery;
  • open any registered state with a deterministic deep link;
  • copy one named component into an existing Expo app without adopting the gallery;
  • paste a paywall-specific integration prompt into Codex, Claude Code, Cursor, or another coding agent;
  • connect visible controls to your own billing, restore, close, and legal flows; and
  • inspect the exact state transitions and generated-asset provenance.

The project comes from the product-flow research behind Appllama, a library for studying onboarding, paywall, and product UI from leading iOS apps.

Note

The demo does not perform a real App Store or Google Play purchase. Prices, product names, trial language, and renewal copy are visual research data. A production host must supply its own localized product catalog, eligibility checks, billing SDK, restore flow, legal destinations, analytics, and error handling.

The 10 paywall studies

UI study Paywall ID Component Registered variants Interaction model Source Agent prompt
ChatGPT-inspired chatgpt ChatGptPaywall plus, go Animated segmented tier and scrolling feature comparison View source Copy prompt
Cleanup-inspired cleanup CleanupPaywall smart-cleanup, unlimited Separate compositions; weekly/lifetime selection in Unlimited View source Copy prompt
Facetune-inspired facetune FacetunePaywall trial, vip Trial explainer → VIP plans, plan selection, static blur palette View source Copy prompt
Flo-inspired flo FloPaywall plans, all-plans Testimonial pager, trial toggle, animated draggable plan sheet View source Copy prompt
Learna-inspired learna LearnaPaywall personalized, trial Two externally selected fixed-layout compositions View source Copy prompt
MyFitnessPal-inspired myfitnesspal MyFitnessPalPaywall standard, offer Plan selection, close → downsell, animated Learn More sheet View source Copy prompt
Perplexity-inspired perplexity PerplexityPaywall pro, max Animated tier state, remembered Pro plan, draggable model rail View source Copy prompt
PictureThis-inspired picturethis PictureThisPaywall trial, comparison Trial plan/reminder controls or a separate Plus/Pro comparison View source Copy prompt
Strava-inspired strava StravaPaywall bundle, improvements Separate fixed bodies with fixed purchase sheets View source Copy prompt
YAZIO-inspired yazio YazioPaywall default Vertical paywall scroll, snapping review rail, sticky CTA View source Copy prompt

Bold variants are registry defaults. A registered variant can represent either an alternate starting composition or a reachable state in the same experience. The distinction matters; it is documented precisely in INTERACTION_SPEC.md.

Copy-paste integration prompts

Open one section, use GitHub’s copy button, and paste the complete prompt into a coding agent while it is working inside your existing Expo app. Each prompt is scoped to one component and tells the agent to follow only its transitive assets, helpers, packages, fonts, states, and actions.

The prompts deliberately protect the target app’s existing routing, billing, state, and design system. They also require replacement of third-party commercial identity before release.

ChatGPT-inspired Go / Plus paywall — copy prompt
You are working inside my existing Expo React Native repository.

Use https://github.com/Appllama/top-paywall-screens as a read-only technical reference. Integrate only the ChatGPT-inspired paywall into my app. Do not turn my app into the gallery, do not copy unrelated paywalls, and do not modify unrelated features.

Reference files:
- src/paywalls/chatgpt.tsx
- src/paywalls/types.ts
- src/paywalls/shared/actions.ts, pressable.tsx, reference-canvas.tsx, and geometry.ts, following only actual transitive imports
- the ChatGPT section of docs/INTERACTION_SPEC.md
- src/app/_layout.tsx only as a font-loading reference
- NOTICE.md

Public contract:
- Component: ChatGptPaywall
- Paywall ID: chatgpt
- Registered variants: plus (default), go
- Fonts: Inter_400Regular, Inter_500Medium, Inter_600SemiBold
- App-specific raster assets: none; the marks, comparison table, and controls are code-native
- Semantic actions: chatgpt.select-go, chatgpt.select-plus, chatgpt.close, chatgpt.upgrade-go, chatgpt.upgrade-plus, chatgpt.purchase-on-web, chatgpt.learn-more
- Relevant packages: expo-font, expo-haptics, expo-linear-gradient, expo-status-bar, @expo-google-fonts/inter, react-native-reanimated, react-native-svg, and react-native-worklets

Requirements:
1. Before editing, inspect my Expo SDK, React Native version, router, package manager, font loading, billing architecture, product catalog, legal routes, and existing dependencies.
2. Copy only ChatGptPaywall and the transitive shared helpers it imports. Do not copy the demo router, gallery, Zustand store, or another paywall.
3. Preserve my package versions, navigation, state architecture, design system, app configuration, and native projects. Install only missing SDK-compatible packages with npx expo install.
4. Load the exact Inter aliases before revealing the screen. Adapt loading to my existing root instead of replacing it.
5. Mount the component in a full-height flex: 1 surface with no visible navigation header or surrounding safe-area padding; it owns a calibrated 390×844 ReferenceCanvas and status bar.
6. Preserve the actual experience: Go/Plus segmented selection, the 210 ms pill/content transition, the tier-specific vertically scrolling comparison viewport, fixed lower purchase area, plan-specific CTA text, replayKey reset, and accessible tab state. Do not replace it with a static screenshot or generic fade.
7. Wire semantic actions to my host. Connect only explicit upgrade actions to my real billing flow; map close, web purchase, and Learn More separately. Do not infer product IDs from the reference price strings.
8. Keep production pricing, eligibility, renewal terms, localization, loading, purchase errors, and restore behavior driven by my billing source of truth.
9. Before public or commercial release, replace every third-party name, mark, phrase, price presentation, color treatment, and recognizable composition with authorized original branding and a meaningfully unique design.
10. Validate both tiers, feature scrolling, every action, replay, TypeScript, lint, an iPhone simulator, and one Android viewport. Finish by listing every changed file and dependency.

Cleanup-inspired Smart Cleanup / Unlimited paywalls — copy prompt
You are working inside my existing Expo React Native repository.

Use https://github.com/Appllama/top-paywall-screens as a read-only technical reference. Integrate only the Cleanup-inspired paywall into my app. Do not turn my app into the gallery, do not copy unrelated paywalls, and do not modify unrelated features.

Reference files:
- src/paywalls/cleanup.tsx
- assets/paywalls/cleanup/photos-tile.png and assets/paywalls/cleanup/icloud-tile.png
- src/paywalls/types.ts
- src/paywalls/shared/actions.ts, pressable.tsx, reference-canvas.tsx, and geometry.ts, following only actual transitive imports
- the Cleanup section of docs/INTERACTION_SPEC.md
- src/app/_layout.tsx only as a font and asset-preloading reference
- docs/ASSET_PROVENANCE.md and NOTICE.md

Public contract:
- Component: CleanupPaywall
- Paywall ID: cleanup
- Registered variants: smart-cleanup (default), unlimited
- Fonts: Inter_400Regular, Inter_500Medium, Inter_600SemiBold, Inter_700Bold, Inter_800ExtraBold, plus native system/SF text for the calibrated Smart Cleanup subtitle and tile labels
- Semantic actions, Smart Cleanup: cleanup.restore, cleanup.try-free, cleanup.privacy-policy, cleanup.terms-of-use
- Semantic actions, Unlimited: cleanup.close, cleanup.select-weekly, cleanup.select-lifetime, cleanup.start-trial, cleanup.buy-lifetime, cleanup.terms, cleanup.restore
- Relevant packages: expo-asset, expo-font, expo-haptics, expo-image, expo-linear-gradient, expo-status-bar, @expo-google-fonts/inter, react-native-reanimated, and react-native-worklets

Requirements:
1. Before editing, inspect my Expo SDK, React Native version, router, package manager, font and image loading, billing architecture, product catalog, legal routes, and existing dependencies.
2. Copy only CleanupPaywall, its two generated art tiles, and the transitive shared helpers it imports. Do not copy the demo router, gallery, Zustand store, or another paywall.
3. Preserve my package versions, navigation, state architecture, design system, app configuration, and native projects. Install only missing SDK-compatible packages with npx expo install.
4. Load the exact Inter aliases and the two selected images before revealing the screen, and preserve the native system/SF styles where used. Preserve image aspect ratios and adapt preloading to my root.
5. Mount the component in a full-height flex: 1 surface with no visible navigation header or surrounding safe-area padding; it owns a calibrated 390×844 ReferenceCanvas and status bar.
6. Treat smart-cleanup and unlimited as externally selected compositions—do not add a visible switch. Preserve the 680 ms storage fills, Unlimited weekly/lifetime selection, 190 ms selection transition, plan-specific CTA, vertical content behavior, replayKey reset, and accessibility state. Plan choices emit typed semantic actions without changing the registered composition.
7. Wire try-free/start-trial/buy-lifetime to distinct products in my billing layer, and wire restore, close, privacy, and terms to their existing host destinations. Do not infer product IDs from visible strings.
8. Keep production pricing, trial eligibility, renewal terms, localization, loading, errors, and restore behavior driven by my billing source of truth.
9. Before public or commercial release, replace every third-party name, icon treatment, phrase, statistic, price presentation, color system, and recognizable composition with authorized original material and a meaningfully unique design.
10. Validate both registered variants, both Unlimited plans, storage motion, scrolling, every action, replay, TypeScript, lint, an iPhone simulator, and one Android viewport. Finish by listing every changed file and dependency.

Facetune-inspired trial timeline / VIP paywall — copy prompt
You are working inside my existing Expo React Native repository.

Use https://github.com/Appllama/top-paywall-screens as a read-only technical reference. Integrate only the Facetune-inspired paywall into my app. Do not turn my app into the gallery, do not copy unrelated paywalls, and do not modify unrelated features.

Reference files:
- src/paywalls/facetune.tsx
- assets/paywalls/facetune/hero.png
- src/paywalls/types.ts
- src/paywalls/shared/actions.ts, pressable.tsx, reference-canvas.tsx, and geometry.ts, following only actual transitive imports
- the Facetune section of docs/INTERACTION_SPEC.md
- src/app/_layout.tsx only as a font and asset-preloading reference
- docs/ASSET_PROVENANCE.md and NOTICE.md

Public contract:
- Component: FacetunePaywall
- Paywall ID: facetune
- Registered variants: trial (default), vip
- Fonts: Manrope_400Regular, Manrope_500Medium, Manrope_600SemiBold, Manrope_700Bold, Manrope_800ExtraBold
- Semantic actions: facetune.restore, facetune.close, facetune.start-yearly-trial, facetune.show-all-plans, facetune.select-yearly, facetune.select-weekly, facetune.continue-yearly, facetune.continue-weekly
- Relevant packages: expo-asset, expo-blur, expo-font, expo-haptics, expo-image, expo-status-bar, @expo-google-fonts/manrope, react-native-reanimated, react-native-svg, and react-native-worklets

Requirements:
1. Before editing, inspect my Expo SDK, React Native version, router, package manager, font and image loading, billing architecture, product catalog, legal routes, and existing dependencies.
2. Copy only FacetunePaywall, its generated hero, and the transitive shared helpers it imports. Do not copy the demo router, gallery, Zustand store, or another paywall.
3. Preserve my package versions, navigation, state architecture, design system, app configuration, and native projects. Install only missing SDK-compatible packages with npx expo install.
4. Load the exact Manrope aliases and hero before revealing the screen. Preserve the asset aspect ratio and adapt preloading to my root.
5. Mount the component in a full-height flex: 1 surface with no visible navigation header or surrounding safe-area padding; it owns a calibrated 390×844 ReferenceCanvas and status bar.
6. Preserve the state machine: trial is a timeline explainer; Show all plans performs the one-way trial → vip transition with a 230 ms crossfade; VIP starts yearly, supports weekly/yearly selection with a 190 ms transition, and uses a real static BlurView palette. Replay restores initialVariant. Do not make the decorative palette interactive.
7. Wire the yearly-trial and continue actions to my eligible billing products, and wire restore/close independently. `onVariantChange` reports the supported trial-to-VIP composition transition; plan changes use their typed semantic action IDs.
8. Keep production pricing, eligibility, renewal terms, localization, loading, purchase errors, and restore behavior driven by my billing source of truth.
9. Before public or commercial release, replace every third-party name, image, phrase, price presentation, palette, color system, and recognizable composition with authorized original material and a meaningfully unique design.
10. Validate both starting variants, the one-way transition, both plans, blur rendering, every action, replay, TypeScript, lint, an iPhone simulator, and one Android viewport. Finish by listing every changed file and dependency.

Flo-inspired plans and draggable all-plans sheet — copy prompt
You are working inside my existing Expo React Native repository.

Use https://github.com/Appllama/top-paywall-screens as a read-only technical reference. Integrate only the Flo-inspired paywall into my app. Do not turn my app into the gallery, do not copy unrelated paywalls, and do not modify unrelated features.

Reference files:
- src/paywalls/flo.tsx
- src/paywalls/types.ts
- src/paywalls/shared/actions.ts, pressable.tsx, reference-canvas.tsx, geometry.ts, pager-view.tsx, and pager-view.web.tsx, following only actual transitive imports
- the Flo section of docs/INTERACTION_SPEC.md
- src/app/_layout.tsx only as a font-loading reference
- NOTICE.md

Public contract:
- Component: FloPaywall
- Paywall ID: flo
- Registered variants: plans (default), all-plans
- Fonts: Inter_400Regular, Inter_500Medium, Inter_600SemiBold, Inter_700Bold, Inter_800ExtraBold
- App-specific raster assets: none; the visual UI is code-native
- Semantic actions: flo.close, flo.restore, flo.select-yearly, flo.select-family, flo.select-monthly, flo.toggle-trial, flo.continue-yearly, flo.continue-yearly-trial, flo.continue-family, flo.continue-family-trial, flo.continue-monthly, flo.continue-monthly-trial, flo.view-all-plans, flo.dismiss-all-plans, flo.go-back, flo.subscribe-app-store, flo.limited-access
- Relevant packages: expo-font, expo-haptics, expo-status-bar, @expo-google-fonts/inter, react-native-gesture-handler, react-native-pager-view, react-native-reanimated, react-native-svg, and react-native-worklets

Requirements:
1. Before editing, inspect my Expo SDK, React Native version, router, root GestureHandler setup, package manager, font loading, billing architecture, product catalog, legal routes, and existing dependencies.
2. Copy only FloPaywall and the transitive shared helpers it imports. Do not copy the demo router, gallery, Zustand store, or another paywall.
3. Preserve my package versions, navigation, state architecture, design system, app configuration, and native projects. Install only missing SDK-compatible packages with npx expo install, and keep GestureHandlerRootView at the app root.
4. Load the exact Inter aliases before revealing the screen. Keep the small header mark code-native from the component's SVG geometry, and adapt font loading to my root instead of replacing it.
5. Mount the component in a full-height flex: 1 surface with no visible navigation header or surrounding safe-area padding; it owns a calibrated 390×844 ReferenceCanvas and status bar.
6. Preserve the complete experience: swipeable/auto-advancing testimonial PagerView, yearly/family featured plans, trial toggle, vertically scrollable lower content, View all plans transition, dimmed backdrop, 310 ms sheet entrance, 260 ms exit, yearly/family/monthly choices, and downward drag dismissal at the documented distance/velocity thresholds. Do not replace the sheet or pager with static artwork.
7. Wire each plan/trial combination to the correct product and eligibility in my billing layer. Keep App Store subscription, limited access, restore, close, and sheet-dismiss actions semantically distinct.
8. Keep production pricing, trial eligibility, renewal terms, localization, loading, purchase errors, and restore behavior driven by my billing source of truth. Respect reduced-motion expectations in my production adaptation even though the reference transitions are not currently gated.
9. Before public or commercial release, replace every third-party name, phrase, testimonial, price presentation, color system, and recognizable composition with authorized original material and a meaningfully unique design.
10. Validate both registered starts, pager swipes, automatic paging, all plan/trial combinations, sheet backdrop and pan dismissal, scrolling, every action, replay, TypeScript, lint, an iPhone simulator, and one Android viewport. Finish by listing every changed file and dependency.

Learna-inspired personalized / trial paywalls — copy prompt
You are working inside my existing Expo React Native repository.

Use https://github.com/Appllama/top-paywall-screens as a read-only technical reference. Integrate only the Learna-inspired paywall into my app. Do not turn my app into the gallery, do not copy unrelated paywalls, and do not modify unrelated features.

Reference files:
- src/paywalls/learna.tsx
- assets/paywalls/learna/hero.png
- src/paywalls/types.ts
- src/paywalls/shared/actions.ts, pressable.tsx, reference-canvas.tsx, and geometry.ts, following only actual transitive imports
- the Learna section of docs/INTERACTION_SPEC.md
- src/paywalls/assets.ts and src/app/_layout.tsx only as Learna hero preloading and font-loading references; use only the Learna asset entry
- docs/ASSET_PROVENANCE.md and NOTICE.md

Public contract:
- Component: LearnaPaywall
- Paywall ID: learna
- Registered variants: personalized (default), trial
- Fonts: Nunito_400Regular, Nunito_700Bold, Nunito_800ExtraBold, Nunito_900Black
- Semantic actions: learna.close, learna.restore, learna.try-free, learna.privacy, learna.terms
- Relevant packages: expo-asset, expo-font, expo-haptics, expo-image, expo-linear-gradient, expo-status-bar, @expo-google-fonts/nunito, and react-native-svg

Requirements:
1. Before editing, inspect my Expo SDK, React Native version, router, package manager, font and image loading, billing architecture, product catalog, legal routes, and existing dependencies.
2. Copy only LearnaPaywall, its generated robot hero, and the transitive shared helpers it imports. Do not copy the demo router, gallery, Zustand store, or another paywall.
3. Preserve my package versions, navigation, state architecture, design system, app configuration, and native projects. Install only missing SDK-compatible packages with npx expo install.
4. Load the exact Nunito aliases and hero before revealing the screen. Preserve its aspect ratio and adapt preloading to my root.
5. Mount the component in a full-height flex: 1 surface with no visible navigation header or surrounding safe-area padding; it owns a calibrated 390×844 ReferenceCanvas and status bar.
6. Treat personalized and trial as externally selected fixed compositions. Do not add an in-paywall variant switch, scroll, carousel, sheet, or invented entrance animation. Preserve the shared hero, distinct content hierarchy, replayKey reset, exact controls, and accessibility labels.
7. Wire Try Free to my eligible product, Restore to my restore flow, Close to my navigation, and both legal actions to real documents. Do not infer product IDs or eligibility from visible strings.
8. Keep production pricing, trial terms, localization, loading, purchase errors, and restore behavior driven by my billing source of truth.
9. Before public or commercial release, replace every third-party name, robot/character treatment, phrase, price presentation, color system, and recognizable composition with authorized original material and a meaningfully unique design.
10. Validate both registered variants, every action, replay, TypeScript, lint, an iPhone simulator, and one Android viewport. Finish by listing every changed file and dependency.

MyFitnessPal-inspired standard paywall and downsell — copy prompt
You are working inside my existing Expo React Native repository.

Use https://github.com/Appllama/top-paywall-screens as a read-only technical reference. Integrate only the MyFitnessPal-inspired paywall into my app. Do not turn my app into the gallery, do not copy unrelated paywalls, and do not modify unrelated features.

Reference files:
- src/paywalls/myfitnesspal.tsx
- src/paywalls/types.ts
- src/paywalls/shared/actions.ts, pressable.tsx, reference-canvas.tsx, and geometry.ts, following only actual transitive imports
- the MyFitnessPal section of docs/INTERACTION_SPEC.md
- src/app/_layout.tsx only as a font-loading reference
- NOTICE.md

Public contract:
- Component: MyFitnessPalPaywall
- Paywall ID: myfitnesspal
- Registered variants: standard (default), offer
- Fonts: Inter_400Regular, Inter_500Medium, Inter_600SemiBold, Inter_700Bold, Inter_700Bold_Italic
- App-specific raster assets: none; the ticket, icons, gradients, cards, and controls are code-native
- Semantic actions: myfitnesspal.select-annual, myfitnesspal.select-monthly, myfitnesspal.close-to-offer, myfitnesspal.try-free-annual, myfitnesspal.try-free-monthly, myfitnesspal.upgrade-promo, myfitnesspal.select-promo-annual, myfitnesspal.no-thanks, myfitnesspal.learn-more, myfitnesspal.dismiss-learn-more
- Relevant packages: expo-font, expo-haptics, expo-linear-gradient, expo-status-bar, @expo-google-fonts/inter, react-native-reanimated, react-native-svg, and react-native-worklets

Requirements:
1. Before editing, inspect my Expo SDK, React Native version, router, package manager, font loading, billing architecture, product catalog, offer eligibility, legal routes, and existing dependencies.
2. Copy only MyFitnessPalPaywall and the transitive shared helpers it imports. Do not copy the demo router, gallery, Zustand store, or another paywall.
3. Preserve my package versions, navigation, state architecture, design system, app configuration, and native projects. Install only missing SDK-compatible packages with npx expo install.
4. Load the exact Inter aliases before revealing the screen. Adapt loading to my root instead of replacing it.
5. Mount the component in a full-height flex: 1 surface with no visible navigation header or surrounding safe-area padding; it owns a calibrated 390×844 ReferenceCanvas and status bar.
6. Preserve the sequential state machine: standard starts annual, supports annual/monthly selection, and opens a real Learn More sheet; tapping X transitions to the promotional offer and deliberately does not call the host close callback; the offer has no X; No thanks is the actual dismiss action. Preserve the reduced-motion-aware transitions, sheet backdrop/Got it dismissal, and replay reset.
7. Gate the promotional offer with my real eligibility rules. Wire standard trial, promotional upgrade, and No thanks as distinct actions; do not trigger billing from plan-card selection alone and do not infer product IDs from visible prices.
8. Keep production pricing, trial/offer eligibility, renewal terms, localization, loading, purchase errors, and restore behavior driven by my billing source of truth. Review the downsell sequence for platform policy, consent, accessibility, and product requirements before shipping.
9. Before public or commercial release, replace every third-party name, phrase, price presentation, color system, ticket treatment, and recognizable composition with authorized original material and a meaningfully unique design.
10. Validate both starting variants, standard → offer, both standard plans, Learn More open/dismiss, No thanks, every action, replay, reduced motion, TypeScript, lint, an iPhone simulator, and one Android viewport. Finish by listing every changed file and dependency.

Perplexity-inspired Pro / Max paywall — copy prompt
You are working inside my existing Expo React Native repository.

Use https://github.com/Appllama/top-paywall-screens as a read-only technical reference. Integrate only the Perplexity-inspired paywall into my app. Do not turn my app into the gallery, do not copy unrelated paywalls, and do not modify unrelated features.

Reference files:
- src/paywalls/perplexity.tsx
- src/paywalls/types.ts
- src/paywalls/shared/actions.ts, pressable.tsx, reference-canvas.tsx, and geometry.ts, following only actual transitive imports
- the Perplexity section of docs/INTERACTION_SPEC.md
- src/app/_layout.tsx only as a font-loading reference
- NOTICE.md

Public contract:
- Component: PerplexityPaywall
- Paywall ID: perplexity
- Registered variants: pro (default), max
- Fonts: Inter_400Regular, Inter_500Medium, Inter_600SemiBold, Inter_800ExtraBold
- App-specific raster assets: none; model marks, background, comparison table, cards, and controls are code-native
- Semantic actions: perplexity.select-pro, perplexity.select-max, perplexity.select-yearly, perplexity.select-monthly, perplexity.select-max-monthly, perplexity.close, perplexity.restore, perplexity.get-pro-yearly, perplexity.get-pro-monthly, perplexity.get-max, perplexity.scroll-models
- Relevant packages: expo-blur, expo-font, expo-haptics, expo-linear-gradient, expo-status-bar, @expo-google-fonts/inter, react-native-reanimated, react-native-svg, and react-native-worklets

Requirements:
1. Before editing, inspect my Expo SDK, React Native version, router, package manager, font loading, billing architecture, product catalog, legal routes, and existing dependencies.
2. Copy only PerplexityPaywall and the transitive shared helpers it imports. Do not copy the demo router, gallery, Zustand store, or another paywall.
3. Preserve my package versions, navigation, state architecture, design system, app configuration, and native projects. Install only missing SDK-compatible packages with npx expo install.
4. Load the exact Inter aliases before revealing the screen. Adapt loading to my root instead of replacing it.
5. Mount the component in a full-height flex: 1 surface with no visible navigation header or surrounding safe-area padding; it owns a calibrated 390×844 ReferenceCanvas and status bar.
6. Preserve the experience: Pro/Max segmented tier, 225 ms reduced-motion-aware transition, crossfading comparison/pricing layers, remembered yearly/monthly Pro selection while moving between tiers, Max’s fixed monthly product, horizontally draggable model strip with tier offsets, static BlurView surfaces, replay reset, and accessible tab/plan state.
7. Wire Pro yearly, Pro monthly, and Max to distinct billing products. Keep plan/tier/model-scroll selection semantic but non-purchasing; wire close and restore separately. Do not infer product IDs from visible prices.
8. Keep production pricing, eligibility, renewal terms, localization, loading, purchase errors, and restore behavior driven by my billing source of truth.
9. Before public or commercial release, replace every third-party name, model/provider mark, phrase, price presentation, blur/color treatment, and recognizable composition with authorized original material and a meaningfully unique design.
10. Validate both tiers, remembered Pro selection, manual model-strip drag, blur rendering, every action, replay, reduced motion, TypeScript, lint, an iPhone simulator, and one Android viewport. Finish by listing every changed file and dependency.

PictureThis-inspired trial / comparison paywalls — copy prompt
You are working inside my existing Expo React Native repository.

Use https://github.com/Appllama/top-paywall-screens as a read-only technical reference. Integrate only the PictureThis-inspired paywall into my app. Do not turn my app into the gallery, do not copy unrelated paywalls, and do not modify unrelated features.

Reference files:
- src/paywalls/picturethis.tsx
- assets/paywalls/picturethis/trial-bg.png and assets/paywalls/picturethis/mosaic.png
- src/paywalls/types.ts
- src/paywalls/shared/actions.ts, pressable.tsx, reference-canvas.tsx, and geometry.ts, following only actual transitive imports
- the PictureThis section of docs/INTERACTION_SPEC.md
- src/app/_layout.tsx only as a font and asset-preloading reference
- docs/ASSET_PROVENANCE.md and NOTICE.md

Public contract:
- Component: PictureThisPaywall
- Paywall ID: picturethis
- Registered variants: trial (default), comparison
- Fonts: the native system sans face (SF Pro on iOS) with explicit 400/600/700 weights
- Semantic actions, Trial: picturethis.select-annual, picturethis.select-monthly, picturethis.reminder-on, picturethis.reminder-off, picturethis.continue-annual, picturethis.continue-monthly, picturethis.cancel, picturethis.terms, picturethis.subscription-terms, picturethis.privacy, picturethis.restore
- Semantic actions, Comparison: picturethis.close, picturethis.get-plus, picturethis.get-pro, picturethis.terms, picturethis.subscription-terms, picturethis.privacy, picturethis.restore
- Relevant packages: expo-asset, expo-haptics, expo-image, expo-linear-gradient, expo-status-bar, react-native-reanimated, react-native-svg, and react-native-worklets

Requirements:
1. Before editing, inspect my Expo SDK, React Native version, router, package manager, font and image loading, billing architecture, product catalog, notification-permission strategy, legal routes, and existing dependencies.
2. Copy only PictureThisPaywall, its two generated art layers, and the transitive shared helpers it imports. Do not copy the demo router, gallery, Zustand store, or another paywall.
3. Preserve my package versions, navigation, state architecture, design system, app configuration, and native projects. Install only missing SDK-compatible packages with npx expo install.
4. Preserve the native system/SF typography and preload the selected images before revealing the screen. Preserve their aspect ratios and adapt preloading to my root.
5. Mount the component in a full-height flex: 1 surface with no visible navigation header or surrounding safe-area padding; it owns a calibrated 390×844 ReferenceCanvas and status bar.
6. Treat trial and comparison as externally selected fixed compositions—do not add a pager between them. Preserve annual/monthly trial selection, reduced-motion-aware selection surfaces, the custom code-native Reanimated reminder switch, replay reset, legal/restore actions, and separate direct Get Plus/Get Pro actions in comparison. Do not turn plan selection or the reminder switch into a purchase.
7. Connect reminder intent to my permission-aware notification flow only after user consent. Wire annual, monthly, Plus, and Pro to distinct eligible products, and wire cancel/close, restore, and legal documents separately.
8. Keep production pricing, trial eligibility, renewal terms, localization, notification permissions, loading, purchase errors, and restore behavior driven by my sources of truth.
9. Before public or commercial release, replace every third-party name, imagery, phrase, price presentation, color system, feature comparison, and recognizable composition with authorized original material and a meaningfully unique design.
10. Validate both variants, both trial plans, reminder on/off, both comparison CTAs, every legal/restore action, replay, reduced motion, TypeScript, lint, an iPhone simulator, and one Android viewport. Finish by listing every changed file and dependency.

Strava-inspired bundle / improvements paywalls — copy prompt
You are working inside my existing Expo React Native repository.

Use https://github.com/Appllama/top-paywall-screens as a read-only technical reference. Integrate only the Strava-inspired paywall into my app. Do not turn my app into the gallery, do not copy unrelated paywalls, and do not modify unrelated features.

Reference files:
- src/paywalls/strava.tsx
- assets/paywalls/strava/bundle-hero.png, assets/paywalls/strava/avatars.png, and assets/paywalls/strava/you-avatar.png
- src/paywalls/types.ts
- src/paywalls/shared/actions.ts, pressable.tsx, reference-canvas.tsx, and geometry.ts, following only actual transitive imports
- the Strava section of docs/INTERACTION_SPEC.md
- src/app/_layout.tsx only as a font and asset-preloading reference
- docs/ASSET_PROVENANCE.md and NOTICE.md

Public contract:
- Component: StravaPaywall
- Paywall ID: strava
- Registered variants: bundle (default), improvements
- Fonts: Inter_400Regular, Inter_600SemiBold, Inter_700Bold, plus native system/SF text where explicitly specified in the Bundle labels, shared subscription toolbar, and Improvements composition
- Semantic actions, common: strava.skip
- Semantic actions, Bundle: strava.select-bundle, strava.select-annual, strava.start-free-trial-bundle, strava.start-free-trial-annual
- Semantic actions, Improvements: strava.start-free-trial-web, strava.pay-in-app
- Relevant packages: expo-asset, expo-font, expo-haptics, expo-image, expo-status-bar, @expo-google-fonts/inter, react-native-reanimated, react-native-svg, and react-native-worklets

Requirements:
1. Before editing, inspect my Expo SDK, React Native version, router, package manager, font and image loading, billing architecture, product catalog, external-checkout policy, legal routes, and existing dependencies.
2. Copy only StravaPaywall, its generated bundle hero, avatar sprite, highlighted-cyclist portrait, and the transitive shared helpers it imports. Do not copy the demo router, gallery, Zustand store, or another paywall.
3. Preserve my package versions, navigation, state architecture, design system, app configuration, and native projects. Install only missing SDK-compatible packages with npx expo install.
4. Load the exact Inter aliases and all three selected images before revealing the screen, and preserve native system/SF typography wherever the source specifies it. Preserve image aspect ratios/crop behavior and adapt preloading to my root.
5. Mount the component in a full-height flex: 1 surface with no visible navigation header or surrounding safe-area padding; it owns a calibrated 390×844 ReferenceCanvas and status bar.
6. Treat bundle and improvements as externally selected fixed compositions—do not add an in-paywall switch or scrolling. Preserve the fixed toolbar and fixed purchase sheet, reduced-motion-aware bundle/annual selection, replay reset, separate web/in-app actions in Improvements, and the shared Skip behavior.
7. Wire bundle, annual, web-trial, and in-app purchase intents to distinct eligible host flows. Validate whether external checkout is permitted in my distribution context; never open it solely because the reference includes a web CTA.
8. Keep production pricing, bundle eligibility, renewal terms, localization, loading, purchase errors, and restore behavior driven by my billing source of truth.
9. Before public or commercial release, replace every third-party name, partner mark, generated imagery, athlete likeness, phrase, price presentation, orange treatment, and recognizable composition with authorized original material and a meaningfully unique design.
10. Validate both fixed variants, both bundle plans, fixed sheets, Skip, web/in-app action separation, every action, replay, reduced motion, TypeScript, lint, an iPhone simulator, and one Android viewport. Finish by listing every changed file and dependency.

YAZIO-inspired scrollable goal paywall — copy prompt
You are working inside my existing Expo React Native repository.

Use https://github.com/Appllama/top-paywall-screens as a read-only technical reference. Integrate only the YAZIO-inspired paywall into my app. Do not turn my app into the gallery, do not copy unrelated paywalls, and do not modify unrelated features.

Reference files:
- src/paywalls/yazio.tsx
- assets/paywalls/yazio/hero.png
- src/paywalls/types.ts
- src/paywalls/shared/actions.ts, pressable.tsx, reference-canvas.tsx, and geometry.ts, following only actual transitive imports
- the YAZIO section of docs/INTERACTION_SPEC.md
- src/app/_layout.tsx only as a font and asset-preloading reference
- docs/ASSET_PROVENANCE.md and NOTICE.md

Public contract:
- Component: YazioPaywall
- Paywall ID: yazio
- Registered variants: default
- Fonts: Nunito_600SemiBold, Nunito_700Bold, Nunito_800ExtraBold, Nunito_900Black
- Semantic actions: yazio.select-annual, yazio.select-quarterly, yazio.close, yazio.continue-annual, yazio.continue-quarterly
- Relevant packages: expo-asset, expo-font, expo-haptics, expo-image, expo-linear-gradient, expo-status-bar, @expo-google-fonts/nunito, react-native-reanimated, react-native-svg, and react-native-worklets

Requirements:
1. Before editing, inspect my Expo SDK, React Native version, router, package manager, font and image loading, billing architecture, product catalog, legal routes, and existing dependencies.
2. Copy only YazioPaywall, its generated hero, and the transitive shared helpers it imports. Do not copy the demo router, gallery, Zustand store, or another paywall.
3. Preserve my package versions, navigation, state architecture, design system, app configuration, and native projects. Install only missing SDK-compatible packages with npx expo install.
4. Load the exact Nunito aliases and hero before revealing the screen. Preserve its aspect ratio and adapt preloading to my root.
5. Mount the component in a full-height flex: 1 surface with no visible navigation header or surrounding safe-area padding; it owns a calibrated 390×844 ReferenceCanvas and status bar.
6. Preserve the full experience: reduced-motion-aware 350 ms entrance, annual/quarterly selection, vertically scrolling body, nested horizontal testimonial rail with 260 pt snapping, fixed close control, alpha-gradient sticky CTA footer, and replayKey resetting both scroll positions and plan state. Do not replace nested native scrolling with static cards or blur.
7. Wire annual and quarterly CTAs to distinct eligible products; keep card selection non-purchasing and Close separate. Do not invent the later discount-wheel flow—it is outside this implementation.
8. Keep production goals, dates, pricing, eligibility, renewal terms, localization, loading, purchase errors, and restore behavior driven by my sources of truth.
9. Before public or commercial release, replace every third-party name, mascot/character treatment, testimonial, phrase, goal/date, price presentation, color system, and recognizable composition with authorized original material and a meaningfully unique design.
10. Validate both plans, full vertical scrolling, horizontal snapping without gesture conflict, sticky footer, every action, replay, reduced motion, TypeScript, lint, an iPhone simulator, and one Android viewport. Finish by listing every changed file and dependency.

Run the Expo gallery

Requirements: Node.js 22.13 or newer, Xcode for iOS, or Android Studio for Android.

git clone https://github.com/Appllama/top-paywall-screens.git
cd top-paywalls
npm ci
npm run ios

Other targets:

npm run android
npm run web

The committed iOS bundle identifier and Android package name are development examples for this gallery. Forks should replace dev.appllama.paywalls with an identifier they control; no Apple team or signing credential is committed.

The root route opens the separate gallery selector. Replica routes contain no visible app switcher or debug chrome.

Deep links, variants, and replay

Every paywall has a direct Expo Router path:

/chatgpt
/cleanup
/facetune
/flo
/learna
/myfitnesspal
/perplexity
/picturethis
/strava
/yazio

Use variant to select an exact registered starting state and change replay to reset a mounted experience:

/chatgpt?variant=go
/flo?variant=all-plans
/myfitnesspal?variant=offer&replay=1
/perplexity?variant=max&replay=qa-2
/picturethis?variant=comparison
/strava?variant=improvements
/yazio?replay=2

The route validates variant against the registry. Missing or unsupported variants fall back to that paywall’s default. replay is an opaque string; it only needs to change.

Open the same routes through the configured custom scheme:

npx uri-scheme open "paywall-showcase:///perplexity?variant=max&replay=1" --ios
npx uri-scheme open "paywall-showcase:///strava?variant=bundle&replay=2" --android

See INTERACTION_SPEC.md for the canonical route contract and state behavior.

React Native paywall API

Prepare fonts and gestures once

The components intentionally own their 390×844 layout and status-bar treatment, but the host owns application bootstrap. Keep GestureHandlerRootView at your app root and load the font aliases used by the studies before mounting a paywall:

import { Inter_400Regular } from '@expo-google-fonts/inter/400Regular';
import { Inter_500Medium } from '@expo-google-fonts/inter/500Medium';
import { Inter_600SemiBold } from '@expo-google-fonts/inter/600SemiBold';
import { Inter_700Bold } from '@expo-google-fonts/inter/700Bold';
import { Inter_700Bold_Italic } from '@expo-google-fonts/inter/700Bold_Italic';
import { Inter_800ExtraBold } from '@expo-google-fonts/inter/800ExtraBold';
import { Manrope_400Regular } from '@expo-google-fonts/manrope/400Regular';
import { Manrope_500Medium } from '@expo-google-fonts/manrope/500Medium';
import { Manrope_600SemiBold } from '@expo-google-fonts/manrope/600SemiBold';
import { Manrope_700Bold } from '@expo-google-fonts/manrope/700Bold';
import { Manrope_800ExtraBold } from '@expo-google-fonts/manrope/800ExtraBold';
import { Nunito_400Regular } from '@expo-google-fonts/nunito/400Regular';
import { Nunito_600SemiBold } from '@expo-google-fonts/nunito/600SemiBold';
import { Nunito_700Bold } from '@expo-google-fonts/nunito/700Bold';
import { Nunito_800ExtraBold } from '@expo-google-fonts/nunito/800ExtraBold';
import { Nunito_900Black } from '@expo-google-fonts/nunito/900Black';
import { useFonts } from 'expo-font';
import { GestureHandlerRootView } from 'react-native-gesture-handler';

export function AppRoot() {
  const [fontsLoaded, fontError] = useFonts({
    Inter_400Regular,
    Inter_500Medium,
    Inter_600SemiBold,
    Inter_700Bold,
    Inter_700Bold_Italic,
    Inter_800ExtraBold,
    Manrope_400Regular,
    Manrope_500Medium,
    Manrope_600SemiBold,
    Manrope_700Bold,
    Manrope_800ExtraBold,
    Nunito_400Regular,
    Nunito_600SemiBold,
    Nunito_700Bold,
    Nunito_800ExtraBold,
    Nunito_900Black,
  });

  if (!fontsLoaded && !fontError) return null;

  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <YourNavigationRoot />
    </GestureHandlerRootView>
  );
}

If you integrate only one study, load just the aliases listed in its copyable prompt. For a production launch, keep the splash visible until fonts and that study's raster assets are ready so the first paywall frame cannot reflow.

Import one component

import {
  MyFitnessPalPaywall,
  type PaywallActionId,
} from 'paywall-experience-gallery';

function handlePaywallAction(actionId: PaywallActionId) {
  if (actionId === 'myfitnesspal.try-free-annual') {
    // Start your annual product purchase through your billing service.
  }

  if (actionId === 'myfitnesspal.no-thanks') {
    // Dismiss the host route after the promotional state.
  }
}

export function PremiumRoute() {
  return (
    <MyFitnessPalPaywall
      initialVariant="standard"
      onActionPress={handlePaywallAction}
      onClosePress={() => navigation.goBack()}
    />
  );
}

Plan and tier taps update local UI state inside the component. A purchase occurs only when your host handles an explicit purchase action or onPurchasePress.

Select from the typed component map

import {
  PaywallScreen,
  type PaywallId,
} from 'paywall-experience-gallery';

export function PaywallPreview({ name }: { name: PaywallId }) {
  return (
    <PaywallScreen
      name={name}
      onActionPress={(actionId) => analytics.track('paywall_action', { actionId })}
    />
  );
}

Use the registry when a generic host needs the correct default and allowed variants:

import {
  getPaywallMetadata,
  PAYWALL_METADATA,
} from 'paywall-experience-gallery';

const allPaywalls = PAYWALL_METADATA;
const perplexity = getPaywallMetadata('perplexity');
// perplexity?.defaultVariant === 'pro'

Source-distributed Git dependency

This repository is intentionally not published to the npm registry. It exports src/index.ts so SDK-matched Expo workspaces can consume the source directly from GitHub:

npm install github:Appllama/top-paywall-screens

The demo targets Expo SDK 57 and React Native 0.86. Apps on another Expo SDK should prefer the component-specific prompt workflow so npx expo install can resolve compatible native package versions.

Shared props

Prop Purpose
initialVariant Selects the starting composition/state. Components normalize unsupported values; the demo route validates against the registry.
replayKey Resets or remounts the experience when this number or string changes.
onActionPress Receives a typed semantic ID for every implemented selection, CTA, close, restore, legal, sheet, or scroll intent.
onClosePress Host callback used by applicable close/dismiss controls. MyFitnessPal’s first X changes to the downsell; No thanks is the actual close callback.
onPurchasePress Generic host callback used by explicit purchase CTAs. It contains no billing implementation.
onRestorePress Generic host callback used by implemented restore controls.
onVariantChange Observes registered in-screen composition or tier transitions; local plan choices use semantic action IDs.

For controls with a legacy callback, local behavior and that callback run before onActionPress. If you provide both APIs, do not start the same purchase twice. Prefer onActionPress when you need exact per-product routing; use the generic callbacks when one host action is sufficient.

PaywallActionId, PaywallActionPressHandler, PaywallId, PaywallVariantId, PAYWALL_IDS, PAYWALL_METADATA, getPaywallMetadata, and isPaywallId are exported for typed tooling.

Interaction architecture

State machines, not screenshot swaps

The implementations keep purchase selection separate from purchase intent. Plan cards, segment controls, switches, and sheet navigation update local state and emit semantic actions. Explicit CTAs invoke the host purchase callback. Sequential experiences preserve their observed transition order:

  • MyFitnessPal’s first close moves to the promotional offer; only No thanks dismisses it.
  • Facetune’s trial explainer moves one way into VIP plans.
  • Flo’s all-plans state opens and dismisses as a draggable modal sheet.
  • Perplexity remembers the selected Pro plan while the user compares Max.
  • Cleanup, Learna, PictureThis, and Strava use externally selected registered compositions and intentionally expose no replica switcher.

These mechanics are reference behavior, not automatic product recommendations. Review every sequence for clear consent, honest trial disclosure, accessible dismissal, platform rules, and your own product requirements.

Scroll, sheets, blur, and motion

  • Reference canvas: every replica is authored at 390×844 points and uniformly scaled through ReferenceCanvas.
  • Vertical scroll: ChatGPT scrolls its comparison viewport; Cleanup and Facetune use full-canvas scroll surfaces; YAZIO combines a long body with a sticky footer. Strava's two bodies are fixed behind fixed chrome.
  • Horizontal interaction: Flo uses native PagerView; Perplexity exposes a draggable model rail; YAZIO nests a snapping testimonial rail inside its vertical scroll.
  • Sheets: Flo’s all-plans sheet has a backdrop and pan-to-dismiss gesture. MyFitnessPal’s Learn More disclosure has a real animated backdrop and dismissal controls.
  • Blur and transparency: Perplexity’s controls/comparison surface and Facetune’s decorative palette use BlurView. YAZIO’s sticky footer uses an alpha gradient, not blur; Strava’s purchase sheets are opaque.
  • Reduced motion: MyFitnessPal, Perplexity, PictureThis, Strava, and YAZIO gate the relevant authored transitions. Other measured transitions are documented honestly rather than being described as reduced-motion-aware.
  • Accessibility and feedback: pressables expose labels, roles, selection state where relevant, a generous hit target, brief press feedback, and Expo haptics.

Production commerce boundary

This repository intentionally contains no StoreKit, Google Play Billing, RevenueCat, Superwall, or subscription backend implementation. The visible prices are not product identifiers. The host app is responsible for:

  • loading localized products and eligibility from its source of truth;
  • presenting current price, billing period, trial, renewal, and cancellation terms;
  • starting, observing, validating, and restoring purchases;
  • handling pending, cancelled, failed, and already-owned states;
  • routing privacy, terms, subscription terms, external checkout, and limited-access actions;
  • recording analytics without double-counting callbacks; and
  • replacing every reference identity and composition before release.

Documentation

Document What it contains
docs/INTERACTION_SPEC.md Canonical variants, state machines, durations, gestures, scrolling, sheets, limitations, and semantic actions
docs/ASSET_PROVENANCE.md Inventory and generation notes for every distributed raster asset
NOTICE.md Educational-use boundary, third-party rights, and no-commercial-IP permission notice
LICENSE GNU General Public License v3.0 for licensable original project code/material

Project structure

assets/paywalls/                  Generated, non-interactive art layers by paywall
docs/INTERACTION_SPEC.md          Exact behavior and semantic-action contract
docs/ASSET_PROVENANCE.md          Auditable generated-asset inventory
src/app/                          Expo Router gallery and invisible-switch replica routes
src/store/                        Zustand demo selection/replay state
src/paywalls/                     Ten components, registry, types, and shared helpers
src/index.ts                      Source-distributed package entry

The third-party stills used during visual research are intentionally outside the repository. No production-app screenshot pixels or extracted production artwork are distributed. See ASSET_PROVENANCE.md.

Verification

npm run verify

The verification command runs:

  1. strict TypeScript with tsc --noEmit;
  2. Expo ESLint;
  3. local Markdown link validation; and
  4. a production static web export.

For interaction-sensitive changes, also validate every affected state and gesture in an iPhone simulator and at least one Android viewport. Test release or internal builds when native purchase, blur, status-bar, haptic, or deep-link behavior matters.

Frequently asked questions

Can I copy only one paywall without the gallery?

Yes. Use the matching prompt above or import its named component. Copy only the component’s actual assets and transitive shared helpers. The Expo Router gallery and Zustand store are demo infrastructure, not requirements for an individual paywall.

Are the purchase buttons connected to a billing provider?

No. They update local UI where appropriate, provide tactile feedback, and emit callbacks. Your app must connect explicit purchase IDs to its own compatible billing implementation and product catalog.

Why are some variants switchable and others not?

Some references show states in one user journey; others show distinct entry compositions. The implementation preserves that evidence. The gallery and URL can select every registered variant without adding controls inside a replica that were not present in the reference.

Does this support scrolling, blur, sheets, and reduced motion?

Yes where the corresponding study calls for them. The project uses native scroll surfaces, PagerView, Gesture Handler, Reanimated, Expo BlurView, and explicit reduced-motion handling in the components documented above. It does not invent those behaviors for fixed references.

Is this a drop-in production paywall system?

No. It is a runnable Expo research gallery and a source-distributed component collection. Production commerce, remote configuration, experiments, eligibility, localization, legal review, analytics, and third-party identity replacement belong to the integrating app.

Can I use these exact designs commercially?

No commercial-use permission for third-party intellectual property is granted. The original project code is GPL-3.0-licensed, but referenced brands, screen content, trade dress, and other third-party rights are separate. Replace them and create a meaningfully unique production experience.

Contributing

Issues and focused pull requests are welcome.

  • Keep every paywall independently importable.
  • Preserve registered variant behavior and action IDs unless a change is deliberately documented.
  • Preserve accessibility, scroll boundaries, gesture arbitration, and reduced-motion handling.
  • Do not submit extracted production artwork, source screenshots, or source video from third-party apps.
  • Record provenance for every new distributable bitmap.
  • Update docs/INTERACTION_SPEC.md when behavior changes.
  • Run npm run verify before opening a pull request.

Open an issue or start a pull request.

Educational use and intellectual property

This is an independent, unofficial project created by Appllama for education, UI research, and technical demonstration. It is not affiliated with, sponsored by, endorsed by, or authorized by OpenAI, Cleanup, Facetune, Flo, Learna, MyFitnessPal, Perplexity, PictureThis, Strava, YAZIO, Apple, Google, or any other referenced company.

Third-party product names, trademarks, service marks, logos, icons, screen text, artwork, product claims, prices, and other brand elements belong to their respective owners. They are referenced only to identify and study publicly visible subscription and paywall patterns. Appllama claims no ownership of, and grants no license to, any third-party intellectual property.

The GNU General Public License v3.0 applies only to original project code and original material that Appllama is legally able to license. It does not grant permission to use third-party trademarks, copyrighted material, protected trade dress, publicity rights, or other proprietary material.

Do not ship these reference implementations unchanged. Before using an implementation in a public or commercial product, you must:

  • replace every third-party name, logo, icon, character, illustration, image, testimonial, statistic, claim, price string, and piece of copy;
  • create your own independently designed colors, typography, spacing, composition, imagery, interaction sequence, and motion language;
  • remove anything that could imply affiliation, sponsorship, endorsement, or approval by a referenced company; and
  • obtain any permissions or legal clearance required for your use and jurisdiction.

Changing only a logo, app name, price, or accent color may not be sufficient. Calling a use “educational” or “noncommercial,” adding attribution, or including this notice does not automatically make the use lawful or qualify it as fair use. Fair use is evaluated case by case.

This notice is informational, is not legal advice, and does not guarantee that any particular use is permitted. If you are uncertain, consult a qualified intellectual-property attorney before publishing or distributing your work. See the full repository notice, the U.S. Copyright Office fair-use guidance, and the USPTO trademark-infringement overview.

Rights holders can request a correction or removal by opening an issue.

License

Original source code is available under the GNU General Public License v3.0, subject to the third-party rights and exclusions explained above and in NOTICE.md.

An open-source creation by Appllama

Appllama

Study the onboarding, paywall, and product flows behind leading iOS apps at appllama.io.

Follow @appllamaio on X · Created by @jaimintf · Star the repository