project setup with core files including configuration, package management, and basic structure. Added .gitignore, README, and various TypeScript types for CMS components. Implemented initial components and layouts for the application.

This commit is contained in:
Peter Meier
2025-12-13 23:26:13 +01:00
parent ea288a5bbc
commit b1a556dc6d
167 changed files with 19057 additions and 131 deletions

View File

@@ -0,0 +1,14 @@
import type { CF_ContentType } from "src/@types/Contentful_ContentType.enum";
import type { CF_ComponentListSkeleton } from "src/@types/Contentful_List";
export interface CF_ComponentBadges {
internal: string;
badges: CF_ComponentListSkeleton;
variants: "light" | "dark";
layout?: any;
}
export interface CF_ComponentBadgesSkeleton {
contentTypeId: CF_ContentType.badges
fields: CF_ComponentBadges
}

View File

@@ -0,0 +1,24 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum";
import type { Asset } from "contentful";
export interface CF_Campaign {
campaignName: string;
urlPatter: string;
selector: string;
insertHtml:
| "afterbegin"
| "beforeend"
| "afterend"
| "beforebegin"
| "replace";
timeUntil?: string;
javascript?: string;
medias?: Asset[];
html?: string;
css?: string;
}
export interface CF_CampaignSkeleton {
contentTypeId: CF_ContentType.campaign;
fields: CF_Campaign;
}

View File

@@ -0,0 +1,13 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum";
import type { CF_CampaignSkeleton } from "./Contentful_Campaign";
export interface CF_Campaigns {
id: string;
campaings: CF_CampaignSkeleton[];
enable: boolean;
}
export interface CF_CampaignsSkeleton {
contentTypeId: CF_ContentType.campaigns;
fields: CF_Campaigns;
}

View File

@@ -0,0 +1,15 @@
export interface CF_CloudinaryImage {
bytes: number;
created_at: string;
format: string;
height: number;
original_secure_url: string;
original_url: string;
public_id: string;
resource_type: string;
secure_url: string;
type: string;
url: string;
version: number;
width: number;
}

View File

@@ -0,0 +1,24 @@
import type { EntrySkeletonType } from "contentful";
export type rowJutify =
| "start"
| "end"
| "center"
| "between"
| "around"
| "evenly";
export type rowAlignItems = "start" | "end" | "center" | "baseline" | "stretch";
export interface CF_Content {
row1JustifyContent: rowJutify;
row1AlignItems: rowAlignItems;
row1Content: EntrySkeletonType<any>[];
row2JustifyContent: rowJutify;
row2AlignItems: rowAlignItems;
row2Content: EntrySkeletonType<any>[];
row3JustifyContent: rowJutify;
row3AlignItems: rowAlignItems;
row3Content: EntrySkeletonType<any>[];
}

View File

@@ -0,0 +1,31 @@
export enum CF_ContentType {
"componentLinkList" = "componentLinkList",
"badges" = "badges",
"componentPostOverview" = "componentPostOverview",
"footer" = "footer",
"fullwidthBanner" = "fullwidthBanner",
"headline" = "headline",
"html" = "html",
"image" = "image",
"img" = "img",
"iframe" = "iframe",
"imgGallery" = "imageGallery",
"internalReference" = "internalComponent",
"link" = "link",
"list" = "list",
"markdown" = "markdown",
"navigation" = "navigation",
"page" = "page",
"pageConfig" = "pageConfig",
"picture" = "picture",
"post" = "post",
"postComponent" = "postComponent",
"quote" = "quoteComponent",
"richtext" = "richtext",
"row" = "row",
"rowLayout" = "rowLayout",
"tag" = "tag",
"youtubeVideo" = "youtubeVideo",
"campaign" = "campaign",
"campaigns" = "campaigns",
}

View File

