Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ashcroft08/provesa-web/llms.txt

Use this file to discover all available pages before exploring further.

Directory Overview

PROVESA Web follows SvelteKit’s conventions with additional organizational patterns for maintainability:
provesa-web/
├── src/
│   ├── lib/
│   ├── routes/
│   ├── app.html
│   └── hooks.server.js
├── static/
├── drizzle/
├── package.json
└── svelte.config.js

Source Directory (src/)

Library Code (src/lib/)

Reusable components, utilities, and server-side logic.
src/lib/
├── assets/
│   └── images/              # Static image assets
├── components/              # Svelte components
│   ├── admin/              # Admin panel components
│   │   ├── AdminSidebar.svelte
│   │   ├── ConcursosTab.svelte
│   │   ├── ConfiguracionTab.svelte
│   │   ├── DashboardTab.svelte
│   │   ├── FooterTab.svelte
│   │   ├── NosotrosPageTab.svelte
│   │   ├── NosotrosTab.svelte
│   │   ├── PaginasLegalesTab.svelte
│   │   ├── PersonalizacionTab.svelte
│   │   ├── PlaceholderTab.svelte
│   │   ├── PostulacionesTab.svelte
│   │   ├── ProductosTab.svelte
│   │   ├── SlidersTab.svelte
│   │   └── SugerenciasTab.svelte
│   ├── Footer.svelte
│   ├── HeroSlider.svelte
│   ├── Navbar.svelte
│   ├── NosotrosTeaser.svelte
│   ├── ProductSection.svelte
│   ├── RedesSociales.svelte
│   └── SugerenciasForm.svelte
├── server/                  # Server-side code (Node.js only)
│   ├── db/
│   ├── repositories/
│   ├── services/
│   ├── auth.js
│   └── cloudinary.js
└── utils/                   # Shared utilities

Server Code (src/lib/server/)

All server-side logic is isolated here. This code never runs in the browser.

Database Layer (src/lib/server/db/)

db/
├── schemas/                 # Drizzle schema definitions
│   ├── auth.schema.js      # User, session, account, verification
│   ├── concursos.schema.js # Contests and winners
│   ├── empleo_sucursales.schema.js  # Job location branches
│   ├── footer.schema.js    # Footer info and branches
│   ├── hero_slides.schema.js # Homepage hero slides
│   ├── legal_pages.schema.js # Privacy, terms pages
│   ├── nosotros_config.schema.js # About us teaser config
│   ├── nosotros_page.schema.js   # Full about page content
│   ├── postulaciones.schema.js   # Job applications
│   ├── products.schema.js  # Product catalog
│   ├── site_config.schema.js     # Key-value site settings
│   ├── sugerencias.schema.js     # Customer suggestions
│   ├── sugerencias_config.schema.js # Suggestion form config
│   └── theme_config.schema.js    # Theme color settings
├── seeds/                   # Database seed files
│   ├── seed-admin.js       # Admin user creation
│   └── seed-theme.js       # Default theme setup
├── index.js                 # Database connection and setup
└── schema.js                # Central schema exports
Key Files:
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from './schema';
import { env } from '$env/dynamic/private';

if (!env.DATABASE_URL) throw new Error('DATABASE_URL is not set');

const client = postgres(env.DATABASE_URL);
export const db = drizzle(client, { schema });

Services Layer (src/lib/server/services/)

Business logic and data orchestration.
services/
├── concursos.service.js     # Contest management + file uploads
├── empleo.service.js        # Job location branches
├── footer.service.js        # Footer info and branch CRUD
├── legal.service.js         # Legal pages content
├── nosotros.service.js      # About us config and page
├── postulaciones.service.js # Job applications with file uploads
├── products.service.js      # Product catalog CRUD
├── site-config.service.js   # Site settings (logo, etc.)
├── slides.service.js        # Hero slider management
├── sugerencias.service.js   # Customer suggestions
└── theme.service.js         # Theme color management (CSS file)
Service Responsibilities:
  • Validate input data
  • Handle file uploads (Cloudinary integration)
  • Transform data (e.g., JSON parsing)
  • Calculate derived values (e.g., sortOrder)
  • Orchestrate multiple repository calls
  • Business rule enforcement

Repositories Layer (src/lib/server/repositories/)

Database access abstraction.
repositories/
├── concursos.repository.js  # Contest and winner queries
├── empleo.repository.js     # Job location queries
├── footer.repository.js     # Footer data queries
├── legal.repository.js      # Legal page queries
├── nosotros.repository.js   # About us queries
├── postulaciones.repository.js # Job application queries
├── products.repository.js   # Product CRUD queries
├── site-config.repository.js # Site config queries
├── slides.repository.js     # Hero slide queries
├── sugerencias.repository.js # Suggestion queries
└── upload.repository.js     # Cloudinary upload abstraction
Repository Pattern: Each repository provides a consistent API:
  • getAll() - Fetch all records (sorted)
  • getById(id) - Fetch single record
  • create(data) - Insert new record
  • update(id, data) - Update existing record
  • remove(id) - Delete record

Authentication (src/lib/server/auth.js)

Better Auth configuration:
import { betterAuth } from 'better-auth';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { db } from '$lib/server/db';
import * as schema from '$lib/server/db/schema';

export const auth = betterAuth({
    database: drizzleAdapter(db, { provider: 'pg', schema }),
    // ... auth configuration
});

