Skip to content
BuildBase

Zero to first sale - storefront

From your Stripe keys to a seller paid out: the storefront shape end to end, where buyers pay on the seller's own Stripe account and your fee comes to you.

This guide takes an app from no selling at all to a paid, fulfilled and refunded sale in the storefront shape, then live. In the storefront shape the buyer pays the seller: Stripe charges on the seller's own Stripe account (a direct charge) and sends your fee to you. The seller owns their refunds and disputes, and Stripe's processing fee is the seller's unless you choose to pay it.

Running a marketplace instead, where your app takes the money and pays sellers out? Follow Zero to first sale: marketplace. The two guides share their steps; the differences are called out in each.

Note

What you can use today. Every console step and server route below works now. The SDK screens and hooks (<SellerHome>, <SellerItems>, <BuyButton>, <SellerSales> and the rest) are in @buildbase/sdk 1.2.0 and later. You can also call the routes named on each module's page from your own screens.

Before you start

  • A BuildBase app with the SDK installed (installation) and two test users you can sign in as: one seller, one buyer.
  • A Staging environment to test in (step 0). It takes Stripe test keys only, so nothing real is charged.
  • A Stripe account. In the Stripe Dashboard, in test mode (the mode of your test keys), turn Connect on and complete your platform profile.
  • A webhook endpoint on your server for BuildBase events, if your server acts on sales (webhooks).
  • Selling open for your app. If Billing, Selling says Selling is not open for this app yet, contact BuildBase support.

Storefront and marketplace side by side

Storefront (this guide)Marketplace
Who the buyer paysThe seller, on the seller's Stripe accountYour app, which sends the seller's share
Your feeSent to you by Stripe from each chargeKept from the charge on your account
Refunds and disputesThe seller's (you can refund too)Yours only
Stripe's feesThe seller's, or yours if you chooseYours
Stripe TaxOn each seller's account, which each seller sets upOn your account
Carts across sellersOne Stripe page per seller, in turnOne Stripe page for the whole cart
Seller's countriesCountries Stripe supports for sellers in your regionA narrower list Stripe can pay out to
Seller gives emailNoYes

0. Open Staging

Everything up to step 12 happens in a Staging environment. In the console, choose Staging in the environment switcher at the top, or add it there with Add environment (owners and admins). Staging keeps its own users, settings and Stripe keys apart from Production, and takes Stripe test keys only. Point your app at it with its environment key (environments), so the seller and buyer you sign in as in steps 5 and 7 are Staging users.

No Staging environment yet? Environments are switched on per app as the platform rolls them out: yours has them once the console shows Environments under Settings > General. Until then, your Production environment accepts Stripe test keys too. Make your first test sale there with your test keys (steps 1 to 12, with a Test keys badge on Selling), then switch to your live keys there in step 13.

1. Save your Stripe test keys in Staging

In the console, in Staging, open Billing, Credentials and save your Stripe test secret and publishable keys. Selling and Item types appear in the Billing menu, under Selling, once they are saved. Staging refuses a live key: "Staging accepts Stripe test keys only (sk_test_ and pk_test_). Live keys belong in production."

Billing, Credentials with a Stripe test secret key and publishable key saved, and Selling and Item types listed under Selling in the Billing menu

2. Set selling up as a storefront

Open Billing, Selling. The Overview tab is a checklist of seven steps, each saved on its own:

The Selling Overview tab in Staging, the header reading Staging: test keys: Let your users sell at 1 of 7 done, Your Stripe account is ready ticked, steps 2 to 7 still to do, and the Go live step open with a Test keys badge, saying nothing real is charged in Staging and going live happens from Production

  1. Your Stripe account is ready. Press Check my Stripe account: your secret key works, Connect is on and your platform profile is complete.
  2. How selling works. Choose Storefront: the buyer pays the seller. The choice locks once the first seller joins, because each seller's Stripe account is made for it.
  3. Money. Set your fee (a percent, a fixed part and a minimum) and who pays Stripe's fee. Choose what happens to your fee on a refund, and whether Stripe Tax works out tax at checkout. In the storefront shape, Stripe Tax runs on each seller's account, so each seller completes Stripe Tax's settings in Stripe; leave it off for a first sale.
  4. Who can sell. People, workspaces or both; their countries; your currencies; whether you approve each seller by hand.
  5. Receive your sellers' Stripe events. Press Set it up for me, then Create the endpoint. In the storefront shape every sale happens on a seller's account, so this Connect endpoint is how payments, refunds, disputes and subscription renewals reach your app.
  6. Your terms and policies. Link your seller terms and refund policy (both required), and your fee disclosure, buyer terms and privacy policy, each a full https:// address, and set your Order page so buyers get a receipt email.
  7. Turn on selling. In Staging it runs on your test keys: nothing real is charged.

