SETUP PROTOCOLS — REAL CODE ANALYSIS 2026

Development & Run Guide

The complete, code-verified playbook for cloning, configuring, and running Lastiendas. Every section is derived from real file analysis — no guesswork.

1. Verified Technology Stack

FRONTEND

Next.js 15.5.4

App Router with 'use client' directives. Static HTML export configured (output: 'export'). React 18.2.0 with hooks-first architecture. Tailwind CSS v4 for utility styling.

package.json: next@15.5.4 / react@18.2.0
BACKEND

PHP 8.2 REST API

Custom REST API without a framework. PDO (PHP Data Objects) for all database queries. 85 PHP endpoint files organized into 17 modules. Bearer token session authentication stored in user_sessions table.

api/ — 85 files across 17 directories
DATABASE

MySQL 8.0

Managed via PDO with utf8mb4 charset. DSN-based connection: mysql:host=localhost;dbname=u278171752_jess_DB. Full database dump available in jess_DB.sql (194KB).

jess_DB.sql — production dump
EMAIL

Hostinger SMTP

Custom SMTP mailer via api/utils/smtp_mailer.php and hostinger_mailer.php. Template-based email system in api/utils/email.php (39KB). Configuration in api/config/email.php.

api/utils/email.php — 39KB engine

2. Full Dependency Registry

NPM Production Dependencies

next@15.5.4
Core framework. App Router, SSR, static export, image optimization.
react@18.2.0 react-dom@18.2.0
React core and DOM renderer. Used with hooks useState, useEffect, useContext.
@react-google-maps/api@^2.20.8
Google Maps integration. Key stored in NEXT_PUBLIC_GOOGLE_MAPS_API_KEY env var. Used in LocationPicker.js.
leaflet@^1.9.4 react-leaflet@^5.0.0
Open-source map alternative. LocationPickerLeaflet.js — no API key required.
@tinymce/tinymce-react@^6.3.0
Rich text editor. Used for page content management in ManagePages.js and email templates. Configured in src/config/tinymce.js.
mysql2@^3.15.2
MySQL driver for Node.js. Used in any server-side Next.js routes if applicable.

NPM Dev Dependencies

tailwindcss@^4 @tailwindcss/postcss@^4
Tailwind CSS v4 with PostCSS toolchain. Config in tailwind.config.js and postcss.config.mjs.
eslint@^8 eslint-config-next@15.5.4
Code linting. ESLint disabled during builds (ignoreDuringBuilds: true) in next.config.mjs.

Environment Variables

NEXT_PUBLIC_GOOGLE_MAPS_API_KEY
Located in .env.local. Required for Google Maps location picker. Must be prefixed with NEXT_PUBLIC_ for client-side access.
API_BASE_URL
Defined in src/config/api.js (NOT .env). Currently set to https://lastiendas.pe/api. Change this single constant to switch environments.

3. Local Development Setup

Important: This project has two independent parts — the Next.js frontend and the PHP backend API. They must run on separate ports.

Frontend: localhost:3000  |  PHP API: requires a web server like XAMPP or PHP's built-in server at localhost:8000

1

Clone & Install Frontend

# Navigate to your projects folder
cd "G:/Client Projects/Sell (Jess)/67/65"

# Install all Node.js dependencies
npm install

# Verify installation
npm list next
2

Configure Backend Database Connection

Open api/config/database.php. Switch to the LOCAL credentials block (lines 40-45) by commenting out production and uncommenting local:

// FOR LOCAL DEVELOPMENT (XAMPP):
private $host = "localhost";
private $db_name = "marketplace";  // Your local DB name
private $username = "root";
private $password = "";             // XAMPP default = empty
public $conn;

// FOR PRODUCTION (lastiendas.pe):
// private $host = "localhost";
// private $db_name = "u278171752_jess_DB";
// private $username = "u278171752_jess_user";
// private $password = "Pak@12345$$";
// public $conn;
3

Import the Database

Use phpMyAdmin or the MySQL CLI to import the production dump:

# Method 1: MySQL CLI
mysql -u root -p marketplace < jess_DB.sql

# Method 2: phpMyAdmin (XAMPP)
# 1. Open http://localhost/phpmyadmin
# 2. Create database: 'marketplace' (or your chosen name)
# 3. Import: jess_DB.sql (194KB)
4

Switch API Base URL to Local

Open src/config/api.js and comment out the production URL, uncomment localhost:

// SWITCH TO LOCAL:
const API_BASE_URL = 'http://localhost:8000/api'

// SWITCH TO PRODUCTION:
// const API_BASE_URL = 'https://lastiendas.pe/api'
5

