# Add Tilnivo to this app

Before you start, ask me for my Tilnivo store id. It starts with sto_ and is under Storefront → Install in my Tilnivo dashboard (https://tilnivo.com/dashboard/storefront). Use it in place of YOUR_STORE_ID below.

Add a Tilnivo cart and checkout to this app. Tilnivo handles the cart, the checkout, payments, tax and shipping, so don't build any of those or a payments backend.

1. Add this script tag once, in index.html before </body>:
   <script async src="https://tilnivo.com/c.js" data-store="YOUR_STORE_ID"></script>

2. Make each buy button a Tilnivo button. The page is the catalog: the button says everything about the product, and Tilnivo reads this page again on the server before it takes payment, so render buttons in the HTML the server sends (or answer JSON at data-item-url) and keep the price there the real one:
   <button data-tilnivo-add data-item-id="black-tee" data-item-name="Black tee" data-item-price="25.00" data-item-url="https://yourshop.com/black-tee" data-item-image="https://yourshop.com/tee.jpg">Add to cart</button>
   data-item-id is the product's id and never changes. Options go in data-item-custom1-name="Size" data-item-custom1-options="S|M|L[+2.00]", stock in data-item-stock. My domain must be in my Tilnivo store's domain list.
   Buttons rendered later by React work in the cart, but the server never runs JavaScript: in a single-page app, point each data-item-url at a URL that answers the product as JSON ({ "id", "name", "price", "url" }). From code, call window.Tilnivo.add({ id, name, price, url }) and window.Tilnivo.open().
   For a form with a size picker and a quantity, put the same data-item-* on a <form data-tilnivo-form="add"> (custom options as data-item-custom1-name="Size" data-item-custom1-options="S|M|L"), name each input after its option (name="Size", name="quantity"), and add <p data-tilnivo-error="Size"></p> and <p data-tilnivo-message></p> for errors. data-tilnivo-form="signin" (name="email", then name="code") and "discount" (name="code") work the same way. Don't write submit handlers for these. To show something only when the shopper is signed in or out, or the cart has items or is empty, add data-tilnivo-if="signed-in" (or signed-out, has-items, empty) instead of writing that logic.

3. Add a cart button to the header:
   <button data-tilnivo-open>Cart (<span data-tilnivo-count>0</span>)</button>

4. To react to a purchase, listen for the tilnivo:order_completed event on window. Never unlock anything paid from that event alone: do it from Tilnivo's signed order.paid webhook on the server.

5. If the app has sign-in (Supabase, Clerk, Firebase…), call window.Tilnivo.identify(token) with the signed-in user's token whenever the session changes, and window.Tilnivo.identify(null) on sign-out.