How selling works with Storefront chosen: the buyer pays the seller on their own Stripe account, and refunds and disputes are the seller's

The Money step: a 10% fee, the live preview of what a seller keeps at $5, $10, $50, $100 and $500, keep or return the fee on a refund, and Tax at checkout off

3. Design an item type

Open Billing, Item types, choose New item type and start from the ready-made Service or commission type: a fixed price, a message for the buyer and work the seller delivers by hand. Name it Coaching session (key coaching-session), work through the sections and press Publish v1. Item types never touch Stripe, so they are the same in both shapes.

The item type builder on the Pricing section of Coaching session, with the seller's form previewed on the right and Publish enabled

More in item types.

4. Add the seller screens to your app

Install Stripe's Connect loader and pass it to the provider:

npm install @stripe/connect-js
app/providers.tsx
import { ApiVersion } from '@buildbase/sdk';
import { SaaSOSProvider } from '@buildbase/sdk/react';
import { loadConnectAndInitialize } from '@stripe/connect-js/pure';

import '@buildbase/sdk/css';

export function BuildBaseProvider({ children }: { children: React.ReactNode }) {
  return (
    <SaaSOSProvider
      serverUrl="https://api.console.buildbase.app"
      version={ApiVersion.V1}
      orgId="your-org-id"
      loadConnectAndInitialize={loadConnectAndInitialize}
      // auth and your other props as in the installation guide
    >
      {children}
    </SaaSOSProvider>
  );
}

Allow https://connect-js.stripe.com and https://js.stripe.com in your Content-Security-Policy's script-src and frame-src. Then give sellers a page with their account, their items and their sales:

app/selling/page.tsx
'use client';

import {
  SellerHome,
  SellerItems,
  SellerSales,
  useSaaSAuth,
} from '@buildbase/sdk/react';

export default function SellingPage() {
  const { user } = useSaaSAuth();
  return (
    <>
      <SellerHome subject={{ user: true }} defaultDisplayName={user?.name} />
      <SellerItems
        subject={{ user: true }}
        itemTypeKeys={['coaching-session']}
      />
      <SellerSales subject={{ user: true }} />
    </>
  );
}

5. Onboard a seller

Sign in to your app as the seller and open the selling page. Start selling shows your fee and who pays Stripe's fee; the seller picks their country and the name buyers see (no email: a storefront seller's Stripe account is their own contact). Stripe's onboarding opens inside your app; in Staging, on your test keys, it accepts Stripe's test values. Back in your app the seller reads Can sell and Can get paid.

SellerHome once the seller is active: Can sell and Can get paid, and Payouts and balance open on the balance and two payouts

The seller shows under Billing, Selling, Sellers. If you approve sellers by hand, open the row's menu (...) and choose Approve.

The Sellers tab: one seller Active, one Onboarding and one Awaiting your approval, with the row menu open on Refresh from Stripe, Approve, Pause selling and Close account

6. Publish an item

As the seller, press New item in <SellerItems> and fill in an item of Coaching session: a title, a price of $45.00, under Add a message the message the buyer reads after paying, and, under Add something you deliver, what the seller will do. Press Publish (Send for review when you approve items). If you approve items, approve it from its row's menu under Billing, Selling, Items, Needs review; the seller gets the Item Approved email.

SellerItems with the item form open: title, summary, a USD price of $45.00, and the message a buyer gets after paying

7. A buyer pays

The shop page is the same in both shapes:

app/shop/page.tsx
'use client';

import {
  BuyButton,
  formatMinorAmountIntl,
  usePublishedItems,
} from '@buildbase/sdk/react';

export default function ShopPage() {
  const { items } = usePublishedItems({ typeKey: 'coaching-session' });
  return items.map((item) => {
    const variant = item.variants[0];
    const price = variant.prices[0];
    return (
      <div key={item._id}>
        <h2>{item.title}</h2>
        {/* some prices have no fixed amount */}
        {price.amount !== undefined && (
          <p>{formatMinorAmountIntl(price.amount, price.currency)}</p>
        )}
        <BuyButton
          itemId={item._id}
          variantId={variant.id}
          priceId={price.id}
        />
      </div>
    );
  });
}

Sign in as the buyer and press the button. Stripe's page opens on the seller's Stripe account; in Staging, pay with Stripe's test card 4242 4242 4242 4242, any future date and any CVC.

Stripe's hosted checkout in test mode for Coaching session at $45.00, on the seller's own Stripe account

