Getting started

ShopNative comes ready to run. The project is connected to our demo store (Luma Store), so you can build it and see a working app before you change anything. Then connect your own Shopify store in a few steps.

Home   Product

1. Install the tools

Check your setup with flutter doctor.

2. Build the demo app (no changes needed)

Unzip the download and open a terminal in the shopnative folder (the folder that contains pubspec.yaml):

Windows: unzip to a short path such as C:\dev\ShopNative. Very long folder paths (over 260 characters, e.g. deep inside Downloads or a synced folder) make the Flutter tool fail with "Directory listing failed".

flutter pub get
flutter run                     # on a connected phone, emulator or iOS simulator

Or build an installable APK:

flutter build apk --debug       # → build/app/outputs/flutter-apk/app-debug.apk
flutter build apk --release     # → build/app/outputs/flutter-apk/app-release.apk

The release APK is signed with the debug key until you add your own (see step 4). You can also open the shopnative folder in Android Studio or VS Code and press Run.

What to try in the demo

Run the tests (optional)

flutter test

3. Connect your own store

  1. Set up the free Shopify Headless channel and copy your keys: Shopify setup.
  2. In assets/app-config.json, replace the demo values in store (domain, storefrontToken, customerAccountClientId, customerAccountRedirectUri) with yours.
  3. Replace the four demo banners in home.banners with your own images (or remove them).
  4. Change app.id (for example com.yourcompany.store) and app.name, then run:
    dart run tool/rebrand.dart
    
  5. flutter run again: the app now shows your products.

Then follow the Rebranding checklist for your logo, app icon and colours. Every setting is described in Configuration.

The demo store keys in app-config.json are public Storefront and Customer Account keys (the same kind every Shopify app ships with). They only allow reading products and creating carts on the demo store. The demo store is kept online for testing, but it may change at any time: always connect your own store before you publish.

4. Publish

When the app shows your store and your brand, build the release versions:

flutter build appbundle --release --obfuscate --split-debug-info=build/symbols   # Google Play
flutter build ipa --release --obfuscate --split-debug-info=build/symbols         # App Store (on a Mac)

For Google Play, sign the app with your own key: copy android/key.properties.example to android/key.properties and point it to your keystore. Without it, release builds use the debug key (fine for testing, not for Google Play).

5. Project structure

shopnative/
  assets/
    app-config.json        your store, brand, home page and support settings (see Configuration)
    brand/                 logo, symbol and app icon images
    i18n/                  one JSON file per language (en.json, ar.json)
  lib/
    main.dart              starts the app: creates the AppStore, then runs ShopNativeApp
    app.dart               ShopNativeApp: theme, languages, right-to-left
    config/                app_config.dart (reads app-config.json), theme.dart (light and dark themes)
    data/                  Shopify connection: storefront_api.dart, customer_account_api.dart, disk cache
      models/              product, catalog, cart and customer models
    state/                 app state (cart, catalog, customer, settings), shared through StoreScope
    i18n/                  strings.dart: loads the translations from assets/i18n
    ui/
      shell/               app frame: header, bottom bar, side menu, search, links from notifications
      screens/             one file per screen: home, collections, product, cart, checkout, account, ...
      kit/                 small reusable widgets: buttons, product card, glass panels, images
  addons/push/             optional push notifications add-on (Firebase)
  tool/rebrand.dart        applies app id, name and version to Android and iOS
  test/                    unit and widget tests (flutter test)
  android/  ios/           native projects (normally you only change them through rebrand.dart)

Most changes need only assets/: store keys, colours, banners, menus and texts. Change the code in lib/ui/ when you want a different layout.

Shopify setup

ShopNative talks to your store through two official Shopify APIs. Both are set up in the free Headless sales channel. No Shopify app or server is needed.

API Used for What you copy into assets/app-config.json
Storefront API Products, collections, menu, search, cart, checkout store.storefrontToken
Customer Account API Sign in, profile, orders, addresses store.customerAccountClientId, store.customerAccountRedirectUri

