Track all types in git, sync to server on deploy
Some checks failed
Deploy to Server / deploy (push) Failing after 7s
Some checks failed
Deploy to Server / deploy (push) Failing after 7s
This commit is contained in:
@@ -27,6 +27,9 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo "${{ secrets.SSH_DEPLOY_KEY }}" > /tmp/deploy_key
|
echo "${{ secrets.SSH_DEPLOY_KEY }}" > /tmp/deploy_key
|
||||||
chmod 600 /tmp/deploy_key
|
chmod 600 /tmp/deploy_key
|
||||||
|
rsync -avz --delete \
|
||||||
|
-e "ssh -o StrictHostKeyChecking=no -i /tmp/deploy_key" \
|
||||||
|
./types/ root@167.86.74.105:/opt/rustycms/types/
|
||||||
ssh -o StrictHostKeyChecking=no -i /tmp/deploy_key root@167.86.74.105 \
|
ssh -o StrictHostKeyChecking=no -i /tmp/deploy_key root@167.86.74.105 \
|
||||||
"docker compose -f /opt/rustycms/docker-compose.yml up -d && docker image prune -f"
|
"docker compose -f /opt/rustycms/docker-compose.yml up -d && docker image prune -f"
|
||||||
rm /tmp/deploy_key
|
rm /tmp/deploy_key
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -19,10 +19,7 @@ content/de/page/*
|
|||||||
content/assets/*
|
content/assets/*
|
||||||
!content/assets/mountains-w300.webp
|
!content/assets/mountains-w300.webp
|
||||||
|
|
||||||
# Types: ignore all except demo types (demo + page for demo references)
|
# Types are tracked in git and deployed to server via CI/CD
|
||||||
types/*
|
|
||||||
!types/demo.json5
|
|
||||||
!types/page.json5
|
|
||||||
|
|
||||||
.history
|
.history
|
||||||
.cursor
|
.cursor
|
||||||
|
|||||||
60
types/blog_post.json5
Normal file
60
types/blog_post.json5
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"name": "blog_post",
|
||||||
|
"description": "Simple blog post with title, body, tags and publish status",
|
||||||
|
"tags": [
|
||||||
|
"content",
|
||||||
|
"blog"
|
||||||
|
],
|
||||||
|
"category": "content",
|
||||||
|
"fieldOrder": [
|
||||||
|
"author",
|
||||||
|
"body",
|
||||||
|
"created_at",
|
||||||
|
"excerpt",
|
||||||
|
"published",
|
||||||
|
"tags",
|
||||||
|
"title"
|
||||||
|
],
|
||||||
|
"fields": {
|
||||||
|
"author": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Author name"
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"type": "markdown",
|
||||||
|
"required": true,
|
||||||
|
"description": "Main content (Markdown)",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"type": "datetime",
|
||||||
|
"auto": true,
|
||||||
|
"readonly": true,
|
||||||
|
"description": "Creation timestamp (auto-generated)"
|
||||||
|
},
|
||||||
|
"excerpt": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Short summary for previews",
|
||||||
|
"maxLength": 500
|
||||||
|
},
|
||||||
|
"published": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "Whether the post is publicly visible"
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "Categorisation tags"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true,
|
||||||
|
"description": "Title of the blog post",
|
||||||
|
"minLength": 1,
|
||||||
|
"maxLength": 200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
types/calendar.json5
Normal file
23
types/calendar.json5
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
name: "calendar",
|
||||||
|
description: "Calendar (entries identified by slug).",
|
||||||
|
tags: [
|
||||||
|
"content"
|
||||||
|
],
|
||||||
|
category: "content",
|
||||||
|
fields: {
|
||||||
|
items: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "reference",
|
||||||
|
collection: "calendar_item",
|
||||||
|
},
|
||||||
|
description: "Calendar entries (references to calendar_item)",
|
||||||
|
},
|
||||||
|
fromPost: {
|
||||||
|
type: "boolean",
|
||||||
|
default: false,
|
||||||
|
description: "Include entries from post",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
33
types/calendar_item.json5
Normal file
33
types/calendar_item.json5
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
name: "calendar_item",
|
||||||
|
description: "Single calendar entry (event) with title, description and time.",
|
||||||
|
tags: [
|
||||||
|
"content"
|
||||||
|
],
|
||||||
|
category: "content",
|
||||||
|
fields: {
|
||||||
|
title: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Event title",
|
||||||
|
section: "Event",
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: "string",
|
||||||
|
description: "Event description",
|
||||||
|
section: "Event",
|
||||||
|
},
|
||||||
|
terminZeit: {
|
||||||
|
type: "datetime",
|
||||||
|
required: true,
|
||||||
|
description: "Event date/time",
|
||||||
|
section: "Date & link",
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
type: "reference",
|
||||||
|
collection: "link",
|
||||||
|
description: "Optional link (e.g. registration or details page)",
|
||||||
|
section: "Date & link",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
62
types/campaign.json5
Normal file
62
types/campaign.json5
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"name": "campaign",
|
||||||
|
"description": "Campaign with URL pattern and optional content",
|
||||||
|
"tags": [
|
||||||
|
"marketing",
|
||||||
|
"config"
|
||||||
|
],
|
||||||
|
"category": "config",
|
||||||
|
"fields": {
|
||||||
|
"css": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Optional CSS",
|
||||||
|
"widget": "code",
|
||||||
|
"codeLanguage": "css"
|
||||||
|
},
|
||||||
|
"html": {
|
||||||
|
"type": "html",
|
||||||
|
"description": "HTML content"
|
||||||
|
},
|
||||||
|
"insertHtml": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true,
|
||||||
|
"default": "beforeend",
|
||||||
|
"enum": [
|
||||||
|
"afterbegin",
|
||||||
|
"beforeend",
|
||||||
|
"afterend",
|
||||||
|
"beforebegin",
|
||||||
|
"replace"
|
||||||
|
],
|
||||||
|
"description": "Position relative to selector"
|
||||||
|
},
|
||||||
|
"javascript": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Optional JavaScript",
|
||||||
|
"widget": "code",
|
||||||
|
"codeLanguage": "javascript"
|
||||||
|
},
|
||||||
|
"medias": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "reference",
|
||||||
|
"collection": "img"
|
||||||
|
},
|
||||||
|
"description": "Media (images)"
|
||||||
|
},
|
||||||
|
"selector": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true,
|
||||||
|
"description": "CSS selector where content is inserted"
|
||||||
|
},
|
||||||
|
"timeUntil": {
|
||||||
|
"type": "datetime",
|
||||||
|
"description": "Time limit (until when the campaign runs)"
|
||||||
|
},
|
||||||
|
"urlPattern": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true,
|
||||||
|
"description": "URL pattern (e.g. regex) for campaign usage"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
types/campaigns.json5
Normal file
27
types/campaigns.json5
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_Campaigns / Contentful_Campaigns.ts
|
||||||
|
name: "campaigns",
|
||||||
|
description: "Global campaign list and enable flag",
|
||||||
|
tags: ["marketing", "config"],
|
||||||
|
category: "config",
|
||||||
|
fields: {
|
||||||
|
id: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Unique ID (e.g. campaigns-global)",
|
||||||
|
},
|
||||||
|
campaigns: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "reference",
|
||||||
|
collection: "campaign",
|
||||||
|
},
|
||||||
|
description: "Campaign list",
|
||||||
|
},
|
||||||
|
enable: {
|
||||||
|
type: "boolean",
|
||||||
|
default: true,
|
||||||
|
description: "Campaigns enabled",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
86
types/component_layout.json5
Normal file
86
types/component_layout.json5
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
{
|
||||||
|
// Reusable partial (CF_ComponentLayout) – no own collection.
|
||||||
|
name: "component_layout",
|
||||||
|
description: "Reusable grid layout (mobile/tablet/desktop columns)",
|
||||||
|
tags: [
|
||||||
|
"layout",
|
||||||
|
"partial"
|
||||||
|
],
|
||||||
|
category: "layout",
|
||||||
|
reusable: true,
|
||||||
|
fields: {
|
||||||
|
breakout: {
|
||||||
|
type: "boolean",
|
||||||
|
default: false,
|
||||||
|
description: "Breakout layout (full width)",
|
||||||
|
},
|
||||||
|
mobile: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
enum: [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
"5",
|
||||||
|
"6",
|
||||||
|
"7",
|
||||||
|
"8",
|
||||||
|
"9",
|
||||||
|
"10",
|
||||||
|
"11",
|
||||||
|
"12"
|
||||||
|
],
|
||||||
|
default: "12",
|
||||||
|
description: "Width on mobile (1–12)",
|
||||||
|
},
|
||||||
|
tablet: {
|
||||||
|
type: "string",
|
||||||
|
enum: [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
"5",
|
||||||
|
"6",
|
||||||
|
"7",
|
||||||
|
"8",
|
||||||
|
"9",
|
||||||
|
"10",
|
||||||
|
"11",
|
||||||
|
"12"
|
||||||
|
],
|
||||||
|
description: "Width on tablet (optional)",
|
||||||
|
},
|
||||||
|
desktop: {
|
||||||
|
type: "string",
|
||||||
|
enum: [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
"5",
|
||||||
|
"6",
|
||||||
|
"7",
|
||||||
|
"8",
|
||||||
|
"9",
|
||||||
|
"10",
|
||||||
|
"11",
|
||||||
|
"12"
|
||||||
|
],
|
||||||
|
description: "Width on desktop (optional)",
|
||||||
|
},
|
||||||
|
spaceBottom: {
|
||||||
|
type: "number",
|
||||||
|
enum: [
|
||||||
|
0,
|
||||||
|
0.5,
|
||||||
|
1,
|
||||||
|
1.5,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
default: 0,
|
||||||
|
description: "Space below (rem)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
150
types/content_layout.json5
Normal file
150
types/content_layout.json5
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
{
|
||||||
|
// Equivalent to: CF_Content interface
|
||||||
|
// Base type for pages/posts with a 3-row content layout
|
||||||
|
name: "content_layout",
|
||||||
|
description: "Base layout with 3 content rows (inherited by page, post, etc.)",
|
||||||
|
tags: ["layout", "partial"],
|
||||||
|
category: "layout",
|
||||||
|
fields: {
|
||||||
|
row1JustifyContent: {
|
||||||
|
type: "string",
|
||||||
|
enum: [
|
||||||
|
"start",
|
||||||
|
"end",
|
||||||
|
"center",
|
||||||
|
"between",
|
||||||
|
"around",
|
||||||
|
"evenly"
|
||||||
|
],
|
||||||
|
default: "start",
|
||||||
|
description: "Justify content for row 1",
|
||||||
|
},
|
||||||
|
row1AlignItems: {
|
||||||
|
type: "string",
|
||||||
|
enum: [
|
||||||
|
"start",
|
||||||
|
"end",
|
||||||
|
"center",
|
||||||
|
"baseline",
|
||||||
|
"stretch"
|
||||||
|
],
|
||||||
|
default: "stretch",
|
||||||
|
description: "Align items for row 1",
|
||||||
|
},
|
||||||
|
row1Content: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "reference",
|
||||||
|
collections: [
|
||||||
|
"markdown",
|
||||||
|
"post_overview",
|
||||||
|
"html",
|
||||||
|
"headline",
|
||||||
|
"image",
|
||||||
|
"quote",
|
||||||
|
"youtube_video",
|
||||||
|
"image_gallery",
|
||||||
|
"iframe",
|
||||||
|
"searchable_text",
|
||||||
|
"fullwidth_banner",
|
||||||
|
"list",
|
||||||
|
"link_list",
|
||||||
|
"calendar"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
description: "Content components for row 1 (Markdown, Post Overview, HTML, Headline, Image, …)",
|
||||||
|
},
|
||||||
|
row2JustifyContent: {
|
||||||
|
type: "string",
|
||||||
|
enum: [
|
||||||
|
"start",
|
||||||
|
"end",
|
||||||
|
"center",
|
||||||
|
"between",
|
||||||
|
"around",
|
||||||
|
"evenly"
|
||||||
|
],
|
||||||
|
default: "start",
|
||||||
|
},
|
||||||
|
row2AlignItems: {
|
||||||
|
type: "string",
|
||||||
|
enum: [
|
||||||
|
"start",
|
||||||
|
"end",
|
||||||
|
"center",
|
||||||
|
"baseline",
|
||||||
|
"stretch"
|
||||||
|
],
|
||||||
|
default: "stretch",
|
||||||
|
},
|
||||||
|
row2Content: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "reference",
|
||||||
|
collections: [
|
||||||
|
"markdown",
|
||||||
|
"post_overview",
|
||||||
|
"html",
|
||||||
|
"headline",
|
||||||
|
"image",
|
||||||
|
"quote",
|
||||||
|
"youtube_video",
|
||||||
|
"image_gallery",
|
||||||
|
"iframe",
|
||||||
|
"searchable_text",
|
||||||
|
"fullwidth_banner",
|
||||||
|
"list",
|
||||||
|
"link_list",
|
||||||
|
"calendar"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
description: "Content components for row 2",
|
||||||
|
},
|
||||||
|
row3JustifyContent: {
|
||||||
|
type: "string",
|
||||||
|
enum: [
|
||||||
|
"start",
|
||||||
|
"end",
|
||||||
|
"center",
|
||||||
|
"between",
|
||||||
|
"around",
|
||||||
|
"evenly"
|
||||||
|
],
|
||||||
|
default: "start",
|
||||||
|
},
|
||||||
|
row3AlignItems: {
|
||||||
|
type: "string",
|
||||||
|
enum: [
|
||||||
|
"start",
|
||||||
|
"end",
|
||||||
|
"center",
|
||||||
|
"baseline",
|
||||||
|
"stretch"
|
||||||
|
],
|
||||||
|
default: "stretch",
|
||||||
|
},
|
||||||
|
row3Content: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "reference",
|
||||||
|
collections: [
|
||||||
|
"markdown",
|
||||||
|
"post_overview",
|
||||||
|
"html",
|
||||||
|
"headline",
|
||||||
|
"image",
|
||||||
|
"quote",
|
||||||
|
"youtube_video",
|
||||||
|
"image_gallery",
|
||||||
|
"iframe",
|
||||||
|
"searchable_text",
|
||||||
|
"fullwidth_banner",
|
||||||
|
"list",
|
||||||
|
"link_list",
|
||||||
|
"calendar"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
description: "Content components for row 3",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
17
types/footer.json5
Normal file
17
types/footer.json5
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_Footer extends CF_Content / Contentful_Footer.ts
|
||||||
|
name: "footer",
|
||||||
|
description: "Footer with content layout",
|
||||||
|
tags: ["layout", "config"],
|
||||||
|
category: "config",
|
||||||
|
extends: [
|
||||||
|
"content_layout"
|
||||||
|
],
|
||||||
|
fields: {
|
||||||
|
id: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Unique footer ID (e.g. for navigation)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
43
types/fullwidth_banner.json5
Normal file
43
types/fullwidth_banner.json5
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
// Equivalent to: CF_FullwidthBanner interface
|
||||||
|
name: "fullwidth_banner",
|
||||||
|
description: "Full-width banner with dark/light variant",
|
||||||
|
tags: [
|
||||||
|
"component",
|
||||||
|
"layout"
|
||||||
|
],
|
||||||
|
category: "components",
|
||||||
|
fields: {
|
||||||
|
name: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Internal name"
|
||||||
|
},
|
||||||
|
variant: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
enum: [
|
||||||
|
"dark",
|
||||||
|
"light"
|
||||||
|
],
|
||||||
|
default: "light",
|
||||||
|
description: "Color variant"
|
||||||
|
},
|
||||||
|
headline: {
|
||||||
|
type: "string",
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
subheadline: {
|
||||||
|
type: "string"
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
type: "richtext",
|
||||||
|
description: "Banner body text"
|
||||||
|
},
|
||||||
|
image: {
|
||||||
|
type: "referenceOrInline",
|
||||||
|
collection: "img",
|
||||||
|
description: "Banner image"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
37
types/headline.json5
Normal file
37
types/headline.json5
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_ComponentHeadline / Contentful_Headline.ts
|
||||||
|
name: "headline",
|
||||||
|
description: "Headline component with optional layout",
|
||||||
|
tags: ["component", "layout"],
|
||||||
|
category: "components",
|
||||||
|
fields: {
|
||||||
|
internal: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Internal key",
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Headline text",
|
||||||
|
},
|
||||||
|
tag: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
enum: ["h1", "h2", "h3", "h4", "h5", "h6"],
|
||||||
|
default: "h2",
|
||||||
|
description: "HTML tag for headline",
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
type: "object",
|
||||||
|
useFields: "component_layout",
|
||||||
|
description: "Column width (grid) like CF_ComponentLayout",
|
||||||
|
},
|
||||||
|
align: {
|
||||||
|
type: "string",
|
||||||
|
enum: ["left", "center", "right"],
|
||||||
|
default: "left",
|
||||||
|
description: "Text alignment",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
24
types/html.json5
Normal file
24
types/html.json5
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_HTML / Contentful_Html.ts
|
||||||
|
name: "html",
|
||||||
|
description: "Raw HTML content block with optional layout",
|
||||||
|
tags: ["content", "component"],
|
||||||
|
category: "components",
|
||||||
|
fields: {
|
||||||
|
id: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Unique component ID",
|
||||||
|
},
|
||||||
|
html: {
|
||||||
|
type: "html",
|
||||||
|
required: true,
|
||||||
|
description: "HTML content (safely embedded)",
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
type: "object",
|
||||||
|
useFields: "component_layout",
|
||||||
|
description: "Column width (grid) like CF_ComponentLayout",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
34
types/iframe.json5
Normal file
34
types/iframe.json5
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_ComponentIframe / Contentful_Iframe.ts
|
||||||
|
name: "iframe",
|
||||||
|
description: "Embedded iframe with URL and optional title",
|
||||||
|
tags: ["media", "component"],
|
||||||
|
category: "components",
|
||||||
|
fields: {
|
||||||
|
name: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Internal component name",
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Description/content for iframe",
|
||||||
|
},
|
||||||
|
iframe: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Iframe URL or embed code",
|
||||||
|
},
|
||||||
|
overlayImage: {
|
||||||
|
type: "reference",
|
||||||
|
collection: "img",
|
||||||
|
description: "Optional overlay image (reference to img)",
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
type: "object",
|
||||||
|
useFields: "component_layout",
|
||||||
|
description: "Column width (grid) like CF_ComponentLayout",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
38
types/image.json5
Normal file
38
types/image.json5
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
name: "image",
|
||||||
|
description: "Image component with inline img (src + description) and layout",
|
||||||
|
tags: ["component", "media"],
|
||||||
|
category: "components",
|
||||||
|
fields: {
|
||||||
|
name: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Internal component name",
|
||||||
|
},
|
||||||
|
img: {
|
||||||
|
type: "referenceOrInline",
|
||||||
|
collection: "img",
|
||||||
|
required: true,
|
||||||
|
description: "Image: Slug (Referenz) oder Inline-Objekt (gleiche Felder wie img)",
|
||||||
|
},
|
||||||
|
caption: {
|
||||||
|
type: "string",
|
||||||
|
description: "Image caption",
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
type: "object",
|
||||||
|
useFields: "component_layout",
|
||||||
|
description: "Column width (grid)",
|
||||||
|
},
|
||||||
|
maxWidth: {
|
||||||
|
type: "integer",
|
||||||
|
description: "Max width in px",
|
||||||
|
},
|
||||||
|
aspectRatio: {
|
||||||
|
type: "string",
|
||||||
|
description: "Aspect ratio",
|
||||||
|
enum: ["1:1", "4:3", "3:2", "16:9", "21:9", "2:3", "3:4"],
|
||||||
|
default: "4:3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
35
types/image_gallery.json5
Normal file
35
types/image_gallery.json5
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_ImageGallery / Contentful_ImageGallery.ts
|
||||||
|
name: "image_gallery",
|
||||||
|
description: "Gallery of image references",
|
||||||
|
tags: [
|
||||||
|
"media",
|
||||||
|
"component"
|
||||||
|
],
|
||||||
|
category: "components",
|
||||||
|
fields: {
|
||||||
|
name: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Internal gallery name",
|
||||||
|
},
|
||||||
|
images: {
|
||||||
|
type: "array",
|
||||||
|
required: true,
|
||||||
|
items: {
|
||||||
|
type: "referenceOrInline",
|
||||||
|
collection: "img",
|
||||||
|
},
|
||||||
|
description: "Images (references to img)",
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
type: "object",
|
||||||
|
useFields: "component_layout",
|
||||||
|
description: "Column width (grid) like CF_ComponentLayout",
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: "string",
|
||||||
|
description: "Optional gallery description",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
21
types/img.json5
Normal file
21
types/img.json5
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
name: "img",
|
||||||
|
description: "Image asset with URL and optional description (alt text)",
|
||||||
|
tags: [
|
||||||
|
"asset",
|
||||||
|
"media"
|
||||||
|
],
|
||||||
|
category: "components",
|
||||||
|
fields: {
|
||||||
|
description: {
|
||||||
|
type: "string",
|
||||||
|
description: "Alt text / description",
|
||||||
|
},
|
||||||
|
src: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Image URL",
|
||||||
|
widget: "imageUrl",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
75
types/link.json5
Normal file
75
types/link.json5
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_Link / Contentful_Link.ts
|
||||||
|
name: "link",
|
||||||
|
description: "Internal or external link with label and optional icon",
|
||||||
|
tags: ["navigation", "component"],
|
||||||
|
category: "components",
|
||||||
|
fields: {
|
||||||
|
name: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Internal link name",
|
||||||
|
},
|
||||||
|
internal: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Internal key",
|
||||||
|
},
|
||||||
|
linkName: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Display name (e.g. in navigation)",
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Target URL",
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
type: "string",
|
||||||
|
description: "Icon identifier",
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
type: "string",
|
||||||
|
description: "Color (e.g. for buttons)",
|
||||||
|
},
|
||||||
|
newTab: {
|
||||||
|
type: "boolean",
|
||||||
|
default: false,
|
||||||
|
description: "Open in new tab",
|
||||||
|
},
|
||||||
|
external: {
|
||||||
|
type: "boolean",
|
||||||
|
default: false,
|
||||||
|
description: "External link",
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: "string",
|
||||||
|
description: "Description",
|
||||||
|
},
|
||||||
|
alt: {
|
||||||
|
type: "string",
|
||||||
|
description: "Alt text (e.g. for icon)",
|
||||||
|
},
|
||||||
|
showText: {
|
||||||
|
type: "boolean",
|
||||||
|
default: true,
|
||||||
|
description: "Show text",
|
||||||
|
},
|
||||||
|
author: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Author (e.g. for sources)",
|
||||||
|
},
|
||||||
|
date: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Date (e.g. publication)",
|
||||||
|
},
|
||||||
|
source: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Source",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
23
types/link_list.json5
Normal file
23
types/link_list.json5
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_Link_List / Contentful_Link_List.ts (componentLinkList)
|
||||||
|
name: "link_list",
|
||||||
|
description: "List of links with optional headline",
|
||||||
|
tags: ["navigation", "component"],
|
||||||
|
category: "components",
|
||||||
|
fields: {
|
||||||
|
headline: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Link list headline",
|
||||||
|
},
|
||||||
|
links: {
|
||||||
|
type: "array",
|
||||||
|
required: true,
|
||||||
|
items: {
|
||||||
|
type: "reference",
|
||||||
|
collection: "link",
|
||||||
|
},
|
||||||
|
description: "Links (references to link)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
20
types/list.json5
Normal file
20
types/list.json5
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_ComponentList / Contentful_List.ts
|
||||||
|
name: "list",
|
||||||
|
description: "Simple list of string items",
|
||||||
|
tags: ["content", "component"],
|
||||||
|
category: "components",
|
||||||
|
fields: {
|
||||||
|
internal: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Internal key",
|
||||||
|
},
|
||||||
|
item: {
|
||||||
|
type: "array",
|
||||||
|
required: true,
|
||||||
|
items: { type: "string" },
|
||||||
|
description: "List entries",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
29
types/markdown.json5
Normal file
29
types/markdown.json5
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_Markdown / Contentful_Markdown.ts
|
||||||
|
name: "markdown",
|
||||||
|
description: "Markdown content block with optional layout",
|
||||||
|
tags: ["content", "component"],
|
||||||
|
category: "components",
|
||||||
|
fields: {
|
||||||
|
name: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Internal component name",
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
type: "textOrRef",
|
||||||
|
description: "Markdown/body text: either inline or file reference (file:path, e.g. file:slug.content.md)",
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
type: "object",
|
||||||
|
useFields: "component_layout",
|
||||||
|
description: "Column width (grid) like CF_ComponentLayout",
|
||||||
|
},
|
||||||
|
alignment: {
|
||||||
|
type: "string",
|
||||||
|
enum: ["left", "center", "right"],
|
||||||
|
default: "left",
|
||||||
|
description: "Text alignment",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
28
types/navigation.json5
Normal file
28
types/navigation.json5
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_Navigation / Contentful_Navigation.ts
|
||||||
|
name: "navigation",
|
||||||
|
description: "Navigation block with links (header/footer)",
|
||||||
|
tags: ["navigation", "layout"],
|
||||||
|
category: "config",
|
||||||
|
fields: {
|
||||||
|
name: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Display name of navigation",
|
||||||
|
},
|
||||||
|
internal: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Internal key (e.g. navigation-header, navigation-footer)",
|
||||||
|
},
|
||||||
|
links: {
|
||||||
|
type: "array",
|
||||||
|
required: true,
|
||||||
|
items: {
|
||||||
|
type: "reference",
|
||||||
|
collections: ["link", "page", "post"],
|
||||||
|
},
|
||||||
|
description: "Navigation entries (references to link, page or post)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
50
types/page_config.json5
Normal file
50
types/page_config.json5
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_PageConfig / Contentful_PageConfig.ts
|
||||||
|
name: "page_config",
|
||||||
|
description: "Global page config (logo, footer, etc.)",
|
||||||
|
tags: [
|
||||||
|
"config",
|
||||||
|
"layout"
|
||||||
|
],
|
||||||
|
category: "config",
|
||||||
|
fields: {
|
||||||
|
logo: {
|
||||||
|
type: "referenceOrInline",
|
||||||
|
collection: "img",
|
||||||
|
required: true,
|
||||||
|
description: "Logo image (reference to img)",
|
||||||
|
},
|
||||||
|
footerText1: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Footer text (e.g. copyright)",
|
||||||
|
},
|
||||||
|
seoTitle: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Default SEO title for website",
|
||||||
|
},
|
||||||
|
seoDescription: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Default meta description",
|
||||||
|
},
|
||||||
|
blogTagPageHeadline: {
|
||||||
|
type: "string",
|
||||||
|
description: "Headline for tag page (blog)",
|
||||||
|
},
|
||||||
|
blogPostsPageHeadline: {
|
||||||
|
type: "string",
|
||||||
|
description: "Headline for blog overview page",
|
||||||
|
},
|
||||||
|
blogPostsPageSubHeadline: {
|
||||||
|
type: "string",
|
||||||
|
description: "Subheadline for blog overview page",
|
||||||
|
},
|
||||||
|
website: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Website-URL",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
94
types/post.json5
Normal file
94
types/post.json5
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
{
|
||||||
|
"name": "post",
|
||||||
|
"description": "Blog post with layout, SEO and optional tags",
|
||||||
|
"tags": [
|
||||||
|
"content",
|
||||||
|
"blog"
|
||||||
|
],
|
||||||
|
"category": "content",
|
||||||
|
"extends": [
|
||||||
|
"content_layout",
|
||||||
|
"seo"
|
||||||
|
],
|
||||||
|
"defaultSort": "_updated",
|
||||||
|
"defaultOrder": "desc",
|
||||||
|
"fieldOrder": [
|
||||||
|
"slug",
|
||||||
|
"headline",
|
||||||
|
"subheadline",
|
||||||
|
"excerpt",
|
||||||
|
"content",
|
||||||
|
"postImage",
|
||||||
|
"postTag",
|
||||||
|
"created",
|
||||||
|
"date",
|
||||||
|
"icon",
|
||||||
|
"important",
|
||||||
|
"linkName",
|
||||||
|
"showCommentSection"
|
||||||
|
],
|
||||||
|
"fields": {
|
||||||
|
"slug": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true,
|
||||||
|
"unique": true
|
||||||
|
},
|
||||||
|
"headline": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"subheadline": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"excerpt": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Short summary for previews",
|
||||||
|
"maxLength": 500
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"type": "markdown",
|
||||||
|
"required": true,
|
||||||
|
"description": "Post body (Markdown)"
|
||||||
|
},
|
||||||
|
"postImage": {
|
||||||
|
"type": "referenceOrInline",
|
||||||
|
"collection": "img",
|
||||||
|
"description": "Featured image"
|
||||||
|
},
|
||||||
|
"postTag": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "reference",
|
||||||
|
"collection": "tag"
|
||||||
|
},
|
||||||
|
"description": "Associated tags"
|
||||||
|
},
|
||||||
|
"created": {
|
||||||
|
"type": "datetime",
|
||||||
|
"auto": true,
|
||||||
|
"readonly": true
|
||||||
|
},
|
||||||
|
"date": {
|
||||||
|
"type": "datetime",
|
||||||
|
"description": "Optional display date"
|
||||||
|
},
|
||||||
|
"icon": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"important": {
|
||||||
|
"type": "boolean",
|
||||||
|
"required": true,
|
||||||
|
"default": false,
|
||||||
|
"description": "Mark post as important"
|
||||||
|
},
|
||||||
|
"linkName": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"showCommentSection": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Show comment section (default: true)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
62
types/post_overview.json5
Normal file
62
types/post_overview.json5
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_Post_Overview / Contentful_Post_Overview.ts (extends CF_Content, CF_SEO)
|
||||||
|
name: "post_overview",
|
||||||
|
description: "Post listing page with layout and SEO",
|
||||||
|
tags: ["content", "blog"],
|
||||||
|
category: "content",
|
||||||
|
extends: [
|
||||||
|
"content_layout",
|
||||||
|
"seo"
|
||||||
|
],
|
||||||
|
fields: {
|
||||||
|
id: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Unique post overview ID",
|
||||||
|
},
|
||||||
|
headline: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Headline",
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
type: "richtext",
|
||||||
|
description: "Intro text",
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
type: "object",
|
||||||
|
useFields: "component_layout",
|
||||||
|
description: "Column width (grid)",
|
||||||
|
},
|
||||||
|
allPosts: {
|
||||||
|
type: "boolean",
|
||||||
|
default: false,
|
||||||
|
description: "Show all posts (otherwise filter)",
|
||||||
|
},
|
||||||
|
filterByTag: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "reference",
|
||||||
|
collection: "tag",
|
||||||
|
},
|
||||||
|
description: "Only posts with these tags",
|
||||||
|
},
|
||||||
|
posts: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "reference",
|
||||||
|
collection: "post",
|
||||||
|
},
|
||||||
|
description: "Fixed list of posts (when not allPosts)",
|
||||||
|
},
|
||||||
|
numberItems: {
|
||||||
|
type: "integer",
|
||||||
|
description: "Max. number of displayed entries",
|
||||||
|
},
|
||||||
|
design: {
|
||||||
|
type: "string",
|
||||||
|
enum: ["cards", "list"],
|
||||||
|
description: "Display as cards or list",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
75
types/product.json5
Normal file
75
types/product.json5
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
"name": "product",
|
||||||
|
"description": "Product with SKU, price and optional fields (strict schema)",
|
||||||
|
"tags": [
|
||||||
|
"content",
|
||||||
|
"ecommerce"
|
||||||
|
],
|
||||||
|
"category": "content",
|
||||||
|
"strict": true,
|
||||||
|
"fields": {
|
||||||
|
"category": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true,
|
||||||
|
"enum": [
|
||||||
|
"electronics",
|
||||||
|
"clothing",
|
||||||
|
"books",
|
||||||
|
"food",
|
||||||
|
"other"
|
||||||
|
],
|
||||||
|
"description": "Product category"
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"type": "datetime",
|
||||||
|
"auto": true,
|
||||||
|
"readonly": true
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Detailed product description",
|
||||||
|
"maxLength": 5000
|
||||||
|
},
|
||||||
|
"images": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "Product image URLs (1–10)",
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 10
|
||||||
|
},
|
||||||
|
"in_stock": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "Whether the product is in stock"
|
||||||
|
},
|
||||||
|
"price": {
|
||||||
|
"type": "number",
|
||||||
|
"required": true,
|
||||||
|
"description": "Price in EUR",
|
||||||
|
"min": 0.0
|
||||||
|
},
|
||||||
|
"rating": {
|
||||||
|
"type": "number",
|
||||||
|
"nullable": true,
|
||||||
|
"description": "Average customer rating (null if unrated)",
|
||||||
|
"min": 0.0,
|
||||||
|
"max": 5.0
|
||||||
|
},
|
||||||
|
"sku": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true,
|
||||||
|
"unique": true,
|
||||||
|
"description": "Stock Keeping Unit (e.g. EL-1234, BOOK-00042)",
|
||||||
|
"pattern": "^[A-Z]{2,4}-\\d{3,6}$"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true,
|
||||||
|
"description": "Product name",
|
||||||
|
"minLength": 1,
|
||||||
|
"maxLength": 200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
types/quote.json5
Normal file
31
types/quote.json5
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_Quote / Contentful_Quote.ts
|
||||||
|
name: "quote",
|
||||||
|
description: "Quote block with author and optional variant",
|
||||||
|
tags: ["content", "component"],
|
||||||
|
category: "components",
|
||||||
|
fields: {
|
||||||
|
quote: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Quote text",
|
||||||
|
},
|
||||||
|
author: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Author or source of quote",
|
||||||
|
},
|
||||||
|
variant: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
enum: ["left", "right"],
|
||||||
|
default: "left",
|
||||||
|
description: "Quote alignment",
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
type: "object",
|
||||||
|
useFields: "component_layout",
|
||||||
|
description: "Column width (grid) like CF_ComponentLayout",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
44
types/searchable_text.json5
Normal file
44
types/searchable_text.json5
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_ComponentSearchableText / Contentful_SearchableText.ts
|
||||||
|
name: "searchable_text",
|
||||||
|
description: "Searchable text with optional tag whitelist",
|
||||||
|
tags: ["content", "component", "search"],
|
||||||
|
category: "components",
|
||||||
|
fields: {
|
||||||
|
id: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Unique component ID",
|
||||||
|
},
|
||||||
|
tagWhitelist: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "reference",
|
||||||
|
collection: "tag",
|
||||||
|
},
|
||||||
|
description: "Optional: only search content with these tags",
|
||||||
|
},
|
||||||
|
textFragments: {
|
||||||
|
type: "array",
|
||||||
|
required: true,
|
||||||
|
items: {
|
||||||
|
type: "reference",
|
||||||
|
collection: "text_fragment",
|
||||||
|
},
|
||||||
|
description: "Searchable text fragments (references to text_fragment)",
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: "string",
|
||||||
|
description: "Search component title",
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: "string",
|
||||||
|
description: "Description",
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
type: "object",
|
||||||
|
useFields: "component_layout",
|
||||||
|
description: "Column width (grid) like CF_ComponentLayout",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
30
types/seo.json5
Normal file
30
types/seo.json5
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
// Equivalent to: CF_SEO interface
|
||||||
|
name: "seo",
|
||||||
|
description: "SEO meta (title, robots, description; inherited by page/post)",
|
||||||
|
tags: ["seo", "partial"],
|
||||||
|
category: "layout",
|
||||||
|
fields: {
|
||||||
|
seoTitle: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "SEO page title"
|
||||||
|
},
|
||||||
|
seoMetaRobots: {
|
||||||
|
type: "string",
|
||||||
|
enum: [
|
||||||
|
"index, follow",
|
||||||
|
"noindex, follow",
|
||||||
|
"index, nofollow",
|
||||||
|
"noindex, nofollow"
|
||||||
|
],
|
||||||
|
default: "index, follow",
|
||||||
|
description: "Robots meta directive",
|
||||||
|
},
|
||||||
|
seoDescription: {
|
||||||
|
type: "string",
|
||||||
|
maxLength: 160,
|
||||||
|
description: "Meta description for search engines"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
14
types/tag.json5
Normal file
14
types/tag.json5
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
// Equivalent to: CF_Tag interface
|
||||||
|
name: "tag",
|
||||||
|
description: "Tag for categorising content",
|
||||||
|
tags: ["taxonomy", "config"],
|
||||||
|
category: "config",
|
||||||
|
fields: {
|
||||||
|
name: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
32
types/text_fragment.json5
Normal file
32
types/text_fragment.json5
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_TextFragment / Contentful_TextFragment.ts
|
||||||
|
name: "text_fragment",
|
||||||
|
description: "Reusable text fragment with optional tag references",
|
||||||
|
tags: ["content", "component"],
|
||||||
|
category: "components",
|
||||||
|
fields: {
|
||||||
|
id: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Unique fragment ID",
|
||||||
|
},
|
||||||
|
tags: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "reference",
|
||||||
|
collection: "tag",
|
||||||
|
},
|
||||||
|
description: "Optional tags for categorisation",
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Text fragment title",
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
type: "richtext",
|
||||||
|
required: true,
|
||||||
|
description: "Searchable text content",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
19
types/top_banner.json5
Normal file
19
types/top_banner.json5
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_TopBanner / Contentful_TopBanner.ts
|
||||||
|
name: "top_banner",
|
||||||
|
description: "Top-of-page banner or notice text",
|
||||||
|
tags: ["component", "layout"],
|
||||||
|
category: "components",
|
||||||
|
fields: {
|
||||||
|
id: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Unique ID",
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "Banner text (e.g. notice at top of page)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
21
types/translation_bundle.json5
Normal file
21
types/translation_bundle.json5
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
name: "translation_bundle",
|
||||||
|
description: "Übersetzungs-Bundle: ein Objekt mit beliebigen Keys (String) und Werten (String). Für i18n / UI-Texte.",
|
||||||
|
tags: [
|
||||||
|
"content",
|
||||||
|
"i18n"
|
||||||
|
],
|
||||||
|
category: "content",
|
||||||
|
partial: false,
|
||||||
|
fields: {
|
||||||
|
// object mit additionalProperties = beliebige Keys, Werte müssen Strings sein
|
||||||
|
strings: {
|
||||||
|
type: "object",
|
||||||
|
required: true,
|
||||||
|
additionalProperties: {
|
||||||
|
type: "string"
|
||||||
|
},
|
||||||
|
description: "Map: Übersetzungsschlüssel (key) → Text (value). Z. B. { \"searchable_text_help\": \"Hier könnt ihr...\", \"footer_copyright\": \"© 2024\" }",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
38
types/youtube_video.json5
Normal file
38
types/youtube_video.json5
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
// Corresponds to CF_YoutubeVideo / Contentful_YoutubeVideo.ts
|
||||||
|
name: "youtube_video",
|
||||||
|
description: "Embedded YouTube video with optional params",
|
||||||
|
tags: [
|
||||||
|
"media",
|
||||||
|
"component"
|
||||||
|
],
|
||||||
|
category: "components",
|
||||||
|
fields: {
|
||||||
|
id: {
|
||||||
|
type: "string",
|
||||||
|
description: "Unique ID (optional, otherwise _slug)",
|
||||||
|
},
|
||||||
|
youtubeId: {
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
description: "YouTube video ID (e.g. from URL ?v=VIDEO_ID)",
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
type: "string",
|
||||||
|
description: "Optional URL params (e.g. start=30, autoplay=1)",
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: "string",
|
||||||
|
description: "Video title",
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: "string",
|
||||||
|
description: "Short description",
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
type: "object",
|
||||||
|
useFields: "component_layout",
|
||||||
|
description: "Column width (grid) like CF_ComponentLayout",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user