Start the PHP Backend Server

The project includes a start_api.bat script. Or use PHP CLI directly:

# Option A: Use the included batch file (Windows)
start_api.bat

# Option B: PHP built-in server (from project root)
# ⚠ Navigate to a level that exposes /api
php -S localhost:8000 -t .

# Option C: XAMPP
# Copy project to C:/xampp/htdocs/lastiendas/
# Access via: http://localhost/lastiendas/api/
6

Start the Next.js Frontend

# Development mode (hot reload, error messages)
npm run dev
# Frontend available at: http://localhost:3000

# Production build (for testing final output)
npm run build
npm run start

4. Complete File Structure Map

Frontend: /src

src/
├── app/                        # Next.js App Router
│   ├── layout.js               # Root layout — injects LanguageProvider
│   ├── page.js                 # Homepage (24KB) — main marketplace
│   ├── globals.css             # Base styles
│   ├── admin/
│   │   └── page.js             # Admin dashboard (608 lines, 25KB)
│   ├── seller/
│   │   └── page.js             # Seller dashboard (493 lines, 20KB)
│   ├── auth/
│   │   └── page.js             # Login/Register page
│   ├── product/
│   │   └── [...slug]/          # Dynamic product pages
│   │       └── ClientPage.js   # Product detail view
│   ├── about-us/               # About page
│   ├── terms/                  # Terms of service
│   └── information/            # Info pages (dynamic content)
│
├── components/                 # Reusable UI components
│   ├── Navigation.js           # Main site navigation (8.5KB)
│   ├── Footer.js               # Global footer
│   ├── AuthModal.js            # Login/Register modal (11.8KB)
│   ├── ProductGrid.js          # Product listing grid (7.7KB)
│   ├── ProductModal.js         # Product quick-view (6.7KB)
│   ├── StarRating.js           # Star rating component (20KB)
│   ├── CompactRating.js        # Compact version (21KB)
│   ├── SearchFilters.js        # Search/filter bar (3KB)
│   ├── ToastContainer.js       # Toast notifications (2KB)
│   ├── LocationPickerLeaflet.js # Map (Leaflet, no API key)
│   │
│   ├── admin/                  # 25 Admin-only components
│   │   ├── Sidebar.js          # Admin navigation sidebar
│   │   ├── TopBar.js           # Admin top bar (8KB)
│   │   ├── DashboardOverview.js # Stats & metrics (11.8KB)
│   │   ├── ManageSellers.js    # Seller management (45.9KB) ← LARGEST
│   │   ├── ManageProducts.js   # Product moderation (20KB)
│   │   ├── UpcomingPayments.js # Payment tracking (27.8KB)
│   │   ├── NotificationsPanel.js # Email campaigns (20.7KB)
│   │   ├── EmailLogsPanel.js   # Email history (13.8KB)
│   │   ├── EmailTemplateManager.js # Template editor (23KB)
│   │   ├── ReviewsManager.js   # Review moderation (17.8KB)
│   │   ├── SponsoredProductsPanel.js # Sponsored ads (17.7KB)
│   │   ├── ManagePages.js      # CMS pages (13.3KB)
│   │   └── ...13 more components
│   │
│   └── seller/                 # 14 Seller-only components
│       ├── Sidebar.js          # Seller nav sidebar
│       ├── TopBar.js           # Seller top bar (7.9KB)
│       ├── DashboardSummary.js # Seller stats (7KB)
│       ├── ProductsTable.js    # Product list (14.6KB)
│       ├── AddProductForm.js   # Add/edit products (35.5KB) ← LARGEST
│       ├── MyCategoriesPanel.js # Category management (20.5KB)
│       ├── SubscriptionPanel.js # Payment info (19.4KB)
│       ├── ShopInfo.js         # Shop settings (24.8KB)
│       └── ...6 more components
│
├── config/
│   ├── api.js                  # ALL API endpoints (109 lines) ← KEY FILE
│   └── tinymce.js              # Rich text editor config
│
└── lib/
    ├── language.js             # i18n context provider + useLanguage hook
    ├── theme.js                # Theme utilities
    ├── searchLocation.js       # Location search logic
    └── languages/
        ├── en.json             # English translations
        └── es.json             # Spanish translations

Backend: /api

