Skip to main content

Installation

This guide covers everything you need to install and configure Villa Buena E-Commerce for development or production use.

Prerequisites

Before installing Villa Buena, ensure you have the following installed:

Node.js

Version 18.0.0 or higherDownload from nodejs.org

Package Manager

npm, yarn, or pnpmnpm comes with Node.js

Git

For cloning the repositoryDownload from git-scm.com

Code Editor

VS Code recommendedWith ESLint extension

Verify Prerequisites

Check that everything is installed correctly:
node --version  # Should be v18.0.0 or higher
npm --version   # Should be 8.0.0 or higher
git --version   # Any recent version

Installation Methods

Using NPM

1

Clone Repository

git clone <repository-url>
cd villa-buena-ecommerce
2

Install Dependencies

npm install
This installs all packages defined in package.json:12-22:Core Dependencies:
3

Setup Environment

Create .env file:
touch .env
Add configuration:
VITE_API_URL=https://dummyjson.com

Configuration

Environment Variables

Villa Buena uses Vite’s environment variable system. All variables must be prefixed with VITE_ to be exposed to client code. Create a .env file in the project root:
.env
# API Configuration
VITE_API_URL=https://dummyjson.com

# Optional: Custom Port
# VITE_PORT=3000
The API URL is consumed by the axios instance in src/services/api.js:4 using import.meta.env.VITE_API_URL.
Never commit .env files containing sensitive credentials to version control. Use .env.example for templates.

Auth0 Configuration

The application includes pre-configured Auth0 credentials for demo purposes (see src/main.jsx:15-20). For production use, configure your own Auth0 application:
1

Create Auth0 Account

Sign up at auth0.com for a free account.
2

Create Application

  1. Go to Applications > Create Application
  2. Choose “Single Page Web Applications”
  3. Select React as the technology
3

Configure Settings

In your Auth0 application settings:
  • Allowed Callback URLs: http://localhost:5173, https://yourdomain.com
  • Allowed Logout URLs: http://localhost:5173, https://yourdomain.com
  • Allowed Web Origins: http://localhost:5173, https://yourdomain.com
4

Update Application Code

Replace the Auth0 configuration in src/main.jsx:
src/main.jsx
<Auth0Provider
  domain="your-tenant.us.auth0.com"  // Your Auth0 domain
  clientId="your-client-id"          // Your application client ID
  authorizationParams={{ 
    redirect_uri: window.location.origin 
  }}
  onRedirectCallback={onRedirectCallback}
  cacheLocation="localstorage"
>
  <RouterProvider router={router} />
</Auth0Provider>
For development, you can use the pre-configured demo Auth0 credentials. They’re fully functional but shared across all demo instances.

Vite Configuration

The Vite configuration is minimal by default (vite.config.js):
vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
})
You can customize it for your needs:
vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: {
    port: 3000,           // Custom development port
    open: true,           // Auto-open browser
    host: true,           // Expose to network
  },
  build: {
    outDir: 'dist',       // Output directory
    sourcemap: true,      // Generate source maps
  },
  resolve: {
    alias: {
      '@': '/src',        // Path alias for imports
    },
  },
})

Project Structure

After installation, your project will have this structure:
villa-buena-ecommerce/
├── public/              # Static assets
├── src/
│   ├── app/            # Application core
│   │   ├── router.jsx  # Route definitions
│   │   ├── Layout.jsx  # Main layout wrapper
│   │   └── providers/  # React context providers
│   ├── components/     # Reusable UI components
│   │   ├── navbar/     # Navigation component
│   │   ├── cart/       # Cart-related components
│   │   ├── productCard/# Product display card
│   │   └── ...         # Other components
│   ├── pages/          # Route page components
│   │   ├── Home.jsx    # Product catalog page
│   │   ├── cart/       # Cart page
│   │   ├── account/    # Account dashboard
│   │   └── ...         # Other pages
│   ├── services/       # API service layer
│   │   ├── api.js      # Axios instance
│   │   ├── productService.js
│   │   └── categoryService.js
│   ├── store/          # Zustand state stores
│   │   ├── useCartStore.js   # Shopping cart state
│   │   ├── useUserStore.js   # User data state
│   │   └── uiStore.js        # UI preferences
│   ├── hooks/          # Custom React hooks
│   ├── main.jsx        # Application entry point
│   └── index.css       # Global styles
├── index.html          # HTML template
├── package.json        # Dependencies and scripts
├── vite.config.js      # Vite configuration
├── eslint.config.js    # ESLint rules
└── .env                # Environment variables (create this)

Development Dependencies

The following dev dependencies are included (package.json:23-33):

Running the Application

After installation, use these commands from package.json:6-10:
npm run dev
# Starts Vite dev server with HMR
# Available at http://localhost:5173