1. Install the Headless channel

  1. Shopify admin → Settings → Apps and sales channels → Shopify App Store, search Headless, install it (made by Shopify, free).
  2. Open Sales channels → Headless → Create storefront.

2. Storefront API token

  1. In your storefront: Storefront API → Manage.
  2. Copy the Public access token into store.storefrontToken.
  3. Put your shop domain in store.domain, e.g. your-store.myshopify.com.

Never use the private token or an Admin API token (starting with shpat_). Those give full access to your store and must never be put in an app. ShopNative refuses shpat_ tokens.

Permissions: the Headless channel's default Storefront API permissions are enough. If you changed them, make sure products, collections, navigation menus, inventory (for "sold out") and checkouts are allowed.

3. Customer login (Customer Account API)

  1. In your storefront: Customer Account API → Manage.
  2. Client type → Public (mobile app). "Public (web app)" will not work and shows "Invalid redirect_uri scheme".
  3. Copy the Client ID into store.customerAccountClientId.
  4. Find your shop ID: it is the number in the Authorization endpoint shown on the same page, e.g. https://shopify.com/authentication/71533101190/oauth/authorize → 71533101190.
  5. Under Callback URI(s) add exactly:
    shop.<your-shop-id>.app://callback
    
    Do not add https:// in front, even though the page says "include HTTPS". If you see "Redirect uri is not secured", the client type is still "web app" (step 2).
  6. Put the same value in store.customerAccountRedirectUri.
  7. Customer accounts must be on: Settings → Customer accounts → Customer accounts (the new version).

When a customer is signed in in the app, checkout opens signed in too (saved addresses, order linked to the account).

4. Collections, menu and images

In Shopify Used in the app
Collections that have products Collections tab (all of them, with their image)
Content → Menus → Main menu (handle main-menu) Side menu, and "Shop by collection" rows on the home screen (a top-level item with collection sub-items becomes a row with chips)
A collection for new products, e.g. handle new-arrivals "New Arrivals" row (home.newArrivalsCollection)
Collection image (1200 × 1200, subject centered) Collection tiles
Product images Product cards, gallery, cart, orders
Settings → Policies Policies screen (refund, shipping, privacy, terms)

Menu items that are not collections also work: / opens Home, /pages/contact opens Contact, product links open the product, other links open in the in-app browser.

5. Checkout and payments

Checkout is Shopify's own checkout, shown inside the app. Payments, taxes, shipping, discounts and order emails all come from your Shopify settings. After a successful order the app closes checkout, empties the cart and shows a thank-you screen.

Development stores are password protected; checkout asks for the store password unless the customer is signed in. To test payments use Settings → Payments → (for testing) Bogus Gateway and card number 1.

Troubleshooting

Message Fix
"Missing Shopify Storefront API token" store.storefrontToken is empty or still YOUR_....
"...is a Shopify Admin API token" You pasted a shpat_ token. Use the public Storefront token.
Login: "Invalid redirect_uri scheme" Client type must be Public (mobile app).
Login: "Redirect uri is not secured" Same as above; then add the callback without https://.
Login opens but never returns to the app customerAccountRedirectUri in the config must match the callback URI in Shopify exactly. Rebuild the app after changing it.
Collections tab is empty Collections need at least one product and must be available on the Headless channel.
Home has no "Shop by collection" rows Add collections with sub-collections to the Main menu.
Windows: "Directory listing failed" / "cannot find the path" The project folder path is too long. Move it to a short path such as C:\dev\ShopNative.
Checkout shows a password page Development store: sign in first, or enter the store password.

Configuration reference

Everything is configured in one file: assets/app-config.json. No Dart code changes are needed.

After editing:

Text values starting with YOUR_ are treated as empty.


app: identity