api/
├── .htaccess                   # CORS + mod_rewrite rules
│
├── config/                     # Core configuration
│   ├── database.php            # PDO Database class (71 lines)
│   ├── auth.php                # Token verification (112 lines)
│   ├── cors.php                # CORS headers handler
│   ├── email.php               # SMTP config (active)
│   └── email.example.php       # Template for new config
│
├── admin/                      # 31 admin-protected endpoints
│   ├── approve_user.php        # Seller approval (5.3KB)
│   ├── pending_users.php       # List pending (1.8KB)
│   ├── reject_user.php         # Reject user (1.8KB)
│   ├── delete_user.php         # Remove user (1.2KB)
│   ├── create_user.php         # Add seller (4.6KB)
│   ├── sellers.php             # All sellers data (3KB)
│   ├── reviews.php             # Review moderation (6.4KB)
│   ├── pages.php               # CMS CRUD (4.7KB)
│   ├── payment_settings.php    # Payment config (2.5KB)
│   ├── payments_overview.php   # Payment status (6.1KB)
│   ├── send_payment_reminders.php # Auto reminders (10.9KB)
│   ├── send_bulk_reminders.php # Bulk emails (11.1KB)
│   ├── send_manual_reminder.php # Single reminder (4.1KB)
│   ├── sponsored_requests.php  # Sponsored ads CRUD (14.6KB)
│   ├── email_logs.php          # Email history (6.4KB)
│   ├── email_templates.php     # Template CRUD (7KB)
│   └── ...15 more endpoints
│
├── auth/
│   ├── login.php               # Login + token issue (96 lines)
│   └── register.php            # Seller registration (temp table)
│
├── products/
│   └── index.php               # Products CRUD (GET/POST/PUT/DELETE/PATCH)
│
├── seller/                     # 14 seller endpoints
│   ├── profile.php             # Seller profile
│   ├── subscription.php        # Subscription status
│   ├── categories.php          # Seller categories
│   ├── payment_history.php     # Payment records
│   └── ...10 more endpoints
│
├── categories/                 # Category management
├── cities/                     # City management
├── sponsored/                  # Sponsored product endpoints
├── cron/                       # Scheduled tasks
│   └── send_payment_reminders.php
├── upload/                     # File upload handlers
│   ├── product_image.php       # Image uploads
│   └── receipt.php             # Payment receipt uploads
└── utils/                      # Shared utilities
    ├── email.php               # Core email engine (39KB)
    ├── smtp_mailer.php         # SMTP wrapper (4.6KB)
    ├── hostinger_mailer.php    # Hostinger-specific (10.7KB)
    ├── template_email_service.php # Template email (19KB)
    └── payment_reminder_utils.php # Reminder logic (10.7KB)

5. Authentication System — How It Works

The auth system uses a database-stored session token approach (not JWT). When a user logs in, a 64-char hex token is generated and stored in the user_sessions table with a 24-hour expiry.

Login Flow (api/auth/login.php)

// 1. Accept POST: { username, password }
// 2. Query user_accounts JOIN user_details
$query = "SELECT ua.id, ua.username, ua.password_hash, 
                 ua.user_type, ud.company_name ...
          FROM user_accounts ua
          LEFT JOIN user_details ud ON ud.user_id = ua.id";

// 3. Compare: password === password_hash (plaintext dev)
// 4. Generate token:
$token = bin2hex(random_bytes(32));

// 5. Store in DB:
INSERT INTO user_sessions (user_id, token, expires_at)
VALUES (?, ?, DATE_ADD(NOW(), INTERVAL 24 HOUR));

// 6. Return token to frontend

Frontend Auth Guard (src/app/admin/page.js)

// On mount, check localStorage:
const token = localStorage.getItem('auth_token')
const userData = localStorage.getItem('user_data')

if (!token || !userData) {
  router.replace('/auth')  // Redirect if not logged in
  return
}

const parsed = JSON.parse(userData)
if (parsed?.user_type !== 'admin') {
  router.replace('/seller') // Wrong user type
  return
}

setUser(parsed)
fetchAdminData(parsed)  // Load dashboard data

Token Verification (api/config/auth.php)

Every protected admin endpoint calls verifyToken(). It extracts the Bearer <token> from the Authorization header and validates it against the user_sessions table, checking expiry.

$query = "SELECT us.user_id, ua.username, ua.user_type
          FROM user_sessions us 
          JOIN user_accounts ua ON ua.id = us.user_id 
          WHERE us.token = ? AND us.expires_at > NOW()";

Sending Auth Headers (Frontend)

Every admin API call includes the Authorization header:

const token = localStorage.getItem('auth_token')
const authHeaders = token 
  ? { 'Authorization': `Bearer ${token}` } 
  : undefined

const res = await fetch(API_ENDPOINTS.ADMIN_SELLERS, {
  headers: authHeaders
})

6. The API Registry — src/config/api.js

This is the single source of truth for all 40+ API endpoints. To add a new endpoint, you ONLY touch this file and nothing else.