File Uploads (src/lib/server/cloudinary.js)

Cloudinary configuration for image uploads.

Routes (src/routes/)

SvelteKit file-based routing with server-side data loading.
routes/
├── +layout.svelte           # Root layout (navbar, footer)
├── +layout.server.js        # Root layout data (theme, user)
├── +page.svelte             # Homepage
├── +page.server.js          # Homepage data loading
├── admin/                   # Admin panel (protected)
│   ├── +layout.svelte      # Admin layout with sidebar
│   ├── +layout.server.js   # Auth check, redirect if not logged in
│   ├── +page.svelte        # Admin dashboard
│   ├── +page.server.js     # Load all admin data
│   └── users/
│       └── +page.svelte    # User management
├── api/                     # API endpoints
│   └── upload/
│       └── +server.js      # Image upload endpoint
├── concursos/               # Contests page
│   ├── +page.svelte
│   └── +page.server.js
├── empleo/                  # Jobs/careers page
│   ├── +page.svelte
│   └── +page.server.js
├── login/                   # Login page
│   ├── +page.svelte
│   └── +page.server.js
├── nosotros/                # About us page
│   ├── +page.svelte
│   └── +page.server.js
├── politicas/               # Legal pages
│   ├── privacidad/
│   │   ├── +page.svelte
│   │   └── +page.server.js
│   └── terminos/
│       ├── +page.svelte
│       └── +page.server.js
├── recuperar/               # Password recovery
│   ├── +page.svelte
│   └── +page.server.js
└── restablecer-password/    # Password reset
    ├── +page.svelte
    └── +page.server.js
SvelteKit Route Conventions:
  • +page.svelte - Page component (UI)
  • +page.server.js - Server-side data loading and form actions
  • +layout.svelte - Shared layout wrapper
  • +layout.server.js - Layout data loading
  • +server.js - API endpoint (no UI)

Hooks (src/hooks.server.js)

Global server-side request handling:
import { building } from '$app/environment';
import { auth } from '$lib/server/auth';
import { svelteKitHandler } from 'better-auth/svelte-kit';

const handleBetterAuth = async ({ event, resolve }) => {
    // Attach session to event.locals if authenticated
    const session = await auth.api.getSession({ 
        headers: event.request.headers 
    });
    
    if (session) {
        event.locals.session = session.session;
        event.locals.user = session.user;
    }
    
    return svelteKitHandler({ event, resolve, auth, building });
};

export const handle = handleBetterAuth;
This makes event.locals.session and event.locals.user available in all server-side code.

Static Assets (static/)

Public files served directly:
static/
├── favicon.png
├── robots.txt
└── images/                  # Static images not managed by Cloudinary
Accessed via root path: /favicon.png, /images/logo.png

Database Migrations (drizzle/)

Drizzle Kit migration files:
drizzle/
└── migrations/
    ├── 0000_initial.sql
    ├── 0001_add_concursos.sql
    └── meta/

Configuration Files

package.json

Dependencies and scripts:
{
  "scripts": {
    "dev": "vite dev",
    "build": "vite build",
    "preview": "vite preview",
    "db:push": "drizzle-kit push",
    "db:studio": "drizzle-kit studio"
  }
}

svelte.config.js

SvelteKit configuration:
import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';

export default {
    preprocess: vitePreprocess(),
    kit: {
        adapter: adapter()
    }
};

drizzle.config.js

Drizzle ORM configuration:
import { defineConfig } from 'drizzle-kit';

export default defineConfig({
    schema: './src/lib/server/db/schema.js',
    out: './drizzle/migrations',
    dialect: 'postgresql',
    dbCredentials: {
        url: process.env.DATABASE_URL
    }
});

File Naming Conventions

Components

  • PascalCase: ProductSection.svelte, HeroSlider.svelte
  • Suffix: Always .svelte for components

Server Files

  • kebab-case: site-config.service.js, hero_slides.schema.js
  • Suffix: .service.js, .repository.js, .schema.js

Routes

  • kebab-case: restablecer-password/, politicas/
  • SvelteKit prefixes: +page.svelte, +layout.server.js

Database Tables

  • snake_case: hero_slides, empleo_sucursales, concursos_ganadores

Import Path Aliases

SvelteKit provides the $lib alias:
// Instead of: import { db } from '../../../lib/server/db';
import { db } from '$lib/server/db';

// Instead of: import { ProductSection } from '../../../lib/components/ProductSection.svelte';
import ProductSection from '$lib/components/ProductSection.svelte';
Other aliases:
  • $app/* - SvelteKit app modules
  • $env/* - Environment variables

Code Organization Best Practices

1. Colocation

Group related files together:
concursos/
├── concursos.schema.js      # Domain: concursos
├── concursos.repository.js  # Domain: concursos  
└── concursos.service.js     # Domain: concursos

2. Single Responsibility

One feature per file:
  • products.service.js handles ONLY products
  • footer.service.js handles ONLY footer

3. Consistent Exports

Named exports for services/repositories:
export const productsService = { /* ... */ };
Default exports for schemas:
export const products = pgTable(/* ... */);

4. Clear Dependencies

Import from higher-level abstractions:
// ✅ Good: Service imports repository
import { productsRepository } from '../repositories/products.repository.js';

// ❌ Bad: Route imports repository directly
import { productsRepository } from '$lib/server/repositories/products.repository.js';

Next Steps

Build docs developers (and LLMs) love