In this short article we'll explore building a storefront with SvelteKit.
If you're new to Svelte, or SvelteKit, you should take a look at this article by Rich Harris explaining what the deal with SvelteKit is.
SvelteKit boasts a simple setup, run the following to initialize a new project:
npm init svelte@next my-commercejs-storefront
cd my-commercejs-storefront
npm install
npm run dev -- --open
Once your project is up and running, you'll want to install the @chec/commerce.js
dependency.
npm install @chec/commerce.js
Then inside of the directory src/lib
(you'll need to create it) add the file commerce.js
. Here you'll want to instantiate @chec/commerce.js
and add your PUBLIC API KEY.
import CommerceSDK from '@chec/commerce.js';
export const client = new CommerceSDK('pk_184625ed86f36703d7d233bcf6d519a4f9398f20048ec');
Storefront Index Page
Then all that's left to do inside of your .svelte
files (such as index.svelte
) is import the client
and call the usual Commerce.js methods to get your products, categories, etc.
If we wanted to get all of our categories and products, it would look something like:
<script context="module">
import { client } from '$lib/commerce.js';
export async function load() {
const { data: categories } = await client.categories.list();
const { data: products } = await client.products.list();
return {
props: {
categories,
products
}
};
}
</script>
<script>
export let categories;
export let products;
</script>
If you've used Sapper with Svelte before the above will look somewhat familiar, and if you've used other frontend frameworks like Next.js then returning your props
will look even more so.
Then using the variables categories
and products
we'll output the values to a list.
<ul>
{#each categories as category}
<li>
<a rel="prefetch" href="/categories/{category.slug}">{category.name}</a>
</li>
{/each}
</ul>
<ul>
{#each products as product}
<li>
<a rel="prefetch" href="/product/{product.permalink}">{category.name}</a>
</li>
{/each}
</ul>
Category Pages
Now we'll create the page for each of our categories.
Inside of a new file src/routes/categories/[slug].svelte
we'll add the following script module:
<script context="module">
import { client } from '$lib/commerce.js';
export async function load({ page }) {
const { slug } = page?.params;
const category = await client.categories.retrieve(slug, {
type: 'slug'
});
const { data: products } = await client.products.list({ category_slug: [slug] });
return {
props: {
category,
products
}
};
}
</script>
<script>
export let category;
export let products;
</script>
You'll notice above we're fetching the slug
from the page params
.
We then use this slug
to retrieve the category from Commerce.js:
const category = await client.categories.retrieve(slug, {
type: 'slug'
});
The same slug is used when fetching products from Commerce.js, but it is used as a filter:
const { data: products } = await client.products.list({ category_slug: [slug] });
Then all that's left to do on this page is return our category.name
and list out the products belonging to that category:
<h1>{category.name}</h1>
<ul>
{#each products as product}
<li>
<a rel="prefetch" href="/products/{product.permalink}">{product.name}</a>
</li>
{/each}
</ul>
That's it! You'll notice here we're returning a list of links to our products, so we'll create those pages next!
Product Pages
Similar to how we created the individual category pages, we'll do the same for products. But this time we'll call the file [permalink].svelte
since we're linking to the product permalink from the index and category pages.
Add the following code to src/routes/products/[permalink].svelte
:
<script context="module">
import { client } from '$lib/commerce.js';
export async function load({ page }) {
const { permalink } = page?.params;
const product = await client.products.retrieve(permalink, {
type: 'permalink'
});
return {
props: {
product
}
};
}
</script>
<script>
export let product;
</script>
<h1>{product.name}</h1>
<p>{product.price.formatted_with_symbol}</p>
That it for our product! You now can link users to your individual product pages 😅
Top comments (0)