// src/config/api.js
const API_BASE_URL = 'https://lastiendas.pe/api'  // ← Change this for local dev

export const API_ENDPOINTS = {
  // Auth
  AUTH_LOGIN: `${API_BASE_URL}/auth/login.php`,
  AUTH_REGISTER: `${API_BASE_URL}/auth/register.php`,
  
  // Products (full CRUD via single index.php)
  PRODUCTS: `${API_BASE_URL}/products/`,
  
  // Categories & Cities
  CATEGORIES: `${API_BASE_URL}/categories/`,
  CITIES: `${API_BASE_URL}/cities/`,
  
  // Admin Endpoints (all protected)
  ADMIN_PENDING_USERS: `${API_BASE_URL}/admin/pending_users.php`,
  ADMIN_APPROVE_USER: `${API_BASE_URL}/admin/approve_user.php`,
  ADMIN_SELLERS: `${API_BASE_URL}/admin/sellers.php`,
  ADMIN_PAYMENTS_OVERVIEW: `${API_BASE_URL}/admin/payments_overview.php`,
  ADMIN_SPONSORED_REQUESTS: `${API_BASE_URL}/admin/sponsored_requests.php`,
  // ... 35+ more endpoints
}

How to Add a New Endpoint

// Step 1: Create PHP file in /api/
// e.g., api/admin/my_feature.php

// Step 2: Add to api.js
ADMIN_MY_FEATURE: `${API_BASE_URL}/admin/my_feature.php`,

// Step 3: Use in any component
import { API_ENDPOINTS } from '@/config/api'
const res = await fetch(API_ENDPOINTS.ADMIN_MY_FEATURE)

Helper: buildApiUrl()

// Append query params without string interpolation
import { buildApiUrl, API_ENDPOINTS } from '@/config/api'

const url = buildApiUrl(API_ENDPOINTS.PRODUCTS, {
  seller_id: currentUser.id,
  limit: 100,
  lang: 'es'
})
// Result: https://lastiendas.pe/api/products/?seller_id=3&limit=100&lang=es

7. Internationalization (i18n) System

Language Provider — src/lib/language.js

Wraps the entire app via src/app/layout.js. Uses React Context. Persists choice in localStorage. Defaults to Spanish ('es').

// How to use in any component:
import { useLanguage } from '@/lib/language'

const { t, language, changeLanguage } = useLanguage()

// Translate a key (dot-notation)
t('admin.dashboard')  // → "Panel de Control"

// Change language
changeLanguage('en')  // Switches globally

Translation Files

src/lib/languages/en.json
English strings. All keys must exist here.
src/lib/languages/es.json
Spanish strings. Default language.

To add a new translation key:

// en.json
{
  "admin": {
    "myNewFeature": "My New Feature"
  }
}
// Usage: t('admin.myNewFeature')

8. Production Deployment

Live Production — Currently deployed at https://lastiendas.pe (Hostinger)

Frontend Build & Deploy

# 1. Ensure API_BASE_URL = production URL in api.js
# 2. Build static export
npm run build
# Output: /out directory (static HTML/CSS/JS)

# 3. Upload /out folder to Hostinger public_html
# 4. The .htaccess handles routing

next.config.mjs sets output: 'export' — generates a static site in /out folder, ready for shared hosting.

Backend Deploy

# 1. Upload /api directory to server root
# 2. Edit api/config/database.php:
#    Set production credentials
# 3. Ensure api/.htaccess is present
#    (handles CORS headers + routing)
# 4. Verify cron jobs:
#    api/cron/send_payment_reminders.php
# 5. Run setup if needed:
#    setup.php (creates DB tables)

CORS Configuration (api/.htaccess)

The api/.htaccess and api/config/cors.php handle cross-origin requests. All PHP files include cors.php at the top to output the necessary headers for the frontend domain to communicate.

# api/.htaccess — Key rules
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, PATCH, OPTIONS"
Header always set Access-Control-Allow-Headers "Content-Type, Authorization"

9. Quick Command Reference

NPM Scripts

npm run dev
Start development server with hot reload at localhost:3000
npm run build
Build static export to /out folder for production upload
npm run start
Serve the production build locally (requires npm run build first)
npm run lint
Run ESLint across the codebase

Key Files to Know First

src/config/api.js
All API endpoints — the most important config file in the project
api/config/database.php
Switch environment here (local vs production credentials)
src/app/admin/page.js
Admin dashboard master controller — 608 lines, 19 components
src/app/seller/page.js
Seller dashboard master controller — 493 lines, 11 components
jess_DB.sql
Full production DB dump — use to seed local environment