Skip to main content
The PROVESA Web content management system provides comprehensive control over all website content through an intuitive admin interface. All content is stored in a PostgreSQL database and rendered dynamically.

Content Types

The platform manages several distinct content types:

Hero Sliders

Full-screen homepage banner carousel

Products

Product showcase with images and descriptions

About Content

Company information and team details

Footer

Site footer with links and branch locations

Legal Pages

Terms of service and privacy policy

Suggestions

Customer feedback and inquiries

Job Applications

Employment candidate management

Contests

Promotional contests and winners

Hero Sliders

Manage homepage banner slides in the Sliders tab.

Slide Structure

{
  id: 1,
  imageUrl: 'https://cdn.provesa.com/slides/slide1.jpg',
  title: 'El pulso de la',
  highlight: 'distribución',
  highlightColor: 'text-accent-yellow',
  description: 'Garantizamos el abastecimiento estratégico...',
  badge: 'Solidez desde 2006',
  align: 'left'
}

Adding Slides

1

Click 'Nuevo Slide'

Opens the creation form in the Sliders tab.
2

Upload Image

Drag and drop or click to upload. The upload endpoint (/api/upload) handles file storage:
async function uploadImage(file) {
  const formData = new FormData();
  formData.append('file', file);
  const res = await fetch('/api/upload', { method: 'POST', body: formData });
  const data = await res.json();
  return data.url;
}
Recommended specs:
  • Resolution: 1920×1080px
  • Format: JPG, PNG, or WebP
  • Max size: 10MB
3

Configure Text

  • Título principal: Main white text (3-5 words)
  • Palabra destacada: Colored keyword (1-2 words, max 30 chars)
  • Descripción corta: Subtitle (max 150 chars)
  • Etiqueta superior: Optional badge label
4

Set Visual Options

  • Text position: Left, Center, or Right
  • Highlight color: Yellow, Blue, Red, or White
5

Preview and Save

Live preview shows exactly how the slide will appear. Click “Agregar Slide” to save.

Editing and Deleting

Click the edit icon on any slide to modify its properties inline. Click the delete icon to remove a slide.
When all custom slides are deleted, the site reverts to showing 3 default slides to prevent an empty homepage.

Products

Manage the product showcase section in the Productos tab.

Product Structure

{
  id: 1,
  name: 'Arroz Premium Salguero',
  description: 'El protagonista de la canasta familiar ecuatoriana...',
  images: [
    'https://cdn.provesa.com/products/arroz1.jpg',
    'https://cdn.provesa.com/products/arroz2.jpg',
    'https://cdn.provesa.com/products/arroz3.jpg'
  ],
  align: 'left',              // 'left' or 'right'
  accentColor: 'primary',     // 'primary' or 'accent'
  displayType: 'features',    // 'features' or 'categories'
  features: [
    { title: 'Grano Largo y Envejecido', desc: 'Perfecto para cocción uniforme.' },
    { title: 'Ideal para el Hogar', desc: 'Presentaciones de 1kg, 2kg y 5kg.' }
  ],
  categories: [
    { num: '01', name: 'Aceites', desc: 'Variedad de marcas y presentaciones.' }
  ]
}

Display Types

Show specific product benefits:Use when:
  • Highlighting a single flagship product
  • Emphasizing quality and features
  • Building trust with specific claims
Features:
  • Vertical list with icons
  • Title + description for each feature
  • Icons: BadgeCheck, ShoppingBasket, Truck, Award
  • Recommended: 3-4 features

Image Management

Each product supports multiple images that auto-rotate on the public site:
  • Click + to upload additional images
  • Images cycle every 4 seconds
  • Recommended: 3 images per product
  • Hover over thumbnails to delete
async function uploadImage(file, target) {
  isUploading = true;
  const fd = new FormData();
  fd.append('file', file);
  const res = await fetch('/api/upload', { method: 'POST', body: fd });
  const data = await res.json();
  if (target === 'new') {
    newProduct.images = [...newProduct.images, data.url];
  }
  isUploading = false;
}
Use align to control layout:
  • left: Image left, content right
  • right: Content left, image right
Best practice: Alternate between products for magazine-style layout.

Managing Features and Categories

Adding items:
<button onclick={() => addFeature('new')}>+ Agregar</button>
Dynamically adds input fields for:
  • Features: Title and description
  • Categories: Number, name, and description
Removing items: Click the X button next to any feature or category (minimum 1 required).

About Content

The Nosotros tab manages company information displayed on the /nosotros page and homepage teaser.

Content Sections

  1. Homepage Teaser: Short company intro on the main page
  2. Full About Page: Complete company history, mission, values
  3. Team Members: Staff profiles with photos and roles
The about page supports rich text editing for formatting company history and mission statements.
The Footer tab controls site-wide footer content.

Company Info

  • Company name and tagline
  • Copyright text
  • Brief description

Branch Locations

  • Multiple office/store locations
  • Address, phone, email per branch
  • Opening hours

Social Media

  • Facebook, Instagram, Twitter links
  • WhatsApp contact
  • LinkedIn profile

Quick Links

  • Navigation links
  • Legal pages
  • Contact information
The Páginas Legales tab manages:

Terms of Service

  • Located at /politicas/terminos
  • Full terms and conditions
  • User agreements
  • Service policies

Privacy Policy

  • Located at /politicas/privacidad
  • Data collection practices
  • Cookie policies
  • User rights
Legal content supports HTML formatting for structured documents with headings, lists, and emphasis.

Suggestions

The Sugerencias tab displays customer feedback submitted via the homepage form.

Suggestion Structure

{
  id: 1,
  tipo: 'Producto',        // Suggestion type
  nombre: 'Juan Pérez',
  email: 'juan@email.com',
  telefono: '0987654321',
  mensaje: 'Me gustaría que agreguen...',
  leido: false,            // Read status
  createdAt: '2024-03-15T10:30:00Z'
}

Features

  • Badge notification: Unread count appears on sidebar tab
  • Mark as read: Click to toggle read status
  • Filter by type: View by suggestion category
  • Contact details: Email and phone for follow-up
Unread suggestions show with a badge in the admin sidebar:
let unreadSugerencias = $derived(data.sugerencias?.filter((s) => !s.leido).length || 0);

Job Applications

The Candidatos tab manages employment applications submitted through /empleo.

Application Data

  • Applicant name and contact information
  • Desired position/branch
  • Resume upload (PDF)
  • Application date
  • Status tracking

Application Management

  1. View applications: See all submissions in a table
  2. Download resumes: Click to view uploaded CVs
  3. Filter by position: Sort by job opening
  4. Update status: Mark as reviewed, shortlisted, rejected

Contests

The Concursos tab manages promotional contests and winners.

Contest Structure

{
  id: 1,
  titulo: 'Gran Sorteo Navideño 2024',
  descripcion: 'Participa y gana increíbles premios...',
  fechaInicio: '2024-12-01',
  fechaFin: '2024-12-31',
  imagen: 'https://cdn.provesa.com/contests/navidad.jpg',
  activo: true
}

Winner Management

{
  concursoId: 1,
  nombre: 'María González',
  premio: 'iPad Pro',
  fechaSorteo: '2025-01-05',
  foto: 'https://cdn.provesa.com/winners/maria.jpg'
}
Display winners on the public contests page at /concursos.

File Upload System

All image uploads use a centralized API endpoint:

Upload Endpoint

Route: POST /api/upload Implementation (src/routes/api/upload/+server.js):
export async function POST({ request }) {
  const formData = await request.formData();
  const file = formData.get('file');
  
  // Validate file type and size
  if (!file.type.startsWith('image/')) {
    return json({ error: 'Invalid file type' }, { status: 400 });
  }
  
  if (file.size > 10 * 1024 * 1024) { // 10MB
    return json({ error: 'File too large' }, { status: 400 });
  }
  
  // Save file to storage (filesystem, S3, etc.)
  const url = await saveFile(file);
  
  return json({ url });
}

Supported Formats

  • Images: JPG, PNG, WebP, GIF
  • Documents: PDF (for resumes)
  • Max size: 10MB per file
Ensure your server has adequate storage and implement file cleanup for deleted content.

Content Workflow

Typical content management workflow:
1

Access Admin Dashboard

Log in at /login with admin credentials.
2

Navigate to Content Section

Use sidebar to select the content type (Sliders, Productos, etc.).
3

Create or Edit Content

  • Click “Nuevo” button to create
  • Click edit icon on existing items to modify
4

Upload Media

Drag and drop images or click to browse. Wait for upload confirmation.
5

Fill Content Fields

Complete all required text fields, descriptions, and configuration options.
6

Preview (if available)

Use live preview to see how content will appear on the public site.
7

Save Changes

Click “Guardar” or “Agregar” button. Wait for success confirmation.
8

Verify on Public Site

Visit the relevant public page to confirm changes are live.

Database Schema

Content is stored in PostgreSQL tables managed by Drizzle ORM:
  • slides: Hero slider content
  • products: Product showcase items
  • nosotros: About page content
  • footer: Footer configuration
  • legal_pages: Terms and privacy content
  • sugerencias: Customer suggestions
  • postulaciones: Job applications
  • concursos: Contest information
  • ganadores: Contest winners

Real-time Updates

Changes to content are immediately visible:
  1. Admin saves content → Database updated
  2. Public page requested → Fresh data loaded from database
  3. Content rendered → Visitors see new content
No cache clearing or rebuild required. All pages are server-rendered with live database queries.

Content Validation

Forms include validation to ensure data integrity:
  • Required fields: Cannot submit without essential data
  • Character limits: Enforced on text fields (e.g., 150 chars for descriptions)
  • File type checking: Only appropriate file types accepted
  • File size limits: Prevents oversized uploads
<textarea
  bind:value={newSlide.description}
  maxlength="150"
  required
></textarea>
<p class="text-xs text-slate-400">
  {newSlide.description.length}/150 caracteres
</p>

Best Practices

Optimize Images

Compress images before upload to reduce load times. Use WebP format when possible.

Consistent Naming

Use descriptive, consistent names for products and categories.

Regular Backups

Back up content database regularly to prevent data loss.

Preview Changes

Always check the public site after making significant content updates.