Key Example Notes
id com.yourbrand.store Package name (Android) and bundle ID (iOS). Cannot be changed after the first store upload.
name Your Store Name under the app icon.
version 1.0.0 Version shown in the stores.
build 1 Increase by 1 for every upload to Google Play / App Store.

store: Shopify connection

See SHOPIFY_SETUP.md for where to find each value.

Key Required Notes
domain yes your-store.myshopify.com
storefrontToken yes Public Storefront API access token
customerAccountClientId for login Customer Account API client ID (client type: Public, mobile app)
customerAccountRedirectUri for login shop.<shop-id>.app://callback (no https://)
websiteUrl no Your public website, used for product links and policy pages. Default: https://<domain>
apiVersion no Storefront API version, default 2026-04

brand

Key Notes
name Store name in texts (footer, messages).
tagline Shown on the startup screen (spaced capitals). Optional.
logoAsset / logoAssetDark Header logo bundled in the app (PNG, about 600 px wide), for light and dark mode.
symbolAsset / symbolAssetDark Startup screen symbol (PNG).
logoUrl Header logo from a URL, used when no logoAsset is set. If neither is set, the name is shown as text.
themeMode system, light or dark: the default before the user picks one in Settings.
colors Light mode colours (below).
darkColors Dark mode colours, same keys. Optional: derived from colors when missing.