Back on your page, useMyOrder(orderId, { waitForPayment: true }) shows the order once paid. Your server gets order.created, then grant.created and order.paid; the buyer gets the Order Receipt email.

The Order Receipt email: the app's name, Coaching session at $45.00, the seller, and a button to the order page

8. Where the money went

Stripe charged the buyer on the seller's account and sent your fee to your account as an application fee. The order page under Billing, Selling, Orders shows the total, your fee and the seller's share.

An order page in the storefront shape: $45.00 charged on the seller's Stripe account, your fee $4.50 sent to you, the seller's share $40.50, and the cart it was bought in

9. Fulfil the order

A line whose item includes a benefit the seller delivers by hand (kind: 'manual') waits on the seller (fulfilment: 'due'). <SellerItems> adds it under Add something you deliver when the item type allows it, as it does a licence key and something your app delivers (webhook_only); your own screen or server can save it with the item too. An item with only a message reads Nothing to send. In <SellerSales> the seller opens the sale and presses Mark as sent with a note the buyer reads. You can do the same with Mark fulfilled on the order page. Your server gets order.fulfilled.

SellerSales on one sale in the storefront shape: what the seller receives, Mark as sent on the line, and Refund

10. Refund it

In the storefront shape the seller can refund from <SellerSales>, and so can you, from the order page or your server (POST /api/v1/server/commerce/orders/:id/refund). The seller's Stripe balance pays the refund, and your fee on the refunded part goes back to them unless you chose to keep it under Money. Your server gets order.refunded.

The refund dialog on an order: the Coaching session line, $45.00 of $45.00 left, a reason, and Refund $45.00

A buyer who disputes the charge is answered in the seller's own Stripe Dashboard; the order shows the dispute until the bank decides.

11. Payouts

Stripe pays the seller's balance to their bank on their payout schedule. The seller sees Payouts and balance inside <SellerHome>; you see each seller's balance and latest payouts on their page under Sellers. Your server gets payout.created, payout.paid and payout.failed. Your fees land in your own Stripe balance and are paid out on your schedule.

A seller's page in the console: Active, Can sell and Can get paid, the Stripe balance, and the latest payouts with their arrival dates

12. Tick off the go-live list

In Staging, the Overview tab's Before going live list checks the setup steps, selling on, policy pages, tax on sales, the Connect endpoint's events, a clean Reconcile, a seller who can sell, a test sale and a test refund. The last item, Going live, reads In Production: going live happens in your Production environment.

The Overview tab in Staging with selling on: seller counts, the Go live card with a Test keys badge, and Test a sale in Staging with every check Done except Tax on sales, which is Worth a look, and Going live, which reads In Production

13. Go live in Production

Switch to Production with the environment switcher at the top of the console. Production keeps its own settings and item types, so set selling up there as you did in Staging (steps 2 and 3). Save your live keys under Billing, Credentials (until you do, Selling shows a Test keys badge; with live keys it reads Live), complete your platform profile in Stripe live mode, set up the live Connect webhook endpoint (Set it up for me), run the Stripe check again and turn selling on. Live keys reads Not yet open until live selling is open for your app; contact BuildBase support to open it. Each seller finishes Stripe's onboarding again in live mode, and with Stripe Tax on, completes its settings on their own live account. More in test in Staging, then go live.

The Overview tab in Production with selling on and Stripe test keys: the header and the Go live card read Test keys, and Before going live lists Platform profile in live mode, A seller can sell and Live keys to do, with a first sale and a refund recommended

When something stops you

What you seeWhyWhat to do
Selling is not open for this app yetSelling is off for your app on the platformContact BuildBase support
SELLER_COUNTRY_NOT_ALLOWEDA country you do not allowAllow it under Who can sell
CHECKOUT_REFUSED, tax_not_readyStripe Tax is on but not set up on the seller's accountThe seller completes Stripe Tax's settings in Stripe, or turn tax off
SELLER_CANNOT_SELLThe seller is paused, or Stripe needs more from themThe seller finishes what <SellerHome> asks; or resume them under Sellers
Payments or renewals never arriveThe Connect endpoint is missing eventsSelling, Settings, "Your sellers' Stripe events": Set it up for me
REFUND_FAILEDStripe made no refundRead the reason in the seller's Stripe account; nothing was returned
Live keys refused under Billing, Credentials in StagingStaging takes Stripe test keys only (sk_test_, pk_test_)Save your live keys in Production
SELLING_UNAVAILABLE: This environment sells with Stripe test keys onlyA live key in a non-production environment such as StagingUse test keys there; go live in Production
SELLING_UNAVAILABLE with live keysLive selling is not open for your app yetContact BuildBase support, or save your test keys again

Next steps