Skip to main content

Overview

Ana’s Supplements is a custom EverShop theme designed for a health supplements store. It features a clean, modern design with a green/mint color scheme and Spanish language support.
This theme is located at themes/anasuplements/ and is activated in config/default.json.

Brand Colors

The theme uses a consistent color palette throughout:
ColorHex CodeUsage
Primary#2D5A3DButtons, headings, accent elements
Background#F8FAF9Page backgrounds, cards
Borders#E8F5E9Card borders, dividers
Text#4A5568Body text, descriptions
Hover#1E3D2AButton hover states

Color Usage Example

<button className="bg-[#2D5A3D] hover:bg-[#1E3D2A] text-white px-6 py-3 rounded-lg">
  Agregar al Carrito
</button>

Theme Structure

themes/anasuplements/
├── src/pages/
   ├── all/              # Global components
   ├── Header.tsx
   └── Footer.tsx
   ├── homepage/         # Homepage sections
   ├── Hero.tsx
   ├── Features.tsx
   └── FeaturedProducts.tsx
   └── account/          # Account pages
       ├── Login.tsx
       ├── Register.tsx
       └── Dashboard.tsx
├── package.json
└── tsconfig.json

Global Components

These components appear on every page. The header provides navigation, cart, and account access. Location: src/pages/all/Header.tsx
import React from 'react';

type HeaderProps = {
  storeName?: string;
  categories?: {
    name: string;
    url: string;
  }[];
};

export default function Header({ 
  storeName = "Ana's Suplements", 
  categories = [] 
}: HeaderProps) {
  return (
    <header className="bg-[#F8FAF9] border-b border-[#E8F5E9]">
      <div className="container mx-auto px-4 py-4">
        <div className="flex items-center justify-between">
          {/* Store name/logo */}
          <a href="/" className="text-2xl font-bold text-[#2D5A3D]">
            {storeName}
          </a>
          
          {/* Navigation */}
          <nav className="hidden md:flex space-x-6">
            {categories.map((category, index) => (
              <a 
                key={index} 
                href={category.url}
                className="text-[#4A5568] hover:text-[#2D5A3D] transition-colors"
              >
                {category.name}
              </a>
            ))}
          </nav>

          {/* Cart & Account icons */}
          <div className="flex items-center space-x-4">
            <a href="/cart" className="text-[#2D5A3D] hover:text-[#1E3D2A]">
              {/* Cart icon SVG */}
            </a>
            <a href="/account" className="text-[#2D5A3D] hover:text-[#1E3D2A]">
              {/* Account icon SVG */}
            </a>
          </div>
        </div>
      </div>
    </header>
  );
}

export const layout = {
  areaId: 'header',
  sortOrder: 1
};
Features:
  • Responsive design with mobile menu support
  • Dynamic category navigation
  • Shopping cart and account access
  • Branded color scheme
Multi-column footer with links and newsletter signup. Location: src/pages/all/Footer.tsx Key Sections:
  1. About - Store description
  2. Quick Links - Catalog, Account, Cart
  3. Customer Service - Contact, Shipping, Returns
  4. Newsletter - Email subscription form
The footer includes dynamic year using new Date().getFullYear() for automatic copyright updates.

Homepage Components

Hero Section

Location: src/pages/homepage/Hero.tsx
Sort Order: 1 (renders first)
export default function Hero() {
  return (
    <section className="bg-[#F8FAF9] py-16">
      <div className="container mx-auto px-4">
        <div className="text-center">
          <h1 className="text-4xl md:text-5xl font-bold text-[#2D5A3D] mb-4">
            Bienvenido a Ana's Suplements
          </h1>
          <p className="text-lg text-[#4A5568] mb-8 max-w-2xl mx-auto">
            Los mejores suplementos para tu salud y bienestar. 
            Productos de calidad premium para cuidar de ti.
          </p>
          <div className="flex justify-center gap-4">
            <a 
              href="/catalog" 
              className="bg-[#2D5A3D] text-white px-8 py-3 rounded-lg hover:bg-[#1E3D2A] transition-colors font-semibold"
            >
              Ver Catálogo
            </a>
            <a 
              href="/contact" 
              className="border-2 border-[#2D5A3D] text-[#2D5A3D] px-8 py-3 rounded-lg hover:bg-[#2D5A3D] hover:text-white transition-colors font-semibold"
            >
              Contactar
            </a>
          </div>
        </div>
      </div>
    </section>
  );
}
Features:
  • Large, centered headline
  • Descriptive subtitle
  • Two call-to-action buttons (primary and secondary styles)
  • Responsive text sizing (text-4xl md:text-5xl)

Features Section

Location: src/pages/homepage/Features.tsx
Sort Order: 5
Highlights four key benefits with icons:
  1. Calidad Garantizada - Quality assurance
  2. Envío Rápido - Fast shipping (24-48 hours)
  3. Asesoría Personalizada - Expert advice
  4. Natural y Orgánico - Natural ingredients