Colours (#RRGGBB or #AARRGGBB):

Key Used for
primary Buttons, prices, links, selected states, badges
primarySoft Light tint for chips and soft buttons (derived from primary if omitted)
onPrimary Text on primary buttons. Use dark text when primary is light.
textPrimary Headings and important text
textSecondary Body text, hints, captions
background Screen background (also the Android launch screen, via tool/rebrand.dart)
surface Cards, inputs, panels
border Outlines of inputs, cards, chips
icon Header and navigation icons
favorite Active wishlist heart
sale "Sale" badge on products with a compare-at price
error Error messages and destructive actions

Check contrast: text on background and onPrimary on primary should be at least 4.5 : 1.

i18n: languages

Key Example Notes
languages ["en", "ar"] Languages users can pick in Settings. Each needs assets/i18n/<code>.json.
defaultLanguage en Language on first start.

Right-to-left layout is automatic for Arabic, Persian, Hebrew and Urdu. To add a language, copy assets/i18n/en.json to e.g. fr.json, translate the values (keep the keys and {placeholders}), and add "fr" to languages. The test suite checks that every language has all keys.

home

Key Notes
menuHandle Shopify navigation menu used for the side menu and home rows. Default main-menu.
newArrivalsCollection Collection handle for the "New Arrivals" row.
allProductsCollection Collection used for the full catalog. Default all (Shopify's built-in all-products collection).
banners Home carousel, see below. Remove all items to hide it.

Banners:

{
  "collection": "new-arrivals",
  "image": "https://cdn.shopify.com/.../banner.webp",
  "eyebrow": { "en": "New season", "ar": "موسم جديد" },
  "headline": { "en": "Wear the light", "ar": "ارتدِ النور" },
  "button": { "en": "Shop now", "ar": "تسوّق الآن" }
}
Key Notes
collection Collection handle opened on tap (required).
image URL (upload to Shopify → Content → Files) or a bundled path starting with assets/. 1600 × 900 px, JPG/WebP under 300 KB.
eyebrow, headline, button Optional text drawn over the image. A plain string, or one value per language.

With text, keep the left 45 % of the photo calm (the text sits there) and the subject on the right; keep the bottom-right corner clear (page counter). In right-to-left languages the photo is mirrored automatically.

support

title, address, phone, whatsapp, email. Shown on the Contact screen and used by "Check availability" and "Call for price". Empty values are hidden.

features

Key Notes
availabilityCheck Shows "Check availability" on product pages (needs at least one support contact).
taxLabels.enabled Shows a tax label next to prices, based on the variant's taxable setting.
taxLabels.taxable / nonTaxable Label texts, e.g. excl. VAT / incl. VAT.
taxLabels.taxableNote Small note under taxable prices.

Products priced at 0 show Call for price, which contacts the store by WhatsApp, phone or email (first one set).

Rebranding checklist

Turn ShopNative into your store's app in about an hour.

1. Identity and store

  1. Edit assets/app-config.json: app (id, name, version), store (see SHOPIFY_SETUP.md).
  2. Run:
    dart run tool/rebrand.dart --check   # validates the config and shows what will change
    dart run tool/rebrand.dart           # applies it to the iOS project, pubspec and launch screen
    

Replace these PNG files (keep the names, or change the paths in brand):

File Size Shown
assets/brand/logo.png ~600 px wide, transparent Header, light mode
assets/brand/logo-dark.png same Header, dark mode (light-coloured logo)
assets/brand/symbol.png ~240 px wide, transparent Startup screen, light mode
assets/brand/symbol-dark.png same Startup screen, dark mode

No logo yet? Delete logoAsset and logoAssetDark from the config: the header shows your store name as text.

3. App icon

  1. Replace assets/brand/app-icon.png: 1024 × 1024, square, no transparency, no rounded corners (iOS and Android round it themselves). Keep the important part inside the middle 60 %.
  2. Replace assets/brand/app-icon-foreground.png: the same artwork on a transparent background (Android adaptive icon layer), and set adaptive_icon_background in pubspec.yaml to your icon's background colour.
  3. Run dart run flutter_launcher_icons.

4. Colours

Set brand.colors and brand.darkColors (see CONFIGURATION.md). Run dart run tool/rebrand.dart again so the launch screen colour matches.

5. Home banners

Upload 1600 × 900 images to Shopify → Content → Files and list them in home.banners with optional text.

6. Texts and languages

All texts are in assets/i18n/*.json. Change wording there; add or remove languages in i18n.languages.

7. Store listing

Before publishing: test sign in, add to cart, checkout (with a test payment), and dark mode / your languages on a real device. Then build:

flutter build appbundle --release --obfuscate --split-debug-info=build/symbols   # Google Play
flutter build ipa --release --obfuscate --split-debug-info=build/symbols         # App Store (on a Mac)

Keep the build/symbols folder of every release: it is needed to read crash reports.

Push notifications add-on (optional)

Send notifications ("New collection is live", "Summer sale -30 %") from the free Firebase console. Tapping a notification can open a product, a collection or the cart.

ShopNative ships without Firebase, so the app works without any Firebase account or setup files. Enabling this add-on takes about 20 minutes and adds Firebase Messaging (about 0.3 MB on Android, measured on a release build).

1. Create a Firebase project

  1. Go to https://console.firebase.google.com → Add project.
  2. Install the tools (once):
    dart pub global activate flutterfire_cli
    npm install -g firebase-tools   # or see https://firebase.google.com/docs/cli
    firebase login
    
  3. In the project folder, run and pick your Firebase project, Android and iOS:
    flutterfire configure
    
    This creates lib/firebase_options.dart and the Firebase config files for Android and iOS.

2. Add the packages and the code

flutter pub add firebase_core firebase_messaging

Copy addons/push/push_notifications.dart to lib/addons/push_notifications.dart.

In lib/main.dart, start it after the store is created:

import 'addons/push_notifications.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final store = await AppStore.create();
  runApp(ShopNativeApp(store: store));
  store.refresh();
  PushNotifications.init(onMessage: store.addMessage); // ← add this line
}

3. Android

Android 13 and newer ask the user for permission; the add-on does that on first start. Nothing else is needed: flutterfire configure already added the Google services files.

4. iOS (needs an Apple Developer account)

  1. In Xcode, open ios/Runner.xcworkspace → target Runner → Signing & Capabilities → add Push Notifications and Background Modes → Remote notifications.
  2. In the Apple Developer portal create an APNs Authentication Key (.p8).
  3. Firebase console → Project settings → Cloud Messaging → Apple app configuration → upload the key, with your Key ID and Team ID.

5. Send a notification

Firebase console → Messaging → New campaign → Notifications:

Value Opens
/products/<product-handle> that product
/collections/<collection-handle> that collection
/cart the cart
/ home
https://… a web page in the in-app browser

Messages that arrive while the app is open are added to the in-app notifications list (bell icon).

Testing

Run the app in debug mode: the device's push token is printed in the console (Push token: …). In the Firebase console use Send test message with that token.

Removing it again

Delete lib/addons/push_notifications.dart, the PushNotifications.init line, run flutter pub remove firebase_core firebase_messaging, and delete lib/firebase_options.dart and the Firebase config files.

Changelog

1.0.0

First release.

Licenses

ShopNative

The ShopNative source code is licensed to you under the CodeCanyon / Envato Market licence you purchased (Regular or Extended). See https://codecanyon.net/licenses/standard.

Brand assets

The "Luma Store" logo, symbol and app icon in assets/brand/ were created for the ShopNative demo and may be replaced freely. "Luma Store" is a fictional demo brand.

Demo photos

The banner and collection photos seen in the demo store and screenshots are from Pexels (Pexels License) and are not included in this download (only small screenshots of the app in docs/images/). Use your own images. Credits are in docs/DEMO_CREDITS.md.

Open-source packages

All packages used by the app have permissive licences (BSD, MIT, Apache 2.0). Their notices are shown in the app under Settings → Open-source licenses (Flutter collects them automatically).

Direct dependencies:

Package Version Licence
crypto 3.0.7 BSD-3-Clause
flutter SDK BSD-3-Clause
flutter_localizations SDK BSD-3-Clause
flutter_web_auth_2 5.1.0 MIT
http 1.6.0 BSD-3-Clause
path_provider 2.1.6 BSD-3-Clause
shared_preferences 2.5.5 BSD-3-Clause
url_launcher 6.3.2 BSD-3-Clause
webview_flutter 4.14.1 BSD-3-Clause

Including transitive packages: BSD-3-Clause ×60, MIT ×4, Apache-2.0 ×3.

Icons: Material Icons (Apache 2.0), bundled with Flutter. Fonts: the device's system font (no fonts bundled).

Photo credits: Luma Store demo images

All photos are from Pexels and used under the Pexels License (free for commercial use; attribution not required but given here). License: https://www.pexels.com/license/

Images were cropped, resized and colour-graded for the Luma Store demo.

Used for Photographer Source
1-new-arrivals (banner + collection image) cottonbro studio https://www.pexels.com/photo/woman-standing-by-the-water-5263307/
2-women (banner + collection image) MART PRODUCTION https://www.pexels.com/photo/studio-shoot-of-a-woman-with-prosthetic-leg-8437008/
3-men (banner + collection image) cottonbro studio https://www.pexels.com/photo/a-man-wearing-a-white-shirt-over-a-turtleneck-7764067/
4-accessories (collection image) Marina M https://www.pexels.com/photo/woven-bags-on-the-table-8356229/
4-accessories (banner) Minne Yaël Photographie https://www.pexels.com/photo/close-up-of-a-brown-hat-lying-on-beige-fabric-17068555/

Using these photos

Support

Most questions are answered in this documentation; see Troubleshooting first.

If you need help, contact us with your purchase code, your Flutter version (flutter --version) and a screenshot or the error message:

Support covers questions about the item, bugs, and help with the setup described here. Custom changes and installation services are not part of item support.

Installation and publishing service (paid, optional)

If you prefer, we can set up and publish the app for you. This is a separate paid service, quoted per project; it is not included in the item price.

What we do

What you provide

The developer accounts stay in your name, so you keep full ownership of your apps. Store review times are set by Google and Apple.

To request a quote, email devapptics@gmail.com with the subject "ShopNative setup" and your purchase code.