E-commerce websites have become increasingly popular due to their convenience and accessibility. They allow users to buy goods over the internet and have them delivered. In this tutorial, you will learn how to build an e-commerce website using SvelteKit and Strapi CMS.
To follow along with this tutorial, ensure you meet the following criteria:
To get started, let’s create a new Strapi project that will serve as the application backend. To do that, open your terminal, navigate to the directory where you want to install the project and run the command below.
npx create-strapi-app@latest my-project --quickstart
After the project installation is completed, the application development server will start automatically. When you open the application in your browser, you will be required to create a new account.
After creating a new Strapi application account, you will be redirected to the application dashboard, as shown in the screenshot below.
Now, let’s create the Collection Types that define how the application's data is structured and managed. We will create the userInfo
, Product
, and cartItem
collection types by following the steps below.
userInfo
Collection Type**userInfo
as the display name, and click on the "continue" button as shown in the screenshot below.Next, let’s structure how data will be managed in the userInfo
collection type by adding the following fields:
fullname
: type → textemail
: type → Emailpassword
: type → TextAfter adding the fields above, click the "Save" button, as shown in the screenshot below.
Repeat the above steps to create the following collection types.
Create a collection type named product
and add the following fields:
productName
: type→textproductDescription
: type→textproductImage
: type→ multiple mediaproductPrice
: type→textCreate a collection type named cartItem
and add the following fields:
userID
: type→textproductID
: type→textWe need to enable public access for each to interact with the created collection types via an API call. To do this, navigate to Settings → Roles → Public from your Strapi side menu and select all operations for each collection type.
Before we proceed to the frontend, let’s add items to the Product collection type. To do this, navigate to the Content Manager from the side menu and click on the Product collection type. Then, add as many products as you like, as shown in the screenshot below.
Now, let’s start creating the application frontend using SvelteKit. To scaffold a new SvelteKit project, run the command below.
npx degit sveltejs/template my-ecommerce-app
cd my-ecommerce-app
npm install
In this tutorial, we will use the Svelte-routing library to handle the application's page navigation. To install the library, run the command below:
npm install svelte-routing
After the installation, open the project in your preferred code editor or IDE.
Now, let’s start creating the application functionalities and UI, such as the user authentication page, home page, and cart page. To create the application, follow the steps below.
The application's home page will display a list of all available products in the store for users to browse. To create this home page, navigate to the src
folder in your project's root directory and create a new folder named Components
to store the application’s component files. Inside the Components
folder, create a file named Home.svelte
and add the following code:
1<!-- Home.svelte -->
2<script>
3import { onMount } from "svelte";
4import { Link } from "svelte-routing";
5import Navbar from "./Navbar.svelte";
6
7let products = [];
8
9onMount(async () => {
10 try {
11 const response = await fetch(
12 "http://localhost:1337/api/products?populate=*",
13 );
14 const data = await response.json();
15 products = data.data.map((item) => ({
16 id: item.id,
17 name: item.attributes.productName,
18 description: item.attributes.productDescription,
19 price: parseFloat(item.attributes.productPrice),
20 imageUrl: item.attributes.productImage.data[0].attributes.url,
21 }));
22 } catch (error) {
23 console.error("Error fetching products:", error);
24 }
25});
26</script>
27
28<Navbar />
29
30<main>
31 <h1>Main Store</h1>
32 <div class="products">
33 {#each products as product}
34 <div class="product-card">
35 <img
36 src={`http://localhost:1337${product.imageUrl}`}
37 alt={product.name}
38 />
39 <div class="details">
40 <h2>{product.name}</h2>
41 <p>{product.description}</p>
42 <p class="price">${product.price.toFixed(2)}</p>
43 <Link to={`/product/${product.id}`}>
44 <button>View Product</button>
45 </Link>
46 </div>
47 </div>
48 {/each}
49 </div>
50 </main>
51
52<style>
53html,
54body {
55 margin: 0;
56 padding: 0;
57 width: 100%;
58 height: 100%;
59 overflow-x: hidden;
60}
61
62body {
63 font-family: Arial, sans-serif;
64 display: flex;
65 flex-direction: column;
66}
67
68nav {
69 background-color: #71b3bf;
70 color: white;
71 padding: 1em 0;
72 width: 100%;
73 box-sizing: border-box;
74}
75
76.nav-container {
77 display: flex;
78 justify-content: space-between;
79 align-items: center;
80 padding: 0 2em;
81 max-width: 1200px;
82 margin: 0 auto;
83}
84
85.nav-brand a {
86 color: white;
87 text-decoration: none;
88 font-size: 1.5em;
89 font-weight: bold;
90}
91
92.nav-links {
93 display: flex;
94 gap: 1em;
95}
96
97.nav-links a {
98 color: white;
99 text-decoration: none;
100 font-size: 1em;
101}
102
103.nav-links a:hover {
104 text-decoration: underline;
105}
106
107main {
108 padding: 2em;
109 width: 100%;
110 box-sizing: border-box;
111 flex: 1;
112}
113
114h1 {
115 color: #ff3e00;
116 text-transform: uppercase;
117 font-size: 2.5em;
118 font-weight: 300;
119 margin-bottom: 1em;
120}
121
122.products {
123 display: flex;
124 flex-wrap: wrap;
125 gap: 2em;
126 justify-content: center;
127}
128
129.product-card {
130 background: #fff;
131 border: 1px solid #ddd;
132 border-radius: 10px;
133 box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
134 overflow: hidden;
135 flex: 1 1 calc(33.333% - 2em);
136 max-width: calc(33.333% - 2em);
137 transition: transform 0.2s;
138 box-sizing: border-box;
139}
140
141.product-card:hover {
142 transform: scale(1.05);
143}
144
145.product-card img {
146 width: 100%;
147 height: 200px;
148 object-fit: cover;
149}
150
151.details {
152 padding: 1em;
153 text-align: left;
154}
155
156.details h2 {
157 margin: 0 0 0.5em;
158 font-size: 1.5em;
159 color: #333;
160}
161
162.details p {
163 margin: 0;
164 color: #666;
165}
166
167.price {
168 margin-top: 0.5em;
169 font-size: 1.2em;
170 font-weight: bold;
171 color: #ff3e00;
172 padding-top: 10px;
173}
174button {
175 background-color: transparent;
176 color: #71b3bf;
177 border: 1px solid #71b3bf;
178 padding: 0.75em 1.5em;
179 border-radius: 5px;
180 cursor: pointer;
181 font-size: 1em;
182 transition: background-color 0.3s;
183 margin-left: 30%;
184 margin-top: 25px;
185}
186
187button:hover {
188 background-color: #71b3bf;
189 color: white;
190 border: none;
191}
192
193@media (max-width: 768px) {
194 .product-card {
195 flex: 1 1 calc(50% - 2em);
196 max-width: calc(50% - 2em);
197 }
198}
199
200@media (max-width: 480px) {
201 .product-card {
202 flex: 1 1 100%;
203 max-width: 100%;
204 }
205}
206</style>
In the above code, the onMount
method fetches all the available products from the backend by making a GET
request to http://localhost:1337/api/products?populate=*
. The products are then rendered in the user interface inside the main component.
Here is what the home page looks like:
To create the registration page, in the src/Components
directory, create a file named Register.svelte
and add the following code to it:
1<!-- Register.svelte -->
2<script>
3import { createEventDispatcher } from "svelte";
4import { navigate } from "svelte-routing";
5let email = "";
6let fullname = "";
7let password = "";
8const dispatch = createEventDispatcher();
9
10const handleRegister = async () => {
11 try {
12 const checkResponse = await fetch(
13 `http://localhost:1337/api/user-infos?filters[email][$eq]=${email}`,
14 );
15 if (!checkResponse.ok) {
16 throw new Error("Error checking user registration status");
17 }
18 const existingUsers = await checkResponse.json();
19
20 if (existingUsers.data.length > 0) {
21 alert("User with this email is already registered");
22 return;
23 }
24 const response = await fetch("http://localhost:1337/api/user-infos", {
25 method: "POST",
26 headers: {
27 "Content-Type": "application/json",
28 },
29 body: JSON.stringify({
30 data: {
31 email: email,
32 fullname: fullname,
33 password: password,
34 },
35 }),
36 });
37
38 if (!response.ok) {
39 const errorData = await response.json();
40 throw new Error(errorData.error.message || "Registration failed");
41 }
42
43 alert(`Registered successfully.`);
44 navigate(`/login`);
45 } catch (error) {
46 alert(`Error: ${error.message}`);
47 }
48};
49
50const handleLoginLinkClick = () => {
51 navigate(`/login`);
52};
53</script>
54
55<main>
56 <h1>Register</h1>
57 <form on:submit|preventDefault={handleRegister}>
58 <label>
59 Fullname:
60 <input type="text" bind:value={fullname} required>
61 </label>
62 <label>
63 Email:
64 <input type="email" bind:value={email} required>
65 </label>
66 <label>
67 Password:
68 <input type="password" bind:value={password} required>
69 </label>
70 <button type="submit">Register</button>
71 </form>
72 <p>Already have an account? <a href="login" on:click|preventDefault={handleLoginLinkClick}>Login</a></p>
73 </main>
74
75<style>
76main {
77 text-align: center;
78 padding: 1em;
79 max-width: 240px;
80 margin: 0 auto;
81}
82
83h1 {
84 color: #ff3e00;
85 text-transform: uppercase;
86 font-size: 2em;
87 font-weight: 100;
88}
89
90label {
91 display: block;
92 margin: 0.5em 0;
93}
94
95input {
96 width: 100%;
97 padding: 0.5em;
98 margin: 0.5em 0;
99}
100
101button {
102 padding: 0.5em 1em;
103 background-color: #ff3e00;
104 color: white;
105 border: none;
106 cursor: pointer;
107}
108
109button:hover {
110 background-color: #e63600;
111}
112
113p {
114 margin-top: 1em;
115}
116
117a {
118 color: #ff3e00;
119 text-decoration: none;
120}
121
122a:hover {
123 text-decoration: underline;
124}
125</style>
From the code above, we create a registration form that accepts the user's information as input and stores it in the Strapi backend via an API call. Once the registration is successful, the user is redirected to the login page.
Below is what the registration page looks like:
To create the login page, create a file named Login.svelte
inside the Components
folder and add the following code:
1<!-- Login.svelte -->
2<script>
3import { createEventDispatcher } from "svelte";
4import { navigate } from "svelte-routing";
5
6let email = "";
7let password = "";
8let userId = "";
9const dispatch = createEventDispatcher();
10
11const handleLogin = async () => {
12 try {
13 const response = await fetch(
14 `http://localhost:1337/api/user-infos?filters[email][$eq]=${email}`,
15 );
16 if (!response.ok) {
17 throw new Error("Error checking user login status");
18 }
19 const data = await response.json();
20 if (data.data.length === 0) {
21 alert("User not found");
22 return;
23 }
24 const user = data.data[0].attributes;
25 if (user.password !== password) {
26 alert("Incorrect password");
27 return;
28 }
29 alert(`Logged in successfully`);
30 navigate(`/`);
31 document.cookie = `email=${user.email}; path=/; max-age=${7 * 24 * 60 * 60}`;
32 document.cookie = `fullname=${user.fullname}; path=/; max-age=${7 * 24 * 60 * 60}`;
33 document.cookie = `userId=${data.data[0].id}; path=/; max-age=${7 * 24 * 60 * 60}`;
34 } catch (error) {
35 alert(`Error: ${error.message}`);
36 }
37};
38
39const handleRegisterLinkClick = () => {
40 navigate(`/register`);
41};
42</script>
43
44<main>
45 <h1>Login</h1>
46 <form on:submit|preventDefault={handleLogin}>
47 <label>
48 Email:
49 <input type="email" bind:value={email} required>
50 </label>
51 <label>
52 Password:
53 <input type="password" bind:value={password} required>
54 </label>
55 <button type="submit">Login</button>
56 </form>
57 <p>Don't have an account? <a href="#" on:click={handleRegisterLinkClick}>Register</a></p>
58 </main>
59
60<style>
61main {
62 text-align: center;
63 padding: 1em;
64 max-width: 240px;
65 margin: 0 auto;
66}
67
68h1 {
69 color: #ff3e00;
70 text-transform: uppercase;
71 font-size: 2em;
72 font-weight: 100;
73}
74
75label {
76 display: block;
77 margin: 0.5em 0;
78}
79
80input {
81 width: 100%;
82 padding: 0.5em;
83 margin: 0.5em 0;
84}
85
86button {
87 padding: 0.5em 1em;
88 background-color: #ff3e00;
89 color: white;
90 border: none;
91 cursor: pointer;
92}
93
94button:hover {
95 background-color: #e63600;
96}
97
98p {
99 margin-top: 1em;
100}
101
102a {
103 color: #ff3e00;
104 text-decoration: none;
105}
106
107a:hover {
108 text-decoration: underline;
109}
110</style>
In the code above, we create a login form that accepts the user's email and password as input. If the login details are correct, the user's details are stored in cookies; otherwise, a login error is displayed for the user.
Here is what the login page looks like:
Now, let’s create the product preview page showing more details about each product. To do this, create a file named Product.svelte
inside the Components
folder and add the following code:
1<!-- Product.svelte -->
2<script>
3import { onMount } from "svelte";
4import { Link, navigate } from "svelte-routing";
5import Navbar from "./Navbar.svelte";
6export let id;
7
8let product = null;
9let userId = getCookie("userId");
10let successMessage = "";
11
12function getCookie(name) {
13 const value = `; ${document.cookie}`;
14 const parts = value.split(`; ${name}=`);
15 if (parts.length === 2) return parts.pop().split(";").shift();
16}
17
18onMount(async () => {
19 if (!userId) {
20 navigate("/login");
21 } else {
22 try {
23 const response = await fetch(
24 `http://localhost:1337/api/products/${id}?populate=*`,
25 );
26 const data = await response.json();
27 const attributes = data.data.attributes;
28 const imageUrl = attributes.productImage.data[0].attributes.url;
29 product = {
30 id: data.data.id,
31 name: attributes.productName,
32 description: attributes.productDescription,
33 price: parseFloat(attributes.productPrice),
34 imageUrl: `http://localhost:1337${imageUrl}`,
35 };
36 } catch (error) {
37 console.error("Error fetching product:", error);
38 }
39 }
40});
41
42const addToCart = async () => {
43 try {
44 const response = await fetch(`http://localhost:1337/api/cart-items`, {
45 method: "POST",
46 headers: {
47 "Content-Type": "application/json",
48 },
49 body: JSON.stringify({
50 data: {
51 userID: userId,
52 productID: id,
53 },
54 }),
55 });
56
57 if (!response.ok) {
58 throw new Error(response);
59 }
60
61 successMessage = "Product added to cart successfully!";
62 } catch (error) {
63 console.error("Error adding product to cart:", error);
64 }
65};
66</script>
67
68<Navbar />
69<main>
70 {#if product}
71 <div class="product-container">
72 <img src={product.imageUrl} alt={product.name} />
73 <div class="product-details">
74 <h1>{product.name}</h1>
75 <p>{product.description}</p>
76 <p class="price">${product.price.toFixed(2)}</p>
77 <button on:click={addToCart}>Add to Cart</button>
78 {#if successMessage}
79 <p class="success-message">{successMessage}</p>
80 <p><Link to="/cart/w">View Cart</Link></p>
81 {/if}
82 <p><Link to="/">Back to Home</Link></p>
83 </div>
84 </div>
85 {:else}
86 <p>Product not found</p>
87 {/if}
88 </main>
89
90<style>
91html,
92body {
93 margin: 0;
94 padding: 0;
95 width: 100%;
96 height: 100%;
97 overflow-x: hidden;
98 font-family: Arial, sans-serif;
99}
100
101body {
102 display: flex;
103 flex-direction: column;
104 align-items: center;
105 justify-content: center;
106}
107
108main {
109 display: flex;
110 justify-content: center;
111 align-items: center;
112 width: 100%;
113 height: 100%;
114 box-sizing: border-box;
115 padding: 2em;
116 background-color: #f9f9f9;
117}
118
119.product-container {
120 display: flex;
121 flex-direction: column;
122 align-items: center;
123 background: #fff;
124 border: 1px solid #ddd;
125 border-radius: 10px;
126 box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
127 overflow: hidden;
128 max-width: 600px;
129 width: 100%;
130 box-sizing: border-box;
131 padding: 2em;
132}
133
134.product-container img {
135 width: 50%;
136 height: auto;
137 border-bottom: 1px solid #ddd;
138 margin-bottom: 1em;
139}
140
141.product-details {
142 text-align: center;
143}
144
145h1 {
146 color: #ff3e00;
147 text-transform: uppercase;
148 font-size: 2em;
149 font-weight: 300;
150 margin: 0 0 1em;
151}
152
153p {
154 font-size: 1em;
155 color: #666;
156 margin: 0 0 1em;
157}
158
159.price {
160 font-size: 1.5em;
161 font-weight: bold;
162 color: #ff3e00;
163 margin: 0.5em 0;
164}
165
166button {
167 background-color: #ff3e00;
168 color: white;
169 border: none;
170 padding: 0.75em 1.5em;
171 border-radius: 5px;
172 cursor: pointer;
173 font-size: 1em;
174 transition: background-color 0.3s;
175}
176
177button:hover {
178 background-color: #e03500;
179}
180
181.success-message {
182 color: green;
183 font-weight: bold;
184 margin-top: 1em;
185}
186
187a {
188 color: #ff3e00;
189 text-decoration: none;
190 font-size: 1em;
191}
192
193a:hover {
194 text-decoration: underline;
195}
196</style>
From the code above, we fetch the details of a product from the Strapi endpoint using the product ID and render the product details, allowing the user to add the product to the cart.
From the image below, we can see the details of a product.
To create the cart page, create a file named Cart.svelte
and add the following code to it:
1<script>
2import { onMount } from "svelte";
3import { navigate } from "svelte-routing";
4import { Link } from "svelte-routing";
5import Navbar from "./Navbar.svelte";
6
7function getCookie(name) {
8 const value = `; ${document.cookie}`;
9 const parts = value.split(`; ${name}=`);
10 if (parts.length === 2) return parts.pop().split(";").shift();
11}
12
13let userId = getCookie("userId");
14let cart = [];
15let message = "";
16
17const fetchCartItems = async () => {
18 try {
19 const cartResponse = await fetch(`http://localhost:1337/api/cart-items`);
20 const cartData = await cartResponse.json();
21 const userCartItems = cartData.data.filter(
22 (item) => item.attributes.userID === userId,
23 );
24
25 const products = await Promise.all(
26 userCartItems.map(async (item) => {
27 const productResponse = await fetch(
28 `http://localhost:1337/api/products/${item.attributes.productID}?populate=*`,
29 );
30 const productData = await productResponse.json();
31 const attributes = productData.data.attributes;
32 const imageUrl = attributes.productImage.data[0].attributes.url;
33
34 return {
35 id: productData.data.id,
36 item_id: item.id,
37 name: attributes.productName,
38 description: attributes.productDescription,
39 price: parseFloat(attributes.productPrice),
40 imageUrl: `http://localhost:1337${imageUrl}`,
41 };
42 }),
43 );
44 cart = products;
45 } catch (error) {
46 console.error("Error fetching cart items:", error);
47 }
48};
49
50const deleteItem = async (cartItemId) => {
51 try {
52 const response = await fetch(
53 `http://localhost:1337/api/cart-items/${cartItemId}`,
54 {
55 method: "DELETE",
56 },
57 );
58 if (response.ok) {
59 console.log(`Item ${cartItemId} deleted successfully.`);
60 cart = cart.filter((product) => product.item_id !== cartItemId);
61 message = "Item removed successfully!";
62 setTimeout(() => (message = ""), 3000);
63 } else {
64 console.error(`Failed to delete item ${cartItemId}.`);
65 message = "Failed to remove item.";
66 setTimeout(() => (message = ""), 3000);
67 }
68 } catch (error) {
69 console.error("Error deleting item:", error);
70 message = "Error removing item.";
71 setTimeout(() => (message = ""), 3000);
72 }
73};
74
75onMount(() => {
76 if (!userId) {
77 navigate("/login");
78 } else {
79 fetchCartItems();
80 }
81});
82
83const handlePurchase = () => {
84 alert("You will be redirected to a payment gateway");
85 navigate("/");
86};
87
88$: totalPrice = cart
89 .reduce((total, product) => total + product.price, 0)
90 .toFixed(2);
91</script>
92
93<Navbar />
94<main>
95 {#if cart.length > 0}
96 <div class="checkout-container">
97 <h1>Cart</h1>
98 <ul class="product-list">
99 {#if message}
100 <div class="message">{message}</div>
101 {/if}
102 {#each cart as product}
103 <li class="product-item">
104 <img src={product.imageUrl} alt={product.name} />
105 <div class="product-details">
106 <p><strong>{product.name}</strong></p>
107 <p>{product.description}</p>
108 <p>Price: ${product.price.toFixed(2)}</p>
109 </div>
110 <button
111 class="delete-button"
112 on:click={() => deleteItem(product.item_id)}>Remove</button
113 >
114 </li>
115 {/each}
116 </ul>
117 <div class="total-price">
118 <p><strong>Total Price: ${totalPrice}</strong></p>
119 </div>
120 <button on:click={handlePurchase}>Check Out</button>
121 <p><Link to="/">Back to Home</Link></p>
122 </div>
123 {:else}
124 <p>Your cart is empty</p>
125 {/if}
126 </main>
127
128<style>
129html,
130body {
131 margin: 0;
132 padding: 0;
133 width: 100%;
134 height: 100%;
135 overflow-x: hidden;
136 font-family: Arial, sans-serif;
137}
138
139body {
140 display: flex;
141 flex-direction: column;
142 align-items: center;
143 justify-content: center;
144}
145
146main {
147 display: flex;
148 justify-content: center;
149 align-items: center;
150 width: 100%;
151 height: 100%;
152 box-sizing: border-box;
153 padding: 2em;
154 background-color: #f9f9f9;
155}
156
157.checkout-container {
158 display: flex;
159 flex-direction: column;
160 align-items: center;
161 background: #fff;
162 border: 1px solid #ddd;
163 border-radius: 10px;
164 box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
165 padding: 2em;
166 max-width: 600px;
167 width: 100%;
168 box-sizing: border-box;
169}
170
171.checkout-container h1 {
172 color: #ff3e00;
173 text-transform: uppercase;
174 font-size: 2em;
175 font-weight: 300;
176 margin: 0 0 1em;
177}
178
179.product-list {
180 list-style: none;
181 padding: 0;
182 margin: 0 0 2em;
183 width: 100%;
184}
185
186.product-item {
187 display: flex;
188 align-items: center;
189 border-bottom: 1px solid #ddd;
190 padding: 1em 0;
191}
192
193.product-item img {
194 width: 150px;
195 height: auto;
196 margin-right: 1em;
197 border-radius: 5px;
198}
199
200.product-details {
201 flex-grow: 1;
202}
203
204.product-details p {
205 margin: 0.5em 0;
206 font-size: 1em;
207 color: #666;
208}
209
210.total-price {
211 font-size: 1.2em;
212 font-weight: bold;
213 margin-bottom: 1em;
214}
215
216button {
217 background-color: #ff3e00;
218 color: white;
219 border: none;
220 padding: 0.75em 1.5em;
221 border-radius: 5px;
222 cursor: pointer;
223 font-size: 1em;
224 transition: background-color 0.3s;
225 margin-bottom: 1em;
226}
227
228button:hover {
229 background-color: #e03500;
230}
231
232a {
233 color: #ff3e00;
234 text-decoration: none;
235 font-size: 1em;
236}
237
238a:hover {
239 text-decoration: underline;
240}
241
242.delete-button {
243 background-color: #e03500;
244 color: white;
245 border: none;
246 padding: 0.5em 1em;
247 border-radius: 5px;
248 cursor: pointer;
249 font-size: 0.9em;
250 transition: background-color 0.3s;
251 margin-left: 1em;
252}
253
254.delete-button:hover {
255 background-color: #d02e00;
256}
257
258.message {
259 background-color: #dff0d8;
260 color: #3c763d;
261 padding: 1em;
262 border-radius: 5px;
263 margin-bottom: 1em;
264 font-size: 1em;
265 text-align: center;
266 width: 100%;
267 max-width: 600px;
268}
269</style>
From the code above, we fetch all the products in the cart and display them on the page. We also calculate the total price by summing up the prices of all the products in the cart.
Here is a demo of how the cart functionality works.
To wrap up the application, let’s create the application navbar component. Inside the Components
folder, create a file named Navbar.svelte
and add the following code to it:
1<script>
2import { Link, navigate } from "svelte-routing";
3
4function getCookie(name) {
5 const value = `; ${document.cookie}`;
6 const parts = value.split(`; ${name}=`);
7 if (parts.length === 2) return parts.pop().split(";").shift();
8}
9
10const email = getCookie("email");
11const fullname = getCookie("fullname");
12const userId = getCookie("userId");
13
14const handleLogout = () => {
15 document.cookie = "email=; path=/; max-age=0";
16 document.cookie = "fullname=; path=/; max-age=0";
17 document.cookie = "userId=; path=/; max-age=0";
18 navigate("/login");
19};
20</script>
21
22<nav>
23 <div class="nav-container">
24 <div class="nav-brand">
25 <Link to="/">My Store</Link>
26 </div>
27 <div class="nav-links">
28 <Link to="/">Home</Link>
29 {#if email}
30 <span>Welcome, {fullname}</span>
31 <Link to="/cart/w"><span class="meun">Cart</span></Link>
32 <a href="#" on:click|preventDefault={handleLogout}>Logout</a>
33 {:else}
34 <Link to="/login">Login</Link>
35 <Link to="/register">Register</Link>
36 {/if}
37 </div>
38 </div>
39 </nav>
40
41<style>
42nav {
43 background-color: #71b3bf;
44 color: white;
45 padding: 1em 0;
46 width: 100%;
47 box-sizing: border-box;
48}
49
50.nav-container {
51 display: flex;
52 justify-content: space-between;
53 align-items: center;
54 padding: 0 2em;
55 max-width: 1200px;
56 margin: 0 auto;
57}
58
59.nav-brand a {
60 color: white;
61 text-decoration: none;
62 font-size: 1.5em;
63 font-weight: bold;
64}
65
66.nav-links {
67 display: flex;
68 gap: 1em;
69}
70
71.nav-links a,
72.nav-links span {
73 color: white;
74 text-decoration: none;
75 font-size: 1em;
76}
77
78.nav-links span {
79 font-size: 1em;
80}
81.meun {
82 padding: 15px;
83}
84.meun:hover {
85 background-color: #71b3bf;
86}
87</style>
Here is a demo of our Cart functionality.
Next, let’s configure the application route. Inside the src
folder, open the App.svelte
file and replace its code with the following:
1<!-- App.svelte -->
2<script>
3import { Router, Link, Route } from "svelte-routing";
4import Home from "./Components/Home.svelte";
5import Login from "./Components/Login.svelte";
6import Register from "./Components/Register.svelte";
7import Product from "./Components/Product.svelte";
8import Cart from "./Components/Cart.svelte";
9</script>
10
11<main>
12 <Router>
13 <Route path="/" component="{Home}" />
14 <Route path="login" component="{Login}" />
15 <Route path="register" component="{Register}" />
16 <Route path="product/:id" component="{Product}" />
17 <Route path="cart/:id" component="{Cart}" />
18 </Router>
19 </main>
20
21<style>
22main {
23 text-align: center;
24 padding: 1em;
25 max-width: 100%;
26 margin: 0 auto;
27}
28</style>
Start the Svelte development server by running the command below in your terminal to test the application.
npm run dev
Next, open your browser and go to http://localhost:8080. You should see the application functioning as shown in the GIF image below.
In this tutorial, we learned the complete process, from setting up the backend with Strapi to developing the frontend with SvelteKit to create an e-commerce website.
Building an e-commerce website with SvelteKit and Strapi CMS offers a powerful and flexible solution for creating dynamic and responsive online stores.