const features = [
  {
    icon: <svg>...</svg>,
    title: 'Calidad Garantizada',
    description: 'Todos nuestros productos cumplen con los más altos estándares de calidad'
  },
  // ... 3 more features
];

return (
  <section className="bg-[#E8F5E9] py-16">
    <div className="container mx-auto px-4">
      <h2 className="text-3xl font-bold text-center text-[#2D5A3D] mb-12">
        ¿Por Qué Elegirnos?
      </h2>
      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
        {features.map((feature, index) => (
          <div key={index} className="text-center">
            <div className="inline-flex items-center justify-center w-16 h-16 bg-[#2D5A3D] text-white rounded-full mb-4">
              {feature.icon}
            </div>
            <h3 className="font-semibold text-[#2D5A3D] mb-2">{feature.title}</h3>
            <p className="text-[#4A5568] text-sm">{feature.description}</p>
          </div>
        ))}
      </div>
    </div>
  </section>
);
Features:
  • Responsive grid (1 column → 2 → 4)
  • Circular icon containers
  • Light green background (#E8F5E9)
Location: src/pages/homepage/FeaturedProducts.tsx
Sort Order: 10
Displays a grid of featured products with custom ProductCard component.
type ProductCardProps = {
  product: {
    id: string;
    name: string;
    price: number;
    image?: string;
    url?: string;
  };
};

function ProductCard({ product }: ProductCardProps) {
  return (
    <div className="bg-white rounded-lg shadow-sm hover:shadow-md transition-shadow border border-[#E8F5E9] overflow-hidden">
      <div className="aspect-square bg-[#F8FAF9] flex items-center justify-center">
        {product.image ? (
          <img src={product.image} alt={product.name} className="w-full h-full object-cover" />
        ) : (
          <svg className="w-16 h-16 text-[#A0C4B0]">{/* Placeholder icon */}</svg>
        )}
      </div>
      <div className="p-4">
        <h3 className="font-semibold text-[#2D5A3D] mb-2 line-clamp-2">
          {product.name}
        </h3>
        <div className="flex items-center justify-between">
          <span className="text-lg font-bold text-[#2D5A3D]">
            ${product.price?.toFixed(2)}
          </span>
          <button className="bg-[#2D5A3D] text-white px-4 py-2 rounded text-sm hover:bg-[#1E3D2A] transition-colors">
            Agregar
          </button>
        </div>
      </div>
    </div>
  );
}
Sample Products:
const products = [
  { id: '1', name: 'Vitamina D3', price: 15.99 },
  { id: '2', name: 'Omega-3', price: 24.99 },
  { id: '3', name: 'Proteína Whey', price: 45.99 },
  { id: '4', name: 'Magnesio', price: 18.99 },
];
The product list is currently static for demonstration. In production, this would fetch real products via GraphQL.

Account Pages

Login Form

Location: src/pages/account/Login.tsx
export default function LoginForm() {
  return (
    <div className="max-w-md mx-auto px-4 py-8">
      <div className="bg-white border border-[#E8F5E9] rounded-lg p-8">
        <h1 className="text-2xl font-bold text-[#2D5A3D] text-center mb-6">
          Iniciar Sesión
        </h1>
        
        <form method="POST" action="/customer/login" className="space-y-4">
          <div>
            <label htmlFor="email" className="block text-sm font-medium text-[#4A5568] mb-1">
              Correo Electrónico
            </label>
            <input
              type="email"
              id="email"
              name="email"
              required
              className="w-full px-4 py-2 border border-[#E8F5E9] rounded-lg focus:outline-none focus:border-[#2D5A3D]"
              placeholder="tu@email.com"
            />
          </div>
          
          <div>
            <label htmlFor="password" className="block text-sm font-medium text-[#4A5568] mb-1">
              Contraseña
            </label>
            <input
              type="password"
              id="password"
              name="password"
              required
              className="w-full px-4 py-2 border border-[#E8F5E9] rounded-lg focus:outline-none focus:border-[#2D5A3D]"
              placeholder="••••••••"
            />
          </div>
          
          <button
            type="submit"
            className="w-full bg-[#2D5A3D] text-white py-3 rounded-lg hover:bg-[#1E3D2A] transition-colors font-medium"
          >
            Iniciar Sesión
          </button>
        </form>
        
        <div className="mt-6 text-center">
          <p className="text-[#4A5568]">
            ¿No tienes cuenta?{' '}
            <a href="/register" className="text-[#2D5A3D] hover:text-[#1E3D2A] font-medium">
              Regístrate aquí
            </a>
          </p>
        </div>
      </div>
    </div>
  );
}
Features:
  • Email and password fields
  • “Remember me” checkbox
  • Forgot password link
  • Link to registration page

Registration Form

Location: src/pages/account/Register.tsx Form Fields:
  • First name and last name (side by side)
  • Email address
  • Password (minimum 8 characters)
  • Password confirmation
  • Newsletter opt-in checkbox
  • Terms & conditions acceptance (required)
<div className="grid grid-cols-2 gap-4">
  <div>
    <label htmlFor="firstName" className="block text-sm font-medium text-[#4A5568] mb-1">
      Nombre
    </label>
    <input
      type="text"
      id="firstName"
      name="firstName"
      required
      className="w-full px-4 py-2 border border-[#E8F5E9] rounded-lg focus:outline-none focus:border-[#2D5A3D]"
    />
  </div>
  <div>
    <label htmlFor="lastName" className="block text-sm font-medium text-[#4A5568] mb-1">
      Apellido
    </label>
    <input
      type="text"
      id="lastName"
      name="lastName"
      required
      className="w-full px-4 py-2 border border-[#E8F5E9] rounded-lg focus:outline-none focus:border-[#2D5A3D]"
    />
  </div>
</div>

Account Dashboard

Location: src/pages/account/Dashboard.tsx The dashboard displays user information and recent orders using GraphQL data.
type AccountDashboardProps = {
  customer: {
    firstName?: string;
    lastName?: string;
    email?: string;
  };
  orders?: {
    orderId: string;
    createdAt: string;
    total: number;
    status: string;
  }[];
};

export default function AccountDashboard({ customer, orders = [] }: AccountDashboardProps) {
  const firstName = customer?.firstName || 'Cliente';
  
  return (
    <div className="max-w-6xl mx-auto px-4 py-8">
      <h1 className="text-3xl font-bold text-[#2D5A3D] mb-2">
        Bienvenido, {firstName}
      </h1>
      {/* Dashboard content */}
    </div>
  );
}
GraphQL Query:
export const query = `
  query Query {
    customer {
      firstName
      lastName
      email
    }
    orders(limit: 5) {
      orderId
      createdAt
      total
      status
    }
  }
`;
Dashboard Sections:
  1. Quick Actions (3-column grid)
    • Mis Pedidos - View all orders
    • Mis Direcciones - Manage shipping addresses
    • Mi Perfil - Update account information
  2. Recent Orders
    • Last 3 orders displayed
    • Order number, date, total, and status
    • Status badges (delivered, processing, pending)
    • Link to view all orders
Order status is displayed with color-coded badges for visual clarity:
  • Green for “Entregado” (delivered)
  • Yellow for “Procesando” (processing)
  • Gray for “Pendiente” (pending)

Styling Patterns

Buttons

The theme uses two button styles:
{/* Primary Button */}
<button className="bg-[#2D5A3D] text-white px-8 py-3 rounded-lg hover:bg-[#1E3D2A] transition-colors font-semibold">
  Primary Action
</button>

{/* Secondary Button */}
<button className="border-2 border-[#2D5A3D] text-[#2D5A3D] px-8 py-3 rounded-lg hover:bg-[#2D5A3D] hover:text-white transition-colors font-semibold">
  Secondary Action
</button>

Cards

<div className="bg-white border border-[#E8F5E9] rounded-lg p-6 hover:shadow-md transition-shadow">
  {/* Card content */}
</div>

Form Inputs

<input 
  className="w-full px-4 py-2 border border-[#E8F5E9] rounded-lg focus:outline-none focus:border-[#2D5A3D]"
  type="text"
/>

Responsive Grids

{/* 1 column on mobile, 2 on tablet, 4 on desktop */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
  {/* Grid items */}
</div>

Configuration

Activate Theme

In config/default.json:
{
  "system": {
    "theme": "anasuplements"
  }
}

Language Support

All text content is in Spanish:
{
  "shop": {
    "language": "es",
    "currency": "USD"
  }
}

Development

Build Theme

npm run build
This compiles TypeScript files from src/ to dist/.

Development Mode

npm run dev
Enables hot-reload for rapid iteration.

File Locations

Component TypePath PatternExample
Global componentssrc/pages/all/Header.tsx, Footer.tsx
Homepage sectionssrc/pages/homepage/Hero.tsx, Features.tsx
Account pagessrc/pages/account/Login.tsx, Dashboard.tsx
Product pagessrc/pages/catalog/ProductList.tsx

Customization Guide

Change Brand Colors

Replace hex codes throughout the theme:
// Old
<div className="bg-[#2D5A3D]">

// New
<div className="bg-[#YOUR_COLOR]">

Add New Homepage Section

  1. Create component file:
    themes/anasuplements/src/pages/homepage/Testimonials.tsx
    
  2. Implement component:
    export default function Testimonials() {
      return <section>{/* Content */}</section>;
    }
    
    export const layout = {
      areaId: 'content',
      sortOrder: 15  // After FeaturedProducts (10)
    };
    
  3. Rebuild theme:
    npm run build
    

Modify Header Navigation

Pass categories data to the Header component via props or GraphQL query.

Best Practice

Keep theme components purely presentational. Fetch data using GraphQL queries and pass it as props.

Next Steps

Theme Overview

Learn theme fundamentals

Tailwind Styling

Master utility-first CSS

GraphQL Queries

Fetch data in components

Extensions

Add business logic