Zum Hauptinhalt springen

Template Structure

Das heycreo Template-Format ist ein JSON-basiertes Format zur Definition von wiederverwendbaren Design-Templates.

Übersicht

Ein Template besteht aus:

  • Metadata (Name, Kategorie, Thumbnail)
  • Sizes (verschiedene Ausgabeformate wie Instagram Post, Twitter Header, etc.)
  • Elements (Text, Bilder, Shapes, Container)
  • Controls (Benutzer-Eingabefelder zur Anpassung)
  • Layer Groups (Variationen/Varianten)

Template JSON Schema

interface Template {
id: string; // UUID
name: string; // Template-Name
category: string; // Kategorie (z.B. "default")
thumbnail?: string; // Thumbnail-URL
description?: string; // Beschreibung

// Ausgabeformate
sizes: TemplateSize[]; // Array von Template-Größen

// Benutzer-Eingabefelder
controls?: Control[]; // Controls für Template-Anpassung

// Video/Audio
type?: 'image' | 'video'; // Template-Typ
duration?: number; // Dauer in Millisekunden (für Videos)
supportsVideo?: boolean; // Video-Modus aktiviert?
audioTrackId?: string; // Audio-Track ID
withVoiceOver?: boolean; // Voice-Over aktiviert?
voiceOverStartsAt?: number; // Voice-Over Start-Zeit

// Farben (Paletten-Theming ist immer aktiv)
defaultColorPaletteId?: string; // Standard Color-Palette

// Layer Groups (Variationen)
layerGroups?: LayerGroup[]; // Globale Layer-Gruppen

// Exklusive Control-Gruppen
exclusiveControlGroups?: ExclusiveGroup[];

// Editor-Einstellungen
rulerUnit?: 'px' | 'mm' | 'cm' | 'in';
showRulers?: boolean;
guideColor?: string;
}

Template Size

Ein Template kann mehrere Größen haben (z.B. Instagram Post + Twitter Header):

interface TemplateSize {
id: string; // Format-ID (z.B. "instagram-post")
width: number; // Breite in Pixeln
height: number; // Höhe in Pixeln
isDefault?: boolean; // Standard-Größe?

// Elemente für diese Größe
elements: TemplateElement[]; // Array von Elementen

// Layer Groups (größen-spezifisch)
layerGroups?: LayerGroup[];

// Guides (Hilfslinien)
guides?: {
vertical: number[]; // Vertikale Guides (X-Positionen)
horizontal: number[]; // Horizontale Guides (Y-Positionen)
};
}

Element Types

Text Element

{
id: string; // UUID
type: "text";
content: string; // Standard-Text
text?: string; // Aktueller Text (nach Control-Processing)
name: string; // Element-Name (z.B. "headline")
displayName?: string; // Anzeige-Name

// Position & Größe
x: number; // X-Position (links)
y: number; // Y-Position (oben)
width: number; // Breite
height: number; // Höhe
rotation?: number; // Rotation in Grad

// Control-Verknüpfungen
valueControlId?: string; // Control-ID für Text-Inhalt
visibilityControlId?: string; // Control-ID für Sichtbarkeit
visibilityControlValue?: boolean; // Sichtbar wenn Control = true/false

// Container-Properties
parentContainerId?: string; // Parent-Container ID
childLayout?: ChildLayout; // Margin/Padding als Child

// Layer Group
layerGroupId?: string; // Layer-Gruppe (für Variationen)

// Style
style: {
fontSize: number; // Schriftgröße
fontFamily: string; // Schriftart
fontWeight: string | number; // Schriftgewicht ("400", "700", etc.)
fontStyle?: "normal" | "italic";
color: string; // Textfarbe (Hex oder "token:primary")
textAlign?: "left" | "center" | "right";
lineHeight?: number; // Zeilenhöhe (z.B. 1.2)
maxLines?: number | null; // Max. Zeilen (für Auto-Resize)
autoResize?: boolean; // Auto-Resize aktiviert (default: true)

// Text-Effekte
textShadow?: {
enabled: boolean;
offsetX: number;
offsetY: number;
blur: number;
color: string;
};
textDecoration?: "none" | "underline";
};
}

Image Element

{
id: string;
type: "image";
content: string; // Bild-URL
videoContent?: string; // Video-URL (wenn supportsVideo: true)
name: string;

// Position & Größe
x: number;
y: number;
width: number;
height: number;
rotation?: number;

// Control-Verknüpfungen
valueControlId?: string; // Control-ID für Bild-Auswahl
visibilityControlId?: string;

// Video-Support
supportsVideo?: boolean; // Kann als Video gerendert werden?

// Style
style: {
borderRadius?: number; // Abgerundete Ecken
opacity?: number; // Transparenz (0-1)
objectFit?: "cover" | "contain" | "fill";

// SVG-spezifisch
fillColor?: string;
enableFill?: boolean;
};
}

Shape Element

{
id: string;
type: "shape";
content: "square" | "circle" | "rectangle" | "arrow";
name: string;

// Position & Größe
x: number;
y: number;
width: number;
height: number;
rotation?: number;

// Container-Properties
isVerticalStackContainer?: boolean; // Ist Container?
containerLayout?: ContainerLayout; // Container-Layout

// Style
style: {
backgroundColor: string; // Hintergrundfarbe
borderRadius?: number; // Abgerundete Ecken
borderColor?: string; // Rahmenfarbe
borderWidth?: number; // Rahmenbreite
opacity?: number;

// Gradient
gradient?: {
enabled: boolean;
type: "linear" | "radial";
angle?: number; // Für linear (0-360°)
stops: Array<{
color: string;
position: number; // 0-100%
}>;
};

// Schatten
dropShadow?: {
enabled: boolean;
offsetX: number;
offsetY: number;
blur: number;
color: string;
};
};
}

