Products
Products in Hoikka support variants, translations, and facets (attributes).
AI-friendly codebase: Try prompts like “Add a weight field to products” and the agent can trace the full path from schema to admin to storefront.
Variants
Each product has one or more variants:
// Product: "T-Shirt"
// Variants: "T-Shirt - Red / M", "T-Shirt - Blue / L"
const variant = {
sku: "TSHIRT-RED-M",
price: 2999, // cents
stock: 50,
facetValues: [redColor, mediumSize]
};Multi-Language Support
Default language (English) fields are stored directly on the products table. Non-default languages (e.g. Finnish) use the product_translations table, managed via TranslationService.
const product = await productService.getById(123);
// Default language fields — directly on the products table
product.name; // "Blue Shirt"
product.slug; // "blue-shirt"
product.description; // "<p>A nice shirt</p>"Translations are edited in the admin panel via language tabs on the main form (TranslationEditor.svelte, shared by all translated entities). See Localization for details.
Description HTML (default language and translations) is sanitized on save with src/lib/server/sanitize.ts, since it is rendered with {@html} on the storefront.
Facets (Attributes)
Facets define product attributes for filtering:
// Facet: "Color"
// Values: "Red", "Blue", "Green"
// Facet: "Size"
// Values: "S", "M", "L", "XL"Products and variants can have facet values assigned for:
- Filtering in collections
- Search refinement
- Variant selection
Search
Admin product lists use a simple LIKE match over name and description:
const results = await productService.list({ search: "shirt" });The storefront uses a SQLite FTS5 index instead — see Search & Categories.
Admin Operations
// Create product — default language fields go directly on the entity
await productService.create({
name: "Blue Shirt",
slug: "blue-shirt",
description: "..."
});
// Add a Finnish translation
import { translationService } from "$lib/server/services/translations";
await translationService.upsertProductTranslation(productId, "fi", {
name: "Sininen paita",
slug: "sininen-paita",
description: "..."
});
// Variant operations are handled through productService
// See src/lib/server/services/products.ts for variant management