@@ -0,0 +1,10 @@
import type { CF_ContentType } from "src/@types/Contentful_ContentType.enum";
import type { CF_Content } from "./Contentful_Content";
export interface CF_Footer extends CF_Content {
id : string;
}
export type CF_FooterSkeleton = {
contentTypeId: CF_ContentType.footer
fields: CF_Footer
}

View File

@@ -0,0 +1,24 @@
import type { CF_ComponentImgSkeleton } from "./Contentful_Img";
import type { CF_CloudinaryImage } from "./Contentful_CloudinaryImage";
import type { CF_ContentType } from "./Contentful_ContentType.enum";
export enum CF_FullwidthBannerVariant {
"dark"= "dark",
"light" = "light"
}
export interface CF_FullwidthBanner {
name: string,
variant : CF_FullwidthBannerVariant,
headline : string,
subheadline: string,
text : string,
image: CF_CloudinaryImage[];
img: CF_ComponentImgSkeleton;
}
export type CF_FullwidthBannerSkeleton = {
contentTypeId: CF_ContentType.fullwidthBanner
fields: CF_FullwidthBanner
}

View File

@@ -0,0 +1,29 @@
import type { EntrySkeletonType } from "contentful";
import type { CF_ContentType } from "src/@types/Contentful_ContentType.enum";
export type CF_justfyContent = "start" | "end" | "center" | "between" | "around" | "evenly";
export type CF_alignItems = "start" | "end" | "center" | "baseline" | "stretch"
export interface CF_Column_Alignment {
justifyContent: CF_justfyContent,
alignItems: CF_alignItems
}
export interface CF_Column_Layout<T> {
layoutMobile: T
layoutTablet: T
layoutDesktop: T
}
export type CF_Row_1_Column_Layout = "auto" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "10" | "11" | "12";
export interface CF_Row {
alignment: EntrySkeletonType<CF_Column_Alignment>
layout: EntrySkeletonType<CF_Column_Layout<CF_Row_1_Column_Layout>>
content: EntrySkeletonType<any>[]
}
export interface CF_RowSkeleton {
contentTypeId: CF_ContentType.row
fields: CF_Row
}

View File

@@ -0,0 +1,21 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum.js";
import type { CF_ComponentLayout } from "./Contentful_Layout.js";
export type CF_Component_Headline_Align = "left" | "center" | "right";
export type CF_Component_Headline_Tag = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
export type CF_alignTextClasses = "text-left" | "text-center" | "text-right";
export interface CF_ComponentHeadline {
internal: string;
text: string;
tag: CF_Component_Headline_Tag;
layout: CF_ComponentLayout;
align?: CF_Component_Headline_Align;
}
export interface CF_ComponentHeadlineSkeleton {
contentTypeId: CF_ContentType.headline;
fields: CF_ComponentHeadline;
}

View File

@@ -0,0 +1,13 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum";
import type { CF_ComponentLayout } from "./Contentful_Layout";
export interface CF_HTML {
id: string;
html: string;
layout: CF_ComponentLayout;
}
export type CF_HTMLSkeleton = {
contentTypeId: CF_ContentType.html;
fields: CF_HTML;
};

View File

@@ -0,0 +1,16 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum";
import type { CF_ComponentImgSkeleton } from "./Contentful_Img";
import type { CF_ComponentLayout } from "./Contentful_Layout";
export interface CF_ComponentIframe {
name: string;
content: string;
iframe: string;
overlayImage?: CF_ComponentImgSkeleton;
layout: CF_ComponentLayout;
}
export interface CF_ComponentIframeSkeleton {
contentTypeId: CF_ContentType.iframe;
fields: CF_ComponentIframe;
}

View File

@@ -0,0 +1,17 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum";
import type { CF_ComponentImgSkeleton } from "./Contentful_Img";
import type { CF_ComponentLayout } from "./Contentful_Layout";
export interface CF_ComponentImage {
name: string;
image: CF_ComponentImgSkeleton;
caption: string;
layout: CF_ComponentLayout;
maxWidth?: number;
aspectRatio?: number;
}
export interface CF_ComponentImageSkeleton {
contentTypeId: CF_ContentType.image;
fields: CF_ComponentImage;
}

