Experiments >

Supacart: a cart with supabase + svelte

Experiment #1077th April, 2021by Joshua Nussbaum

Lot’s of interesting tech is dropping. svelte-kit is now in beta, and supabase launched a bunch of stuff.

So it’s a good time to investigate what e-commerce looks like with these tools.


To setup a svelte-kit project

mkdir supacart && cd supacart
npm init svelte@next

Now add supabase-js:

yarn add -D @supabase/supabase-js


To start, it will just be a list of products:

drop table if exists products;

create table products (
  id serial primary key,
  permalink varchar not null unique,
  sku varchar not null unique,
  name varchar not null,
  details varchar not null default '',
  price money not null

create unique index products$permalink on products (permalink);

insert into products ( permalink, name, sku, price ) values ('t-shirt', 'T-Shirt', 't-shirt', '19.99');
insert into products ( permalink, name, sku, price ) values ('pants', 'Pants', 'pants', '79.99');

We’ll store env vars in .env:


Notice the prefix VITE_, that makes the variable available in the public bundle that is served to the browser. Since the private key should never be shared, it is not prefixed with VITE_.


The root route / will display a list of products:

<!-- src/routes/index.svelte -->
<script context="module">
  import db from '$lib/db'

  // load products from db
  export async function load() {
    return {
      props: {
        products: await db.products.all()

  export let products

{#each products as product}
    <a href="/products/{product.permalink}">{product.name}</a>

And the product page will be at /products/:permalink, so let’s create a page for that too:

<script context="module">
  import db from '$lib/db'

  export async function load({page}) {
    // find the product
    const product = await db.products.find(page.params.permalink)

    // if we found it, return it as a prop
    if (product) {
      return {
        props: {

    // oh shoot, we didn't find a product, so return 404
    return {
      status: 404,
      error: new Error('product not found')

  // this prop will be provided by the `load` function
  export let product

<p>SKU: {product.sku}</p>



Data access

The logic to access the DB is extracted to it’s own file src/lib/db.js. That will help keep our UI components slim, because they won’t have to deal directly with the database.

// src/lib/db.js
import { createClient } from '@supabase/supabase-js'

const supabase = createClient(

export default {
  products: {
    async all(options = {}) {
      const { data } = await supabase.from('products').select('*')

      return data

    async find(permalink) {
      const { data } = await supabase

      return data


That gives us everything we need to display a homepage and a product page. It can render server side and client side too.

view all experiments

Stay tuned in

Learn how to add more experimentation to your workflow