A full-stack e-commerce web application for computer hardware and setup products. Users can browse products, filter by category, save favorites, manage a shopping cart, and place orders. The application includes user authentication with login and registration functionality.
- Getting Started — Frontend
- Getting Started — Backend
- Test Account
- Project Structure
- Data Flow
- Responsibilities by Layer
The frontend is built with React 19 and Vite.
Requirements: Node.js installed on your machine.
# 1. Navigate to the frontend folder
cd setuplab-frontend
# 2. Install dependencies
npm install
# 3. Start the development server
npm run devThe application will be available at http://localhost:5173
The backend must also be running for the application to work correctly.
The backend is built with Node.js, Express, and MongoDB.
Requirements: Node.js and a MongoDB database (local or MongoDB Atlas).
cd setuplab-backendCreate a file named .env in the setuplab-backend/ folder with the following content:
PORT=3000
CONNECTION_STRING=your_mongodb_connection_string_here
ACCESS_TOKEN_SECRET=your_secret_key_here| Variable | Description |
|---|---|
PORT |
The port the server runs on (default: 3000) |
CONNECTION_STRING |
MongoDB connection URI (local or Atlas) |
ACCESS_TOKEN_SECRET |
Secret key used to sign and verify JWT tokens |
npm installnpm run seednpm run devThe backend API will be available at http://localhost:3000
A default test user is created automatically when the server starts (see below).
A default user is created automatically on server startup if it does not already exist.
| Field | Value |
|---|---|
| Username | user |
| Password | password |
| Method | Endpoint | Auth required | Description |
|---|---|---|---|
| GET | /api/products |
No | Returns all products |
| GET | /api/products/:id |
No | Returns a single product by ID |
| POST | /api/users/register |
No | Creates a new user account |
| POST | /api/users/login |
No | Logs in and returns a JWT token |
| GET | /api/users/current |
Yes (Bearer) | Returns the currently logged-in user |
| POST | /api/orders |
No | Creates a new order |
Protected endpoints require an
Authorization: Bearer <token>header.
setuplab-frontend/
├── index.html # HTML entry point
├── vite.config.js # Vite configuration
├── public/
│ └── images/ # Static images
└── src/
├── App.jsx # Root component — renders Navbar, Footer, and routes
├── main.jsx # Application entry point — mounts App with all Providers
├── api/
│ └── apiClient.js # Shared fetch wrapper for all HTTP requests to the backend
├── services/
│ ├── authService.js # Login, register, token and user storage functions
│ ├── productService.js # Fetch all products or a single product
│ └── orderService.js # Create a new order
├── context/
│ ├── AuthContext.jsx # Global auth state — user, token, login/logout/register
│ ├── CartContext.jsx # Global cart state — items persisted in localStorage
│ └── FavoritesContext.jsx # Global favorites state — persisted in localStorage
├── components/
│ ├── Navbar/ # Top navigation bar with links and cart icon
│ ├── Footer/ # Site footer
│ ├── Hero/ # Hero banner shown on the home page
│ ├── ProductCard/ # Card component for displaying a single product
│ ├── ProductList/ # Renders a grid of ProductCards
│ ├── CategoryFilter/ # Filter buttons for filtering products by category
│ ├── CartItem/ # Single item row in the shopping cart
│ ├── CheckoutForm/ # Form for entering customer and payment details
│ ├── PageHeader/ # Reusable page title/header component
│ └── ScrollToTop/ # Scrolls to top on route change
├── pages/
│ ├── HomePage/ # Landing page with hero and featured products
│ ├── ProductsPage/ # All products with category filter
│ ├── ProductDetailsPage/ # Single product with full details
│ ├── FavoritesPage/ # List of favorited products
│ ├── CartPage/ # Shopping cart with quantity controls
│ ├── CheckoutPage/ # Checkout form — requires items in cart
│ ├── ConfirmationPage/ # Order confirmation after successful checkout
│ └── LoginRegisterPage/ # Login and registration on the same page
├── routes/
│ └── AppRoutes.jsx # Defines all client-side routes using React Router
├── helpers/
│ └── formatPrice.js # Utility for formatting prices
└── styles/
└── global.css # Global CSS variables and base styles
setuplab-backend/
├── server.js # Entry point — sets up Express, middleware, routes, and starts the server
├── package.json
├── config/
│ └── dbConnection.js # Connects to MongoDB using Mongoose
├── routes/
│ ├── productRoutes.js # GET /api/products, GET /api/products/:id
│ ├── orderRoutes.js # POST /api/orders
│ └── userRoutes.js # POST /api/users/register, POST /api/users/login, GET /api/users/current
├── controllers/
│ ├── productController.js # Handles product logic — fetch all or one product
│ ├── orderController.js # Handles order creation and saves to database
│ └── userController.js # Handles registration, login, and current user
├── models/
│ ├── productModel.js # Mongoose schema for products
│ ├── orderModel.js # Mongoose schema for orders
│ └── userModel.js # Mongoose schema for users
├── middleware/
│ ├── validateTokenHandler.js # Verifies JWT token — protects private routes
│ └── errorHandler.js # Global error handler — formats error responses
└── seed/
├── seedProducts.js # Seeds the database with initial product data
└── seedDefaultUser.js # Creates a default test user on server startup
Below is a description of how data flows through the application from the user's perspective.
User visits /products
→ ProductsPage calls productService.getProducts()
→ productService calls apiClient.request("/products")
→ GET http://localhost:3000/api/products
→ Express routes to productController.getProducts()
→ productController queries MongoDB via productModel
→ MongoDB returns product documents
← productController formats and returns JSON
← Express sends response
← apiClient returns parsed JSON
← productService returns array of products
← ProductsPage stores products in local state
← Products are rendered via ProductList → ProductCard
User clicks "Add to cart" on a ProductCard
→ CartContext.addToCart(product) is called
→ Cart state is updated in memory
→ Updated cart is saved to localStorage
← All components using CartContext re-render with updated cart
User fills in CheckoutForm and submits
→ CheckoutPage calls orderService.createOrder(orderData)
→ orderService calls apiClient.request("/orders", { method: "POST", body: ... })
→ POST http://localhost:3000/api/orders
→ Express routes to orderController.createOrder()
→ Request body is validated (customer, paymentMethod, items)
→ Order is saved to MongoDB via orderModel
← orderController returns the saved order
← Express sends response
← apiClient returns order data
← orderService returns order
← User is redirected to /confirmation
← Cart is cleared
User submits login form
→ LoginRegisterPage calls AuthContext.login(username, password)
→ AuthContext calls authService.loginUser()
→ POST http://localhost:3000/api/users/login
→ Express routes to userController.loginUser()
→ Username is looked up in MongoDB
→ Password is verified with bcrypt
→ JWT access token is generated and returned
← Express sends token + user data
← authService receives token
← AuthContext saves token to localStorage and updates auth state
← isLoggedIn becomes true — UI updates accordingly
| Layer | Responsibility |
|---|---|
pages/ |
Full-page views. Fetch data, manage local state, compose components. |
components/ |
Reusable UI pieces. Receive props and render markup. No direct API calls. |
context/ |
Global state shared across the entire app (auth, cart, favorites). |
services/ |
All communication with the backend API. One service per resource. |
api/ |
Low-level HTTP logic. Shared request() function used by all services. |
routes/ |
Defines URL paths and which page component is rendered for each path. |
helpers/ |
Small utility functions (e.g. formatting prices). |
styles/ |
Global CSS variables and base styles applied across the entire application. |
| Layer | Responsibility |
|---|---|
server.js |
Bootstraps the application — registers middleware, routes, and starts server. |
routes/ |
Maps HTTP method + URL to the correct controller function. |
controllers/ |
Business logic — validates input, queries the database, sends responses. |
models/ |
Mongoose schemas that define the shape of data stored in MongoDB. |
middleware/ |
Reusable request processing — JWT validation and global error handling. |
config/ |
Database connection setup. |
seed/ |
Scripts for populating the database with initial or default data. |
En fullstack e-handelssajt för datorkomponenter och setup-produkter. Användare kan bläddra bland produkter, filtrera på kategori, spara favoriter, hantera en varukorg och lägga beställningar. Applikationen har inbyggd användarautentisering med inloggning och registrering.
- Kom igång — Frontend
- Kom igång — Backend
- Testkonto
- Projektstruktur
- Dataflöde
- Vad varje del ansvarar för
Frontenden är byggd med React 19 och Vite.
Krav: Node.js måste vara installerat på din dator.
# 1. Navigera till frontend-mappen
cd setuplab-frontend
# 2. Installera beroenden
npm install
# 3. Starta utvecklingsservern
npm run devApplikationen är tillgänglig på http://localhost:5173
Backendet måste också vara igång för att applikationen ska fungera korrekt.
Backendet är byggt med Node.js, Express och MongoDB.
Krav: Node.js och en MongoDB-databas (lokal eller MongoDB Atlas).
cd setuplab-backendSkapa en fil med namnet .env i mappen setuplab-backend/ med följande innehåll:
PORT=3000
CONNECTION_STRING=din_mongodb_connection_string_här
ACCESS_TOKEN_SECRET=din_hemliga_nyckel_här| Variabel | Beskrivning |
|---|---|
PORT |
Porten som servern körs på (standard: 3000) |
CONNECTION_STRING |
MongoDB-anslutnings-URI (lokal eller Atlas) |
ACCESS_TOKEN_SECRET |
Hemlig nyckel som används för att signera och verifiera JWT-tokens |
npm installnpm run seednpm run devBackend-API:et är tillgängligt på http://localhost:3000
En standardanvändare skapas automatiskt när servern startar (se nedan).
En standardanvändare skapas automatiskt när servern startar, om den inte redan finns.
| Fält | Värde |
|---|---|
| Användarnamn | user |
| Lösenord | password |
| Metod | Endpoint | Kräver auth | Beskrivning |
|---|---|---|---|
| GET | /api/products |
Nej | Returnerar alla produkter |
| GET | /api/products/:id |
Nej | Returnerar en specifik produkt baserat på ID |
| POST | /api/users/register |
Nej | Skapar ett nytt användarkonto |
| POST | /api/users/login |
Nej | Loggar in och returnerar en JWT-token |
| GET | /api/users/current |
Ja (Bearer) | Returnerar den inloggade användaren |
| POST | /api/orders |
Nej | Skapar en ny order |
Skyddade endpoints kräver headern
Authorization: Bearer <token>.
setuplab-frontend/
├── index.html # HTML-startpunkt
├── vite.config.js # Konfiguration för Vite
├── public/
│ └── images/ # Statiska bilder
└── src/
├── App.jsx # Rotkomponent — renderar Navbar, Footer och routes
├── main.jsx # Applikationens startpunkt — monterar App med alla Providers
├── api/
│ └── apiClient.js # Gemensam fetch-funktion för alla HTTP-anrop till backend
├── services/
│ ├── authService.js # Inloggning, registrering, token- och användarlagring
│ ├── productService.js # Hämtar alla produkter eller en specifik produkt
│ └── orderService.js # Skapar en ny order
├── context/
│ ├── AuthContext.jsx # Global autentiseringsstate — användare, token, login/logout
│ ├── CartContext.jsx # Global varukorgsstate — sparas i localStorage
│ └── FavoritesContext.jsx # Global favoritstate — sparas i localStorage
├── components/
│ ├── Navbar/ # Navigeringsfält högst upp med länkar och kundkorgsikon
│ ├── Footer/ # Sidfot
│ ├── Hero/ # Hero-banner som visas på startsidan
│ ├── ProductCard/ # Kortkomponent för att visa en enskild produkt
│ ├── ProductList/ # Renderar ett rutnät av ProductCards
│ ├── CategoryFilter/ # Filterknappar för att filtrera produkter efter kategori
│ ├── CartItem/ # En rad i varukorgen för en enskild produkt
│ ├── CheckoutForm/ # Formulär för att fylla i kunduppgifter och betalning
│ ├── PageHeader/ # Återanvändbar sidtitel/rubrikkomponent
│ └── ScrollToTop/ # Scrollar till toppen vid sidnavigering
├── pages/
│ ├── HomePage/ # Startsida med hero och populära produkter
│ ├── ProductsPage/ # Alla produkter med kategorifilter
│ ├── ProductDetailsPage/ # Enskild produkt med fullständig information
│ ├── FavoritesPage/ # Lista med favoritmarkerade produkter
│ ├── CartPage/ # Varukorg med möjlighet att ändra antal
│ ├── CheckoutPage/ # Kassasida — kräver produkter i varukorgen
│ ├── ConfirmationPage/ # Orderbekräftelse efter genomförd beställning
│ └── LoginRegisterPage/ # Inloggning och registrering på samma sida
├── routes/
│ └── AppRoutes.jsx # Definierar alla klientsidans routes med React Router
├── helpers/
│ └── formatPrice.js # Hjälpfunktion för att formatera priser
└── styles/
└── global.css # Globala CSS-variabler och grundstilar
setuplab-backend/
├── server.js # Startpunkt — sätter upp Express, middleware, routes och startar servern
├── package.json
├── config/
│ └── dbConnection.js # Kopplar upp mot MongoDB med Mongoose
├── routes/
│ ├── productRoutes.js # GET /api/products, GET /api/products/:id
│ ├── orderRoutes.js # POST /api/orders
│ └── userRoutes.js # POST /api/users/register, POST /api/users/login, GET /api/users/current
├── controllers/
│ ├── productController.js # Produktlogik — hämtar alla eller en specifik produkt
│ ├── orderController.js # Orderlogik — skapar och sparar order i databasen
│ └── userController.js # Användarlogik — registrering, inloggning och hämtning av inloggad användare
├── models/
│ ├── productModel.js # Mongoose-schema för produkter
│ ├── orderModel.js # Mongoose-schema för ordrar
│ └── userModel.js # Mongoose-schema för användare
├── middleware/
│ ├── validateTokenHandler.js # Verifierar JWT-token — skyddar privata endpoints
│ └── errorHandler.js # Global felhanterare — formaterar felmeddelanden
└── seed/
├── seedProducts.js # Fyller databasen med startprodukter
└── seedDefaultUser.js # Skapar en standardanvändare när servern startar
Nedan beskrivs hur data flödar genom applikationen ur användarens perspektiv.
Användaren besöker /products
→ ProductsPage anropar productService.getProducts()
→ productService anropar apiClient.request("/products")
→ GET http://localhost:3000/api/products
→ Express skickar vidare till productController.getProducts()
→ productController hämtar data från MongoDB via productModel
→ MongoDB returnerar produktdokument
← productController formaterar och returnerar JSON
← Express skickar svar
← apiClient returnerar tolkad JSON
← productService returnerar array med produkter
← ProductsPage sparar produkterna i lokalt state
← Produkterna renderas via ProductList → ProductCard
Användaren klickar "Lägg i varukorg" på en ProductCard
→ CartContext.addToCart(product) anropas
→ Varukorgens state uppdateras i minnet
→ Uppdaterad varukorg sparas i localStorage
← Alla komponenter som använder CartContext renderas om med uppdaterad data
Användaren fyller i CheckoutForm och skickar
→ CheckoutPage anropar orderService.createOrder(orderData)
→ orderService anropar apiClient.request("/orders", { method: "POST", body: ... })
→ POST http://localhost:3000/api/orders
→ Express skickar vidare till orderController.createOrder()
→ Request body valideras (kunduppgifter, betalningsmetod, produkter)
→ Ordern sparas i MongoDB via orderModel
← orderController returnerar den sparade ordern
← Express skickar svar
← apiClient returnerar orderdata
← orderService returnerar ordern
← Användaren omdirigeras till /confirmation
← Varukorgen töms
Användaren skickar inloggningsformuläret
→ LoginRegisterPage anropar AuthContext.login(username, password)
→ AuthContext anropar authService.loginUser()
→ POST http://localhost:3000/api/users/login
→ Express skickar vidare till userController.loginUser()
→ Användarnamnet slås upp i MongoDB
→ Lösenordet verifieras med bcrypt
→ En JWT-token genereras och returneras
← Express skickar token och användardata
← authService tar emot token
← AuthContext sparar token i localStorage och uppdaterar auth-state
← isLoggedIn blir true — gränssnittet uppdateras
| Lager | Ansvar |
|---|---|
pages/ |
Helsidiga vyer. Hämtar data, hanterar lokalt state och sätter ihop komponenter. |
components/ |
Återanvändbara UI-delar. Tar emot props och renderar markup. Gör inga direkta API-anrop. |
context/ |
Globalt state som delas i hela applikationen (auth, varukorg, favoriter). |
services/ |
All kommunikation med backend-API:et. En service-fil per resurs. |
api/ |
Lågnivå HTTP-logik. Gemensam request()-funktion som används av alla services. |
routes/ |
Definierar URL-sökvägar och vilken sidkomponent som renderas för varje path. |
helpers/ |
Små hjälpfunktioner (t.ex. formatering av priser). |
styles/ |
Globala CSS-variabler och grundstilar som gäller i hela applikationen. |
| Lager | Ansvar |
|---|---|
server.js |
Startar applikationen — registrerar middleware, routes och startar servern. |
routes/ |
Mappar HTTP-metod + URL till rätt controller-funktion. |
controllers/ |
Affärslogik — validerar indata, frågar databasen och skickar svar. |
models/ |
Mongoose-scheman som definierar hur data ser ut i MongoDB. |
middleware/ |
Återanvändbar request-hantering — JWT-validering och global felhantering. |
config/ |
Databaskopplingskonfiguration. |
seed/ |
Skript för att fylla databasen med startdata eller standardanvändare. |