View File

@@ -0,0 +1,15 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum.js";
import type { CF_ComponentImgSkeleton } from "./Contentful_Img.js";
import type { CF_ComponentLayout } from "./Contentful_Layout.js";
export interface CF_ImageGallery {
name: string;
images: CF_ComponentImgSkeleton[];
layout: CF_ComponentLayout;
description?: string;
}
export interface CF_ImageGallerySkeleton {
contentTypeId: CF_ContentType.imgGallery;
fields: CF_ImageGallery;
}

View File

@@ -0,0 +1,26 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum";
export interface CF_ComponentImgDetails {
size: number,
image: {
width: number,
height: number
}
}
export interface CF_ComponentImg {
title: string;
description: string;
file: {
url: string;
details: CF_ComponentImgDetails;
fileName: string;
contentType: string;
}
}
export interface CF_ComponentImgSkeleton {
contentTypeId: CF_ContentType.img
fields: CF_ComponentImg
}

View File

@@ -0,0 +1,14 @@
import type { CF_ContentType } from "src/@types/Contentful_ContentType.enum";
import type { CF_ComponentLayout } from "src/@types/Contentful_Layout";
import type { EntryFieldTypes } from "contentful";
export interface CF_internalReference {
data: EntryFieldTypes.Object,
reference: string,
layout: CF_ComponentLayout
}
export type CF_internalReferenceSkeleton = {
contentTypeId: CF_ContentType.internalReference
fields: CF_internalReference
}

View File

@@ -0,0 +1,100 @@
import type { CF_ContentType } from "src/@types/Contentful_ContentType.enum";
export type CF_Component_Layout_Width =
| "1"
| "2"
| "3"
| "4"
| "5"
| "6"
| "7"
| "8"
| "9"
| "10"
| "11"
| "12";
export type CF_widths_mobile =
| "w-full"
| "w-1/12"
| "w-2/12"
| "w-3/12"
| "w-4/12"
| "w-5/12"
| "w-6/12"
| "w-7/12"
| "w-8/12"
| "w-9/12"
| "w-10/12"
| "w-11/12";
export type CF_widths_tablet =
| ""
| "md:w-full"
| "md:w-1/12"
| "md:w-2/12"
| "md:w-3/12"
| "md:w-4/12"
| "md:w-5/12"
| "md:w-6/12"
| "md:w-7/12"
| "md:w-8/12"
| "md:w-9/12"
| "md:w-10/12"
| "md:w-11/12";
export type CF_widths_desktop =
| ""
| "lg:w-full"
| "lg:w-1/12"
| "lg:w-2/12"
| "lg:w-3/12"
| "lg:w-4/12"
| "lg:w-5/12"
| "lg:w-6/12"
| "lg:w-7/12"
| "lg:w-8/12"
| "lg:w-9/12"
| "lg:w-10/12"
| "lg:w-11/12";
export type CF_Component_Layout_Space =
| 0
| .5
| 1
| 1.5
| 2
export type CF_Component_Space =
| ""
| "mb-[0.5rem]"
| "mb-[1rem]"
| "mb-[1.5rem]"
| "mb-[2rem]"
export type CF_justfyContent =
| "justify-start"
| "justify-end"
| "justify-center"
| "justify-between"
| "justify-around"
| "justify-evenly";
export type CF_alignItems =
| "items-start"
| "items-end"
| "items-center"
| "items-baseline"
| "items-stretch";
export interface CF_ComponentLayout {
mobile: CF_Component_Layout_Width;
tablet?: CF_Component_Layout_Width;
desktop?: CF_Component_Layout_Width;
spaceBottom?: CF_Component_Layout_Space
}
export interface CF_ComponentLayoutSkeleton {
contentTypeId: CF_ContentType.rowLayout
fields: CF_ComponentLayout
}