Application Entry Point

The application bootstraps in src/main.jsx:
src/main.jsx
import ReactDOM from "react-dom/client";
import { RouterProvider } from "react-router-dom";
import { router } from "./app/router";
import { QueryProvider } from "./app/providers/QueryProvider";
import "bootstrap/dist/css/bootstrap.min.css";
import "./index.css";
import { Auth0Provider } from "@auth0/auth0-react";

const onRedirectCallback = (appState) => {
  router.navigate(appState?.returnTo ?? window.location.pathname);
};

ReactDOM.createRoot(document.getElementById("root")).render(
  <QueryProvider>
    <Auth0Provider
      domain="dev-rafaelval.us.auth0.com"
      clientId="ripKJ8Jjq1c3gLEOcusOGUTBTFVGoVdG"
      authorizationParams={{ redirect_uri: window.location.origin }}
      onRedirectCallback={onRedirectCallback}
      cacheLocation="localstorage"
    >
      <RouterProvider router={router} />
    </Auth0Provider>
  </QueryProvider>,
);

Provider Hierarchy

  1. QueryProvider - Wraps app with TanStack Query client for data fetching
  2. Auth0Provider - Provides authentication context throughout the app
  3. RouterProvider - Handles client-side routing

Routing Configuration

Routes are defined in src/app/router.jsx using React Router’s createBrowserRouter:
src/app/router.jsx
import { createBrowserRouter } from "react-router-dom";
import { Home } from "../pages/Home";
import { ProductDetail } from "../pages/productDetail/ProductDetail";
import { Cart } from "../pages/cart/Cart";
import { Layout } from "./layout";

export const router = createBrowserRouter([
  {
    path: "/",
    element: <Layout />,
    children: [
      { index: true, element: <Home /> },
      { path: "product/:id", element: <ProductDetail /> },
      { path: "cart", element: <Cart /> },
      { path: "checkout/shipping", element: <CheckoutShipping /> },
      { path: "checkout/payment", element: <CheckoutPayment /> },
      { path: "payment/success", element: <PaymentSuccess /> },
      { path: "account", element: <AccountPage /> },
      { path: "orders", element: <OrderHistory /> },
    ],
  },
]);
All routes share the Layout component which provides:
  • Navbar with authentication controls
  • Toast notification system
  • Cart drawer
  • Dark mode theming

State Management Setup

Cart Store Example

The cart uses Zustand with persistence middleware (src/store/useCartStore.js):
src/store/useCartStore.js
import { create } from "zustand";
import { persist } from "zustand/middleware";

export const useCartStore = create(
  persist(
    (set) => ({
      cart: [],
      
      addToCart: (product) => set((state) => {
        const existing = state.cart.find(item => item.id === product.id);
        if (existing) {
          return {
            cart: state.cart.map(item =>
              item.id === product.id
                ? { ...item, qty: item.qty + 1 }
                : item
            ),
          };
        }
        return { cart: [...state.cart, { ...product, qty: 1 }] };
      }),
      
      // ... other cart methods
    }),
    { name: "cart-storage" }  // localStorage key
  )
);
The persist middleware automatically syncs cart state to localStorage, providing persistence across page refreshes.

Verification

Verify your installation by checking:
1

Dependencies Installed

ls node_modules | wc -l
# Should show 200+ packages
2

Environment Variables

cat .env
# Should display your VITE_API_URL
3

Dev Server Starts

npm run dev
# Should start without errors
4

Application Loads

Navigate to http://localhost:5173 and verify:
  • Product catalog displays
  • Navigation works
  • No console errors

Troubleshooting

Permission errors usually mean npm needs elevated privileges. Try:
sudo npm install --unsafe-perm=true
Or fix npm permissions: docs.npmjs.com/resolving-eacces-permissions-errors
Clear node_modules and reinstall:
rm -rf node_modules package-lock.json
npm install
Check if the port is already in use:
lsof -i :5173  # macOS/Linux
netstat -ano | findstr :5173  # Windows
Kill the process or change the port in vite.config.js.
Ensure your .env file:
  1. Is in the project root (not in src/)
  2. Uses VITE_ prefix for all variables
  3. Has been created before running npm run dev
Restart the dev server after creating/modifying .env.
The project uses ESLint 9 with new flat config format. If you see errors:
npm run lint
Review errors and fix or update eslint.config.js as needed.

Next Steps

Quick Start

Follow the quick start guide to explore core features

Architecture

Understand the application structure and patterns

API Services

Learn about the API service layer

State Management

Deep dive into Zustand stores
Now that installation is complete, explore the source code starting with src/main.jsx to understand how the application initializes and connects all the pieces together.

Build docs developers (and LLMs) love