docs
/
Client Integration

Example apps

Clone the example repository, point it at your organization, and have a working storefront running in a few minutes.

Two repositories hold runnable code. Read them, or clone one and build on it.

Each app has a full tutorial of its own — see Example apps for the set. The two web stores are the Next.js storefront and the Remix storefront, the second of which also covers appointment booking.

RepositoryWhat it holds
appmint-examplesComplete apps — Next.js and Remix storefronts, plus Flutter demos
appmint-clientThe client libraries themselves — TypeScript and Flutter

Get the code

git clone https://github.com/JacLight/appmint-examples.git
cd appmint-examples

Each app is self-contained: its own dependencies, its own README, its own run command. There is no workspace to understand and nothing to build at the root — cd into the one you want and go.

appmint-examples/
  nextjs-store/                          a storefront: catalog, cart, server-priced totals
  remix-store/                           the same, plus reservations — no proxy needed
  appmint_flutter_authentication_demo/   sign-in, magic link, sessions
  appmint_flutter_chat_demo/             realtime chat over WebSocket
  appmint_flutter_community_demo/        community features
  appmint_flutter_crm_demo/              contacts and CRM records
  appmint_flutter_events_demo/           events, tickets, check-in
  appmint_flutter_payments_demo/         payments and checkout

Just want one app? Fetch a single folder rather than the whole history:

npx degit JacLight/appmint-examples/nextjs-store my-store
cd my-store

Or the Remix one:

npx degit JacLight/appmint-examples/remix-store my-store
cd my-store

Run the Next.js storefront

1. Install

cd nextjs-store
npm install

2. Configure

cp .env.example .env.local
APPENGINE_ENDPOINT=https://appengine.appmint.io
ORG_ID=your-org-id
APP_ID=your-app-id
APP_KEY=your-app-key
APP_SECRET=your-app-secret

Your org id and application credentials come from Studio Manager. .env.local is already in .gitignore — leave it that way.

3. Run

npm run dev

Open http://localhost:4100. The catalog is your organization's own products, fetched server-side on first paint.

What to try

  • Catalog → product → add to cart. Then open the cart: every figure there came from storefront/pricing/calculate-cart.
  • Enter a promo code that does not exist. The total does not move, and a message explains why. That is a 200 with a verdict, not an error.
  • Stop appengine, reload the cart. The total disappears rather than falling back to a locally summed number. That is deliberate — see below.
  • Request /api/repository/find/customer. You get 404 Not proxied. The proxy forwards a storefront surface, not the whole API.

Reading the Next.js app

Six files carry the whole lesson.

FileWhy it matters
lib/appmint.tsThe dual transport. request() picks by typeof window — browser to /api, server to appengine. The app token is fetched and renewed here, server-side only.
app/api/[...slug]/route.tsThe proxy. An allow-list, the visitor's cookie read into x-client-authorization, upstream status codes preserved.
lib/cart-storage.tsThe cart. sku, name, quantity — deliberately no money.
components/CartView.tsxThe money path. Items, address and coupon in one call; the summary rendered field by field.
app/page.tsxServer-side catalog, showing calculatedPrice.finalPrice.
app/product/[sku]/page.tsxDetail, with list price struck through only when it differs.

Three things the app will not do

These are the point of the example, and each one is a bug somebody has already shipped.

It never adds money up. No subtotal + shipping - discount anywhere. total already includes tax and shipping, so recomputing it drops the tax — and matches on tax-free destinations, which is why the bug survives review.

It never lets credentials near the browser. APP_SECRET is read in lib/appmint.ts only on the server path. The browser cannot reach appengine through this app at all.

It shows nothing rather than something wrong. When pricing fails there is no total. A plausible locally-summed figure is worse than a blank, because the customer believes it.

Build your own from it

The storefront is a starting point, not a framework. To turn it into yours:

  1. Replace app/globals.css — the styling is deliberately plain.
  2. Add routes for whatever else you sell. Anything without a helper on the client is one line: appmint.get('storefront/collections').
  3. Extend the proxy allow-list in app/api/[...slug]/route.ts as you reach new endpoints — and only as far as a visitor genuinely needs.
  4. Add checkout. orders.checkout() places the order; payment is configured per organization, so wire the gateway your org uses.

The client libraries

If you want the library rather than an app:

git clone https://github.com/JacLight/appmint-client.git
appmint-client/
  appmint_js_client/       TypeScript — the one the Next.js store uses
  appmint_flutter_client/  Dart/Flutter — device sessions, secure token storage

The TypeScript client is walked through end to end in Build a storefront with the TypeScript client.

Run the Remix storefront

cd remix-store
cp .env.example .env.local     # same five values as above
npm install
npm run dev                    # http://localhost:4200

Same catalog and cart, plus /book and /bookings — a complete guest reservation flow: availability from the server, booking without an account, lookup and cancellation by email. It is built from an empty folder, step by step, in Tutorial: the Remix storefront.

One gotcha that is specific to Remix: Vite does not load .env.local into process.env. The example calls dotenv.config() in vite.config.ts for exactly this reason. Skip it and every credential is undefined, which shows up as an empty catalog rather than an error.

The two are shaped differently on purpose. A web client puts your server between the browser and appengine, so credentials never ship. A mobile client talks to appengine directly — app credentials are readable from any binary, so there they are an identifier rather than a secret, and the signed-in person's token is what protects a request.

Other languages

There is a full OpenAPI document covering the API, served at documentation-json. For Java, C#, Python, Go or anything else, generate a client from it rather than writing one by hand — a generated client tracks the API as it changes.