View File

@@ -0,0 +1,23 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum";
export interface CF_Link {
name: string;
internal: string;
linkName: string;
icon?: string;
color?: string;
url: string;
newTab?: boolean;
external?: boolean;
description?: string;
alt?: string;
showText?: boolean;
author: string;
date: string;
source: string;
}
export interface CF_LinkSkeleton {
contentTypeId: CF_ContentType.link;
fields: CF_Link;
}

View File

@@ -0,0 +1,12 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum";
import type { CF_LinkSkeleton } from "./Contentful_Link";
export interface CF_Link_List {
headline: string;
links: CF_LinkSkeleton[];
}
export type CF_LinkListSkeleton = {
contentTypeId: CF_ContentType.componentLinkList;
fields: CF_Link_List;
};

View File

@@ -0,0 +1,11 @@
import type { CF_ContentType } from "src/@types/Contentful_ContentType.enum";
export interface CF_ComponentList {
internal: string;
item: string[];
}
export interface CF_ComponentListSkeleton {
contentTypeId: CF_ContentType.list
fields: CF_ComponentList
}

View File

@@ -0,0 +1,15 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum";
import type { CF_ComponentLayout } from "./Contentful_Layout";
import type { TextAlignment } from "./TextAlignment";
export interface CF_Markdown {
name: string;
content: string;
layout: CF_ComponentLayout;
alignment: TextAlignment;
}
export type CF_MarkdownSkeleton = {
contentTypeId: CF_ContentType.markdown;
fields: CF_Markdown;
};

View File

@@ -0,0 +1,17 @@
export enum CF_Navigation_Keys {
"header" = "navigation-header",
"socialMedia" = "navigation-social-media",
"footer" = "navigation-footer",
}
export enum CF_PageConfigKey {
"pageConfig" = "page-config",
}
export enum CF_Footer_Keys {
"main" = "main",
}
export enum CF_Campaigns_Keys {
"campaigns" = "campaigns",
}

View File

@@ -0,0 +1,14 @@
import type { CF_Link } from "./Contentful_Link";
import type { CF_ContentType } from "./Contentful_ContentType.enum";
import type { CF_Page } from "./Contentful_Page";
export interface CF_Navigation {
name: string;
internal: string;
links: Array<{ fields: CF_Link | CF_Page }>;
}
export type CF_NavigationSkeleton = {
contentTypeId: CF_ContentType.navigation;
fields: CF_Navigation;
};

View File

@@ -0,0 +1,19 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum";
import type { CF_FullwidthBannerSkeleton } from "./Contentful_FullwidthBanner";
import type { CF_Content } from "./Contentful_Content";
import type { CF_SEO } from "./Contentful_SEO";
export interface CF_Page extends CF_Content, CF_SEO {
slug: string;
name: string;
linkName: string;
icon?: string;
headline: string;
subheadline: string;
topFullwidthBanner: CF_FullwidthBannerSkeleton;
}
export type CF_PageSkeleton = {
contentTypeId: CF_ContentType.page;
fields: CF_Page;
};

View File

@@ -0,0 +1,18 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum";
import type { CF_ComponentImgSkeleton } from "./Contentful_Img";
export interface CF_PageConfig {
logo: CF_ComponentImgSkeleton;
footerText1: string;
seoTitle: string;
seoDescription: string;
blogTagPageHeadline: string;
blogPostsPageHeadline: string;
blogPostsPageSubHeadline: string;
website: string;
}
export type CF_PageConfigSkeleton = {
contentTypeId: CF_ContentType.pageConfig;
fields: CF_PageConfig;
};

View File

@@ -0,0 +1,7 @@
export interface CF_Page_Seo {
name: "page-about-seo",
title: "about",
description: "about",
metaRobotsIndex: "index",
metaRobotsFollow: "follow"
}

View File