Video Element

{
id: string;
type: "video";
content: string; // Video-URL
name: string;

// Position & Größe
x: number;
y: number;
width: number;
height: number;

// Style
style: {
borderRadius?: number;
opacity?: number;
};
}

Controls

Controls sind Benutzer-Eingabefelder, die Elemente dynamisch anpassen:

interface Control {
id: string; // UUID (muss mit valueControlId übereinstimmen!)
label: string; // Anzeige-Name
type: ControlType; // Control-Typ
displayOrder: number; // Reihenfolge in UI

// Control-spezifisch
defaultValue?: string; // Standard-Wert
aiHint?: string; // AI-Hinweis
aiGenerated?: boolean; // Soll AI Werte vorschlagen?
maxCharacters?: number; // Max. Zeichen (für Text)
options?: string[]; // Optionen (für Select)
aspectRatio?: string; // Seitenverhältnis (für Image)
textTransform?: "uppercase" | "lowercase" | "none";
supportsFormatableText?: boolean; // BBCode-Formatierung?

// Exklusive Gruppen
exclusiveGroupIds?: string[]; // IDs von ExclusiveGroups
}

Control Types

TypeBeschreibungBeispiel
text_inputEinzeilige Text-Eingabe"Hauptüberschrift"
textareaMehrzeilige Text-Eingabe"Beschreibung"
checkboxBoolean Toggle"Logo anzeigen"
selectDropdown-Auswahl"Button-Stil"
imageBild-Upload"Hauptbild"
image_videoBild oder Video"Hintergrund"
colorFarbauswahl"Akzentfarbe"

Control-Beispiel

{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"label": "Hauptüberschrift",
"type": "textarea",
"displayOrder": 0,
"defaultValue": "Deine Überschrift",
"aiHint": "Eine einprägsame Überschrift",
"aiGenerated": true,
"maxCharacters": 100,
"supportsFormatableText": true,
"textTransform": "uppercase"
}

Element-Control Verknüpfung

Value Control (Text-Inhalt ändern)

{
"control": {
"id": "headline-control-id",
"label": "Überschrift",
"type": "textarea"
},
"element": {
"type": "text",
"valueControlId": "headline-control-id" // ← Muss exakt übereinstimmen!
}
}

Visibility Control (Element ein/ausblenden)

{
"control": {
"id": "logo-visibility-id",
"label": "Logo anzeigen",
"type": "checkbox",
"defaultValue": "true"
},
"element": {
"type": "image",
"visibilityControlId": "logo-visibility-id",
"visibilityControlValue": true // Sichtbar wenn Control = true
}
}

Container Layout

Vertical Stack Container

Ein Container mit isVerticalStackContainer: true ordnet Kinder automatisch vertikal an:

{
type: "shape",
isVerticalStackContainer: true,
containerLayout: {
paddingLeft: 10,
paddingRight: 10,
paddingTop: 10,
paddingBottom: 10,
growDirection: "bottom" // oder "top"
}
}

Child Layout

Kinder eines Containers haben childLayout:

{
parentContainerId: "container-id",
childLayout: {
marginTop: 0,
marginBottom: 10,
marginLeft: 0,
marginRight: 0
}
}

Siehe Layout Engine für Details.

Layer Groups

Layer Groups ermöglichen Variationen (z.B. "Variante 1" vs "Variante 2"):

interface LayerGroup {
id: string; // UUID
name: string; // z.B. "Variante 1"
displayOrder: number; // Reihenfolge
}

Elemente können einer Layer Group zugeordnet werden:

{
"element": {
"id": "cta-button",
"layerGroupId": "variant-1-id" // Nur in Variante 1 sichtbar
}
}

Color Tokens

Farben können als Tokens referenziert werden:

{
"style": {
"color": "token:primary", // Primärfarbe aus Color-Palette
"backgroundColor": "token:accent" // Akzentfarbe
}
}

Beispiel: Vollständiges Template

{
"id": "template-123",
"name": "Instagram Produktankündigung",
"category": "default",
"type": "image",
"sizes": [{
"id": "instagram-post",
"width": 1080,
"height": 1080,
"isDefault": true,
"elements": [
{
"id": "headline",
"type": "text",
"content": "NEUES PRODUKT",
"valueControlId": "headline-control",
"x": 100,
"y": 100,
"width": 880,
"height": 200,
"style": {
"fontSize": 72,
"fontFamily": "Source Sans Pro",
"fontWeight": "700",
"color": "token:primary",
"textAlign": "center"
}
},
{
"id": "product-image",
"type": "image",
"content": "https://example.com/product.jpg",
"valueControlId": "product-image-control",
"x": 100,
"y": 400,
"width": 880,
"height": 500,
"style": {
"borderRadius": 10
}
}
]
}],
"controls": [
{
"id": "headline-control",
"label": "Überschrift",
"type": "textarea",
"displayOrder": 0
},
{
"id": "product-image-control",
"label": "Produktbild",
"type": "image",
"displayOrder": 1
}
]
}

Siehe auch