@@ -0,0 +1,57 @@
import type { EntryFieldTypes } from "contentful";
import type { CF_ContentType } from "src/@types/Contentful_ContentType.enum";
import type { CF_CloudinaryImage } from "src/@types/Contentful_CloudinaryImage";
export type CF_PictureWidths = 400 | 800 | 1200 | 1400
export type CF_PictureFormats = "aviv" | "jpg" | "png" | "webp"
export type CF_PictureFit = "contain" | "cover" | "fill" | "inside" | "outside"
export type CF_PicturePosition = "top"
| "right top"
| "right"
| "right bottom"
| "bottom"
| "left bottom"
| "left"
| "left top"
| "north"
| "northeast"
| "east"
| "southeast"
| "south"
| "southwest"
| "west"
| "northwest"
| "center"
| "centre"
| "cover"
| "entropy"
| "attention"
export type CF_PictureAspectRatio = 'original'
| '32:9'
| '16:9'
| '5:4'
| '4:3'
| '3:2'
| '1:1'
| '2:3'
| '3:4'
| '4:5'
export interface CF_Picture {
name: EntryFieldTypes.Text;
image: CF_CloudinaryImage[];
alt?: EntryFieldTypes.Text;
widths: Array<CF_PictureWidths>;
aspectRatio: CF_PictureAspectRatio;
formats: CF_PictureFormats;
fit: CF_PictureFit;
position: CF_PicturePosition;
layout?: any;
}
export type CF_PictureSkeleton = {
contentTypeId: CF_ContentType.picture
fields: CF_Picture
}

View File

@@ -0,0 +1,25 @@
import type { CF_ContentType } from "src/@types/Contentful_ContentType.enum";
import type { CF_ComponentImgSkeleton } from "./Contentful_Img";
import type { CF_Content } from "./Contentful_Content";
import type { CF_SEO } from "./Contentful_SEO";
import type { CF_TagSkeleton } from "./Contentful_Tag";
export interface CF_Post extends CF_Content, CF_SEO {
postImage: CF_ComponentImgSkeleton;
postTag: CF_TagSkeleton[];
slug: string;
linkName: string;
icon?: string;
headline: string;
important: boolean;
created: string;
date?: string;
subheadline: string;
excerpt: string;
content: string;
}
export type CF_PostEntrySkeleton = {
contentTypeId: CF_ContentType.post;
fields: CF_Post;
};

View File

@@ -0,0 +1,14 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum";
import type { CF_ComponentLayout } from "./Contentful_Layout";
import type { CF_PostEntrySkeleton } from "./Contentful_Post";
export interface CF_PostComponent {
id: string;
post: CF_PostEntrySkeleton;
layout: CF_ComponentLayout;
}
export interface CF_PostComponentSkeleton {
contentTypeId: CF_ContentType.postComponent;
fields: CF_PostComponent;
}

View File

@@ -0,0 +1,24 @@
import type { CF_ContentType } from "src/@types/Contentful_ContentType.enum";
import type { CF_Content } from "./Contentful_Content";
import type { CF_SEO } from "src/@types/Contentful_SEO";
import type { CF_ComponentLayout } from "src/@types/Contentful_Layout";
import type { CF_PostEntrySkeleton } from "src/@types/Contentful_Post";
import type { CF_TagSkeleton } from "src/@types/Contentful_Tag";
import type { Document } from "@contentful/rich-text-types";
export interface CF_Post_Overview extends CF_Content, CF_SEO {
id: string;
headline: string;
text: Document;
layout: CF_ComponentLayout;
allPosts: boolean;
filterByTag: CF_TagSkeleton[];
posts: CF_PostEntrySkeleton[];
numberItems: number;
design?: "cards" | "list";
}
export type CF_Post_OverviewEntrySkeleton = {
contentTypeId: CF_ContentType.post;
fields: CF_Post_Overview;
};

View File

@@ -0,0 +1,14 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum.js";
import type { CF_ComponentLayout } from "./Contentful_Layout.js";
export interface CF_Quote {
quote: string;
author: string;
variant: "left" | "right";
layout: CF_ComponentLayout;
}
export type CF_QuoteSkeleton = {
contentTypeId: CF_ContentType.quote;
fields: CF_Quote;
};

View File

@@ -0,0 +1,11 @@
import type { CF_ContentType } from "src/@types/Contentful_ContentType.enum";
export interface CF_ComponentRichtext {
content?: Document;
layout?: any;
}
export interface CF_ComponentRichtextSkeleton {
contentTypeId: CF_ContentType.richtext
fields: CF_ComponentRichtext
}

View File

@@ -0,0 +1,8 @@
export type metaRobots = "index, follow" | "noindex, follow" | "index, nofollow" | "noindex, nofollow";
export interface CF_SEO {
seoTitle : string,
seoMetaRobots : metaRobots,
seoDescription : string,
}

View File

@@ -0,0 +1,6 @@
import type { CF_PostEntrySkeleton } from "src/@types/Contentful_Post";
import type { CF_NavigationSkeleton } from "src/@types/Contentful_Navigation";
import type { CF_PageSkeleton } from "src/@types/Contentful_Page";
import type { CF_PageConfigSkeleton } from "src/@types/Contentful_PageConfig";
export type CF_SkeletonTypes = CF_PostEntrySkeleton | CF_NavigationSkeleton | CF_PageSkeleton | CF_PageConfigSkeleton;

View File

@@ -0,0 +1,11 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum";
export interface CF_Tag {
name: string;
icon: string;
}
export interface CF_TagSkeleton {
contentTypeId: CF_ContentType.tag;
fields: CF_Tag;
}

View File

@@ -0,0 +1,16 @@
import type { CF_ContentType } from "./Contentful_ContentType.enum";
import type { CF_ComponentLayout } from "./Contentful_Layout";
export interface CF_YoutubeVideo {
id: string;
youtubeId: string;
params?: string;
title?: string;
description?: string;
layout: CF_ComponentLayout;
}
export interface CF_ComponentYoutubeVideoSkeleton {
contentTypeId: CF_ContentType.youtubeVideo;
fields: CF_YoutubeVideo;
}

View File

@@ -0,0 +1,72 @@
export type TwitterCardType = "summary" | "summary_large_image" | "app" | "player";
export interface Link extends HTMLLinkElement {
prefetch: boolean;
crossorigin: string;
}
export interface Meta extends HTMLMetaElement {
property: string;
}
export interface SeoProperties {
title?: string;
titleTemplate?: string;
titleDefault?: string;
charset?: string;
description?: string;
canonical?: URL | string;
nofollow?: boolean;
noindex?: boolean;
languageAlternates?: {
href: URL | string;
hrefLang: string;
}[];
openGraph?: {
basic: {
title: string;
type: string;
image: string;
url?: URL | string;
};
optional?: {
audio?: string;
description?: string;
determiner?: string;
locale?: string;
localeAlternate?: string[];
siteName?: string;
video?: string;
};
image?: {
url?: URL | string;
secureUrl?: URL | string;
type?: string;
width?: number;
height?: number;
alt?: string;
};
article?: {
publishedTime?: string;
modifiedTime?: string;
expirationTime?: string;
authors?: string[];
section?: string;
tags?: string[];
};
};
twitter?: {
card?: TwitterCardType;
site?: string;
creator?: string;
title?: string;
description?: string;
image?: URL | string;
imageAlt?: string;
};
extend?: {
link?: Partial<Link>[];
meta?: Partial<Meta>[];
};
surpressWarnings?: boolean;
}

View File

@@ -0,0 +1,6 @@
export type TextAlignment = 'left' | 'center' | 'right';
export enum TextAlignmentClasses {
'left' = 'text-left',
'center' = 'text-center',
'right' = 'text-right'
}