fix(web): remove redundant prop-types and unblock lint pipeline
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 10s
Build & Deploy / 🧪 QA (push) Failing after 2m24s
Build & Deploy / 🏗️ Build (push) Failing after 3m40s
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🩺 Health Check (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 3s
1
.gitignore
vendored
@@ -3,6 +3,7 @@ dist/
|
|||||||
.next/
|
.next/
|
||||||
out/
|
out/
|
||||||
.contentlayer/
|
.contentlayer/
|
||||||
|
.pnpm-store
|
||||||
|
|
||||||
# generated types
|
# generated types
|
||||||
.astro/
|
.astro/
|
||||||
|
|||||||
@@ -5,14 +5,12 @@ WORKDIR /app
|
|||||||
# Arguments for build-time configuration
|
# Arguments for build-time configuration
|
||||||
ARG NEXT_PUBLIC_BASE_URL
|
ARG NEXT_PUBLIC_BASE_URL
|
||||||
ARG NEXT_PUBLIC_TARGET
|
ARG NEXT_PUBLIC_TARGET
|
||||||
ARG DIRECTUS_URL
|
|
||||||
ARG UMAMI_API_ENDPOINT
|
ARG UMAMI_API_ENDPOINT
|
||||||
ARG NPM_TOKEN
|
ARG NPM_TOKEN
|
||||||
|
|
||||||
# Environment variables for Next.js build
|
# Environment variables for Next.js build
|
||||||
ENV NEXT_PUBLIC_BASE_URL=$NEXT_PUBLIC_BASE_URL
|
ENV NEXT_PUBLIC_BASE_URL=$NEXT_PUBLIC_BASE_URL
|
||||||
ENV NEXT_PUBLIC_TARGET=$NEXT_PUBLIC_TARGET
|
ENV NEXT_PUBLIC_TARGET=$NEXT_PUBLIC_TARGET
|
||||||
ENV DIRECTUS_URL=$DIRECTUS_URL
|
|
||||||
ENV UMAMI_API_ENDPOINT=$UMAMI_API_ENDPOINT
|
ENV UMAMI_API_ENDPOINT=$UMAMI_API_ENDPOINT
|
||||||
ENV SKIP_RUNTIME_ENV_VALIDATION=true
|
ENV SKIP_RUNTIME_ENV_VALIDATION=true
|
||||||
ENV CI=true
|
ENV CI=true
|
||||||
|
|||||||
20
Dockerfile.dev
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
FROM node:20-alpine
|
||||||
|
|
||||||
|
# Install essential build tools if needed (e.g., for node-gyp)
|
||||||
|
RUN apk add --no-cache libc6-compat python3 make g++
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Enable corepack for pnpm
|
||||||
|
RUN corepack enable
|
||||||
|
|
||||||
|
# Pre-set the pnpm store directory to a location we can volume-mount
|
||||||
|
ENV PNPM_HOME="/pnpm"
|
||||||
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
|
|
||||||
|
# Set up pnpm store configuration
|
||||||
|
RUN pnpm config set store-dir /pnpm/store
|
||||||
|
|
||||||
|
# Note: Dependency installation happens at runtime to support linked packages
|
||||||
|
# and named volumes, but the base image is now optimized for the stack.
|
||||||
|
EXPOSE 3000
|
||||||
95
Posts.ts.tmp
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
import type { CollectionConfig } from "payload";
|
||||||
|
import { lexicalEditor, BlocksFeature } from "@payloadcms/richtext-lexical";
|
||||||
|
import { allBlocks } from "../blocks/allBlocks";
|
||||||
|
|
||||||
|
export const Posts: CollectionConfig = {
|
||||||
|
slug: "posts",
|
||||||
|
admin: {
|
||||||
|
useAsTitle: "title",
|
||||||
|
},
|
||||||
|
access: {
|
||||||
|
read: () => true, // Publicly readable API
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "aiOptimizer",
|
||||||
|
type: "ui",
|
||||||
|
admin: {
|
||||||
|
position: "sidebar",
|
||||||
|
components: {
|
||||||
|
Field: "@/src/payload/components/OptimizeButton#OptimizeButton",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "title",
|
||||||
|
type: "text",
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "slug",
|
||||||
|
type: "text",
|
||||||
|
required: true,
|
||||||
|
unique: true,
|
||||||
|
admin: {
|
||||||
|
position: "sidebar",
|
||||||
|
},
|
||||||
|
hooks: {
|
||||||
|
beforeValidate: [
|
||||||
|
({ value, data }) => {
|
||||||
|
if (value) return value;
|
||||||
|
if (data?.title) {
|
||||||
|
return data.title
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/ /g, "-")
|
||||||
|
.replace(/[^\w-]+/g, "");
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "description",
|
||||||
|
type: "text",
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "date",
|
||||||
|
type: "date",
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "tags",
|
||||||
|
type: "array",
|
||||||
|
required: true,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "tag",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "featuredImage",
|
||||||
|
type: "upload",
|
||||||
|
relationTo: "media",
|
||||||
|
admin: {
|
||||||
|
description: "The main hero image for the blog post.",
|
||||||
|
position: "sidebar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "content",
|
||||||
|
type: "richText",
|
||||||
|
editor: lexicalEditor({
|
||||||
|
features: ({ defaultFeatures }) => [
|
||||||
|
...defaultFeatures,
|
||||||
|
BlocksFeature({
|
||||||
|
blocks: allBlocks,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
After Width: | Height: | Size: 953 KiB |
|
After Width: | Height: | Size: 198 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 5.0 MiB |
BIN
apps/public/media/build-first-digital-architecture-1024x572.png
Normal file
|
After Width: | Height: | Size: 915 KiB |
BIN
apps/public/media/build-first-digital-architecture-400x300.png
Normal file
|
After Width: | Height: | Size: 187 KiB |
BIN
apps/public/media/build-first-digital-architecture-768x1024.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
apps/public/media/build-first-digital-architecture.png
Normal file
|
After Width: | Height: | Size: 5.2 MiB |
|
After Width: | Height: | Size: 654 KiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 987 KiB |
BIN
apps/public/media/builder-systems-threaten-independence.png
Normal file
|
After Width: | Height: | Size: 4.8 MiB |
BIN
apps/public/media/clean-code-for-business-value-1024x572.png
Normal file
|
After Width: | Height: | Size: 659 KiB |
BIN
apps/public/media/clean-code-for-business-value-400x300.png
Normal file
|
After Width: | Height: | Size: 137 KiB |
BIN
apps/public/media/clean-code-for-business-value-768x1024.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
apps/public/media/clean-code-for-business-value.png
Normal file
|
After Width: | Height: | Size: 4.5 MiB |
BIN
apps/public/media/crm-synchronization-headless-1024x572.png
Normal file
|
After Width: | Height: | Size: 670 KiB |
BIN
apps/public/media/crm-synchronization-headless-400x300.png
Normal file
|
After Width: | Height: | Size: 133 KiB |
BIN
apps/public/media/crm-synchronization-headless-768x1024.png
Normal file
|
After Width: | Height: | Size: 987 KiB |
BIN
apps/public/media/crm-synchronization-headless.png
Normal file
|
After Width: | Height: | Size: 4.5 MiB |
|
After Width: | Height: | Size: 690 KiB |
|
After Width: | Height: | Size: 162 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
BIN
apps/public/media/digital-longevity-architecture-1024x572.png
Normal file
|
After Width: | Height: | Size: 743 KiB |
BIN
apps/public/media/digital-longevity-architecture-400x300.png
Normal file
|
After Width: | Height: | Size: 165 KiB |
BIN
apps/public/media/digital-longevity-architecture-768x1024.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
apps/public/media/digital-longevity-architecture.png
Normal file
|
After Width: | Height: | Size: 4.9 MiB |
BIN
apps/public/media/fixed-price-digital-projects-1024x572.png
Normal file
|
After Width: | Height: | Size: 792 KiB |
BIN
apps/public/media/fixed-price-digital-projects-400x300.png
Normal file
|
After Width: | Height: | Size: 170 KiB |
BIN
apps/public/media/fixed-price-digital-projects-768x1024.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
apps/public/media/fixed-price-digital-projects.png
Normal file
|
After Width: | Height: | Size: 4.8 MiB |
BIN
apps/public/media/gdpr-conformity-system-approach-1024x572.png
Normal file
|
After Width: | Height: | Size: 891 KiB |
BIN
apps/public/media/gdpr-conformity-system-approach-400x300.png
Normal file
|
After Width: | Height: | Size: 198 KiB |
BIN
apps/public/media/gdpr-conformity-system-approach-768x1024.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
apps/public/media/gdpr-conformity-system-approach.png
Normal file
|
After Width: | Height: | Size: 5.6 MiB |
BIN
apps/public/media/green-it-sustainable-web-1024x572.png
Normal file
|
After Width: | Height: | Size: 606 KiB |
BIN
apps/public/media/green-it-sustainable-web-400x300.png
Normal file
|
After Width: | Height: | Size: 133 KiB |
BIN
apps/public/media/green-it-sustainable-web-768x1024.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
apps/public/media/green-it-sustainable-web.png
Normal file
|
After Width: | Height: | Size: 4.3 MiB |
BIN
apps/public/media/hidden-costs-of-wordpress-plugins-1024x572.png
Normal file
|
After Width: | Height: | Size: 606 KiB |
BIN
apps/public/media/hidden-costs-of-wordpress-plugins-400x300.png
Normal file
|
After Width: | Height: | Size: 123 KiB |
BIN
apps/public/media/hidden-costs-of-wordpress-plugins-768x1024.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
apps/public/media/hidden-costs-of-wordpress-plugins.png
Normal file
|
After Width: | Height: | Size: 4.5 MiB |
BIN
apps/public/media/mintel-thumb-1771868198228-1024x572.png
Normal file
|
After Width: | Height: | Size: 783 KiB |
BIN
apps/public/media/mintel-thumb-1771868198228-400x300.png
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
apps/public/media/mintel-thumb-1771868198228-768x1024.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
apps/public/media/mintel-thumb-1771868198228.png
Normal file
|
After Width: | Height: | Size: 5.2 MiB |
BIN
apps/public/media/mintel-thumb-1771870270443-1024x572.png
Normal file
|
After Width: | Height: | Size: 635 KiB |
BIN
apps/public/media/mintel-thumb-1771870270443-400x300.png
Normal file
|
After Width: | Height: | Size: 131 KiB |
BIN
apps/public/media/mintel-thumb-1771870270443-768x1024.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
apps/public/media/mintel-thumb-1771870270443.png
Normal file
|
After Width: | Height: | Size: 4.8 MiB |
BIN
apps/public/media/no-us-cloud-platforms-1024x572.png
Normal file
|
After Width: | Height: | Size: 501 KiB |
BIN
apps/public/media/no-us-cloud-platforms-400x300.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
apps/public/media/no-us-cloud-platforms-768x1024.png
Normal file
|
After Width: | Height: | Size: 868 KiB |
BIN
apps/public/media/no-us-cloud-platforms.png
Normal file
|
After Width: | Height: | Size: 3.8 MiB |
BIN
apps/public/media/professional-hosting-operations-1024x572.png
Normal file
|
After Width: | Height: | Size: 633 KiB |
BIN
apps/public/media/professional-hosting-operations-400x300.png
Normal file
|
After Width: | Height: | Size: 141 KiB |
BIN
apps/public/media/professional-hosting-operations-768x1024.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
apps/public/media/professional-hosting-operations.png
Normal file
|
After Width: | Height: | Size: 4.3 MiB |
BIN
apps/public/media/responsive-design-high-fidelity-1024x572.png
Normal file
|
After Width: | Height: | Size: 653 KiB |
BIN
apps/public/media/responsive-design-high-fidelity-400x300.png
Normal file
|
After Width: | Height: | Size: 134 KiB |
BIN
apps/public/media/responsive-design-high-fidelity-768x1024.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
apps/public/media/responsive-design-high-fidelity.png
Normal file
|
After Width: | Height: | Size: 4.3 MiB |
BIN
apps/public/media/slow-loading-costs-customers-1024x572.png
Normal file
|
After Width: | Height: | Size: 752 KiB |
BIN
apps/public/media/slow-loading-costs-customers-400x300.png
Normal file
|
After Width: | Height: | Size: 170 KiB |
BIN
apps/public/media/slow-loading-costs-customers-768x1024.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
apps/public/media/slow-loading-costs-customers.png
Normal file
|
After Width: | Height: | Size: 5.0 MiB |
BIN
apps/public/media/website-without-cookie-banners-1024x572.png
Normal file
|
After Width: | Height: | Size: 620 KiB |
BIN
apps/public/media/website-without-cookie-banners-400x300.png
Normal file
|
After Width: | Height: | Size: 123 KiB |
BIN
apps/public/media/website-without-cookie-banners-768x1024.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
apps/public/media/website-without-cookie-banners.png
Normal file
|
After Width: | Height: | Size: 4.2 MiB |
BIN
apps/public/media/why-agencies-are-slow-1024x572.png
Normal file
|
After Width: | Height: | Size: 575 KiB |
BIN
apps/public/media/why-agencies-are-slow-400x300.png
Normal file
|
After Width: | Height: | Size: 123 KiB |
BIN
apps/public/media/why-agencies-are-slow-768x1024.png
Normal file
|
After Width: | Height: | Size: 966 KiB |
BIN
apps/public/media/why-agencies-are-slow.png
Normal file
|
After Width: | Height: | Size: 4.3 MiB |
BIN
apps/public/media/why-no-templates-matter-1024x572.png
Normal file
|
After Width: | Height: | Size: 862 KiB |
BIN
apps/public/media/why-no-templates-matter-400x300.png
Normal file
|
After Width: | Height: | Size: 178 KiB |
BIN
apps/public/media/why-no-templates-matter-768x1024.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
apps/public/media/why-no-templates-matter.png
Normal file
|
After Width: | Height: | Size: 5.0 MiB |
BIN
apps/public/media/why-websites-break-after-updates-1024x572.png
Normal file
|
After Width: | Height: | Size: 620 KiB |
BIN
apps/public/media/why-websites-break-after-updates-400x300.png
Normal file
|
After Width: | Height: | Size: 128 KiB |
BIN
apps/public/media/why-websites-break-after-updates-768x1024.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
apps/public/media/why-websites-break-after-updates.png
Normal file
|
After Width: | Height: | Size: 4.8 MiB |
@@ -1,4 +1,12 @@
|
|||||||
"use server";
|
"use server";
|
||||||
import { handleServerFunctions as payloadHandleServerFunctions } from "@payloadcms/next/layouts";
|
import { handleServerFunctions as payloadHandleServerFunctions } from "@payloadcms/next/layouts";
|
||||||
|
import config from "@payload-config";
|
||||||
|
import { importMap } from "./admin/importMap";
|
||||||
|
|
||||||
export const handleServerFunctions = payloadHandleServerFunctions;
|
export const handleServerFunctions = async (args: any) => {
|
||||||
|
return payloadHandleServerFunctions({
|
||||||
|
...args,
|
||||||
|
config,
|
||||||
|
importMap,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,6 +1,99 @@
|
|||||||
|
import { OptimizeButton as OptimizeButton_a629b3460534b7aa208597fdc5e30aec } from "@/src/payload/components/OptimizeButton";
|
||||||
|
import { GenerateSlugButton as GenerateSlugButton_63aadb132a046b3f001fac7a715e5717 } from "@/src/payload/components/FieldGenerators/GenerateSlugButton";
|
||||||
|
import { default as default_76cec558bd86098fa1dab70b12eb818f } from "@/src/payload/components/TagSelector";
|
||||||
|
import { GenerateThumbnailButton as GenerateThumbnailButton_39d416c162062cbe7173a99e3239786e } from "@/src/payload/components/FieldGenerators/GenerateThumbnailButton";
|
||||||
|
import { RscEntryLexicalCell as RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e } from "@payloadcms/richtext-lexical/rsc";
|
||||||
|
import { RscEntryLexicalField as RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e } from "@payloadcms/richtext-lexical/rsc";
|
||||||
|
import { LexicalDiffComponent as LexicalDiffComponent_44fe37237e0ebf4470c9990d8cb7b07e } from "@payloadcms/richtext-lexical/rsc";
|
||||||
|
import { BlocksFeatureClient as BlocksFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { AiFieldButton as AiFieldButton_da42292f87769a8025025b774910be6d } from "@/src/payload/components/FieldGenerators/AiFieldButton";
|
||||||
|
import { InlineToolbarFeatureClient as InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { HorizontalRuleFeatureClient as HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { UploadFeatureClient as UploadFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { BlockquoteFeatureClient as BlockquoteFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { RelationshipFeatureClient as RelationshipFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { LinkFeatureClient as LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { ChecklistFeatureClient as ChecklistFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { OrderedListFeatureClient as OrderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { UnorderedListFeatureClient as UnorderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { IndentFeatureClient as IndentFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { AlignFeatureClient as AlignFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { HeadingFeatureClient as HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { ParagraphFeatureClient as ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { InlineCodeFeatureClient as InlineCodeFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { SuperscriptFeatureClient as SuperscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { SubscriptFeatureClient as SubscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { StrikethroughFeatureClient as StrikethroughFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { UnderlineFeatureClient as UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { BoldFeatureClient as BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { ItalicFeatureClient as ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from "@payloadcms/richtext-lexical/client";
|
||||||
|
import { default as default_2ebf44fdf8ebc607cf0de30cff485248 } from "@/src/payload/components/ColorPicker";
|
||||||
|
import { default as default_a1c6da8fb7dd9846a8b07123ff256d09 } from "@/src/payload/components/IconSelector";
|
||||||
import { CollectionCards as CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1 } from "@payloadcms/next/rsc";
|
import { CollectionCards as CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1 } from "@payloadcms/next/rsc";
|
||||||
|
|
||||||
export const importMap = {
|
export const importMap = {
|
||||||
|
"@/src/payload/components/OptimizeButton#OptimizeButton":
|
||||||
|
OptimizeButton_a629b3460534b7aa208597fdc5e30aec,
|
||||||
|
"@/src/payload/components/FieldGenerators/GenerateSlugButton#GenerateSlugButton":
|
||||||
|
GenerateSlugButton_63aadb132a046b3f001fac7a715e5717,
|
||||||
|
"@/src/payload/components/TagSelector#default":
|
||||||
|
default_76cec558bd86098fa1dab70b12eb818f,
|
||||||
|
"@/src/payload/components/FieldGenerators/GenerateThumbnailButton#GenerateThumbnailButton":
|
||||||
|
GenerateThumbnailButton_39d416c162062cbe7173a99e3239786e,
|
||||||
|
"@payloadcms/richtext-lexical/rsc#RscEntryLexicalCell":
|
||||||
|
RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e,
|
||||||
|
"@payloadcms/richtext-lexical/rsc#RscEntryLexicalField":
|
||||||
|
RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e,
|
||||||
|
"@payloadcms/richtext-lexical/rsc#LexicalDiffComponent":
|
||||||
|
LexicalDiffComponent_44fe37237e0ebf4470c9990d8cb7b07e,
|
||||||
|
"@payloadcms/richtext-lexical/client#BlocksFeatureClient":
|
||||||
|
BlocksFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@/src/payload/components/FieldGenerators/AiFieldButton#AiFieldButton":
|
||||||
|
AiFieldButton_da42292f87769a8025025b774910be6d,
|
||||||
|
"@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient":
|
||||||
|
InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient":
|
||||||
|
HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#UploadFeatureClient":
|
||||||
|
UploadFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#BlockquoteFeatureClient":
|
||||||
|
BlockquoteFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#RelationshipFeatureClient":
|
||||||
|
RelationshipFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#LinkFeatureClient":
|
||||||
|
LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#ChecklistFeatureClient":
|
||||||
|
ChecklistFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#OrderedListFeatureClient":
|
||||||
|
OrderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#UnorderedListFeatureClient":
|
||||||
|
UnorderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#IndentFeatureClient":
|
||||||
|
IndentFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#AlignFeatureClient":
|
||||||
|
AlignFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#HeadingFeatureClient":
|
||||||
|
HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#ParagraphFeatureClient":
|
||||||
|
ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#InlineCodeFeatureClient":
|
||||||
|
InlineCodeFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#SuperscriptFeatureClient":
|
||||||
|
SuperscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#SubscriptFeatureClient":
|
||||||
|
SubscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#StrikethroughFeatureClient":
|
||||||
|
StrikethroughFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#UnderlineFeatureClient":
|
||||||
|
UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#BoldFeatureClient":
|
||||||
|
BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@payloadcms/richtext-lexical/client#ItalicFeatureClient":
|
||||||
|
ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||||
|
"@/src/payload/components/ColorPicker#default":
|
||||||
|
default_2ebf44fdf8ebc607cf0de30cff485248,
|
||||||
|
"@/src/payload/components/IconSelector#default":
|
||||||
|
default_a1c6da8fb7dd9846a8b07123ff256d09,
|
||||||
"@payloadcms/next/rsc#CollectionCards":
|
"@payloadcms/next/rsc#CollectionCards":
|
||||||
CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1,
|
CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import {
|
|||||||
CodeSnippet,
|
CodeSnippet,
|
||||||
AbstractCircuit,
|
AbstractCircuit,
|
||||||
} from "@/src/components/Effects";
|
} from "@/src/components/Effects";
|
||||||
import { getImgproxyUrl } from "@/src/utils/imgproxy";
|
|
||||||
import { Marker } from "@/src/components/Marker";
|
import { Marker } from "@/src/components/Marker";
|
||||||
|
|
||||||
export default function AboutPage() {
|
export default function AboutPage() {
|
||||||
@@ -51,12 +51,7 @@ export default function AboutPage() {
|
|||||||
<div className="relative w-32 h-32 md:w-40 md:h-40 rounded-full overflow-hidden border border-slate-200 shadow-xl bg-white p-1 group">
|
<div className="relative w-32 h-32 md:w-40 md:h-40 rounded-full overflow-hidden border border-slate-200 shadow-xl bg-white p-1 group">
|
||||||
<div className="w-full h-full rounded-full overflow-hidden relative aspect-square">
|
<div className="w-full h-full rounded-full overflow-hidden relative aspect-square">
|
||||||
<img
|
<img
|
||||||
src={getImgproxyUrl("/marc-mintel.png", {
|
src="/marc-mintel.png"
|
||||||
width: 400,
|
|
||||||
height: 400,
|
|
||||||
resizing_type: "fill",
|
|
||||||
gravity: "sm",
|
|
||||||
})}
|
|
||||||
alt="Marc Mintel"
|
alt="Marc Mintel"
|
||||||
className="object-cover grayscale transition-all duration-1000 ease-in-out scale-110 group-hover:scale-100 group-hover:grayscale-0 w-full h-full"
|
className="object-cover grayscale transition-all duration-1000 ease-in-out scale-110 group-hover:scale-100 group-hover:grayscale-0 w-full h-full"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { notFound } from "next/navigation";
|
import { notFound, redirect } from "next/navigation";
|
||||||
|
import { getPayloadHMR } from "@payloadcms/next/utilities";
|
||||||
|
import configPromise from "@payload-config";
|
||||||
import { getAllPosts } from "@/src/lib/posts";
|
import { getAllPosts } from "@/src/lib/posts";
|
||||||
import { BlogPostHeader } from "@/src/components/blog/BlogPostHeader";
|
import { BlogPostHeader } from "@/src/components/blog/BlogPostHeader";
|
||||||
import { Section } from "@/src/components/Section";
|
import { Section } from "@/src/components/Section";
|
||||||
@@ -9,6 +11,8 @@ import { BlogPostClient } from "@/src/components/BlogPostClient";
|
|||||||
import { TextSelectionShare } from "@/src/components/TextSelectionShare";
|
import { TextSelectionShare } from "@/src/components/TextSelectionShare";
|
||||||
import { BlogPostStickyBar } from "@/src/components/blog/BlogPostStickyBar";
|
import { BlogPostStickyBar } from "@/src/components/blog/BlogPostStickyBar";
|
||||||
import { MDXContent } from "@/src/components/MDXContent";
|
import { MDXContent } from "@/src/components/MDXContent";
|
||||||
|
import { PayloadRichText } from "@/src/components/PayloadRichText";
|
||||||
|
import { TableOfContents } from "@/src/components/TableOfContents";
|
||||||
|
|
||||||
export async function generateStaticParams() {
|
export async function generateStaticParams() {
|
||||||
const allPosts = await getAllPosts();
|
const allPosts = await getAllPosts();
|
||||||
@@ -54,6 +58,18 @@ export default async function BlogPostPage({
|
|||||||
const post = allPosts.find((p) => p.slug === slug);
|
const post = allPosts.find((p) => p.slug === slug);
|
||||||
|
|
||||||
if (!post) {
|
if (!post) {
|
||||||
|
const payload = await getPayloadHMR({ config: configPromise });
|
||||||
|
const redirectDoc = await payload.find({
|
||||||
|
collection: "redirects",
|
||||||
|
where: {
|
||||||
|
from: { equals: slug },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (redirectDoc.docs.length > 0) {
|
||||||
|
redirect(`/blog/${redirectDoc.docs[0].to}`);
|
||||||
|
}
|
||||||
|
|
||||||
notFound();
|
notFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +118,12 @@ export default async function BlogPostPage({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="article-content max-w-none">
|
<div className="article-content max-w-none">
|
||||||
<MDXContent code={post.body.code} />
|
<TableOfContents />
|
||||||
|
{post.lexicalContent ? (
|
||||||
|
<PayloadRichText data={post.lexicalContent} />
|
||||||
|
) : (
|
||||||
|
<MDXContent code={post.body.code} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Reveal>
|
</Reveal>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
12
apps/web/check-db.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
export const run = async ({ payload }) => {
|
||||||
|
const docs = await payload.find({
|
||||||
|
collection: "context-files",
|
||||||
|
limit: 100,
|
||||||
|
});
|
||||||
|
console.log(`--- DB CHECK ---`);
|
||||||
|
console.log(`Found ${docs.totalDocs} context files.`);
|
||||||
|
docs.docs.forEach((doc) => {
|
||||||
|
console.log(`- ${doc.filename}`);
|
||||||
|
});
|
||||||
|
process.exit(0);
|
||||||
|
};
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
# Marc — digital problem solver
|
|
||||||
|
|
||||||
## Identity
|
|
||||||
- Name: Marc Mintel
|
|
||||||
- Mail: marc@mintel.me
|
|
||||||
- Location: Vulkaneifel, Germany
|
|
||||||
- Role: Independent digital problem solver
|
|
||||||
- Mode: Solo
|
|
||||||
- Focus: Understanding problems and building practical solutions
|
|
||||||
|
|
||||||
## What I do
|
|
||||||
I work on digital problems and build tools, scripts, and systems to solve them.
|
|
||||||
Sometimes that means code, sometimes automation, sometimes AI, sometimes something else.
|
|
||||||
The tool is secondary. The problem comes first.
|
|
||||||
|
|
||||||
## How I work
|
|
||||||
- I try things
|
|
||||||
- I break things
|
|
||||||
- I fix things
|
|
||||||
- I write down what I learned
|
|
||||||
|
|
||||||
## What this blog is
|
|
||||||
A public notebook of:
|
|
||||||
- things I figured out
|
|
||||||
- mistakes I made
|
|
||||||
- tools I tested
|
|
||||||
- small insights that might be useful later
|
|
||||||
|
|
||||||
Mostly short entries.
|
|
||||||
Mostly practical.
|
|
||||||
|
|
||||||
## Why no portfolio
|
|
||||||
Finished projects get outdated.
|
|
||||||
Understanding doesn’t.
|
|
||||||
|
|
||||||
This blog shows how I approach problems, not how pretty something looked last year.
|
|
||||||
|
|
||||||
## Topics
|
|
||||||
- Vibe coding with AI
|
|
||||||
- Debugging and problem solving
|
|
||||||
- Mac tools and workflows
|
|
||||||
- Automation
|
|
||||||
- Small scripts and systems
|
|
||||||
- Learning notes
|
|
||||||
- FOSS
|
|
||||||
|
|
||||||
## Audience
|
|
||||||
People who:
|
|
||||||
- build things
|
|
||||||
- work with computers
|
|
||||||
- solve problems
|
|
||||||
- and don’t need marketing talk
|
|
||||||
|
|
||||||
## Tone
|
|
||||||
- calm
|
|
||||||
- factual
|
|
||||||
- direct
|
|
||||||
- no hype
|
|
||||||
- no self-promotion
|
|
||||||
|
|
||||||
## Core idea
|
|
||||||
Write things down.
|
|
||||||
So I don’t forget.
|
|
||||||
And so others might find them useful.
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
Prinzipien
|
|
||||||
|
|
||||||
Ich arbeite nach klaren Grundsätzen, die sicherstellen, dass meine Kunden fair, transparent und langfristig profitieren.
|
|
||||||
|
|
||||||
⸻
|
|
||||||
|
|
||||||
1. Volle Preis-Transparenz
|
|
||||||
Alle Kosten sind offen und nachvollziehbar.
|
|
||||||
Es gibt keine versteckten Gebühren, keine Abos, keine Lock-ins.
|
|
||||||
Jeder Kunde sieht genau, wofür er bezahlt.
|
|
||||||
|
|
||||||
⸻
|
|
||||||
|
|
||||||
2. Quellcode & Projektzugang
|
|
||||||
Auf Wunsch erhalten Kunden jederzeit den vollständigen Source Code und eine nachvollziehbare Struktur.
|
|
||||||
Damit kann jeder andere Entwickler problemlos weiterarbeiten.
|
|
||||||
Niemand kann später behaupten, der Code sei „Messy“ oder unbrauchbar.
|
|
||||||
|
|
||||||
⸻
|
|
||||||
|
|
||||||
3. Best Practices & saubere Technik
|
|
||||||
Ich setze konsequent bewährte Standards und dokumentierte Abläufe ein.
|
|
||||||
Das sorgt dafür, dass Systeme wartbar, verständlich und erweiterbar bleiben – langfristig.
|
|
||||||
|
|
||||||
⸻
|
|
||||||
|
|
||||||
4. Verantwortung & Fairness
|
|
||||||
Ich übernehme die technische Verantwortung für die Website.
|
|
||||||
Ich garantiere keine Umsätze, Rankings oder rechtliche Ergebnisse – nur saubere Umsetzung und stabile Systeme.
|
|
||||||
Wenn etwas nicht sinnvoll ist, sage ich es ehrlich.
|
|
||||||
|
|
||||||
⸻
|
|
||||||
|
|
||||||
5. Langfristiger Wert
|
|
||||||
Eine Website ist ein Investment.
|
|
||||||
Ich baue sie so, dass Anpassungen, Erweiterungen und Übergaben an andere Entwickler problemlos möglich sind.
|
|
||||||
Das schützt Ihre Investition und vermeidet teure Neuaufbauten.
|
|
||||||
|
|
||||||
⸻
|
|
||||||
|
|
||||||
6. Zusammenarbeit ohne Tricks
|
|
||||||
Keine künstlichen Deadlines, kein unnötiger Overhead.
|
|
||||||
Kommunikation ist klar, Entscheidungen nachvollziehbar, Übergaben sauber dokumentiert.
|
|
||||||
54
apps/web/migrate-docs.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { getPayload } from "payload";
|
||||||
|
import configPromise from "./payload.config";
|
||||||
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
try {
|
||||||
|
const payload = await getPayload({ config: configPromise });
|
||||||
|
console.log("Payload initialized.");
|
||||||
|
|
||||||
|
const docsDir = path.resolve(process.cwd(), "docs");
|
||||||
|
|
||||||
|
if (!fs.existsSync(docsDir)) {
|
||||||
|
console.log(`Docs directory not found at ${docsDir}`);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const files = fs.readdirSync(docsDir);
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
if (file.endsWith(".md")) {
|
||||||
|
const content = fs.readFileSync(path.join(docsDir, file), "utf8");
|
||||||
|
|
||||||
|
// Check if already exists
|
||||||
|
const existing = await payload.find({
|
||||||
|
collection: "context-files",
|
||||||
|
where: { filename: { equals: file } },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existing.totalDocs === 0) {
|
||||||
|
await payload.create({
|
||||||
|
collection: "context-files",
|
||||||
|
data: {
|
||||||
|
filename: file,
|
||||||
|
content: content,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Migration successful! Added ${count} new context files to the database.`,
|
||||||
|
);
|
||||||
|
process.exit(0);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Migration failed:", e);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
||||||
34
apps/web/migrate-drafts.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { getPayload } from "payload";
|
||||||
|
import configPromise from "./payload.config";
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
const payload = await getPayload({ config: configPromise });
|
||||||
|
const { docs } = await payload.find({
|
||||||
|
collection: "posts",
|
||||||
|
limit: 1000,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Found ${docs.length} posts. Checking status...`);
|
||||||
|
|
||||||
|
for (const doc of docs) {
|
||||||
|
if (doc._status !== "published") {
|
||||||
|
try {
|
||||||
|
await payload.update({
|
||||||
|
collection: "posts",
|
||||||
|
id: doc.id,
|
||||||
|
data: {
|
||||||
|
_status: "published",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log(`Updated "${doc.title}" to published.`);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Failed to update ${doc.title}:`, e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Migration complete.");
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
||||||
@@ -1,17 +1,15 @@
|
|||||||
import withMintelConfig from "@mintel/next-config";
|
import withMintelConfig from "@mintel/next-config";
|
||||||
import { withPayload } from '@payloadcms/next/withPayload';
|
import { withPayload } from '@payloadcms/next/withPayload';
|
||||||
|
|
||||||
import createMDX from '@next/mdx';
|
import createMDX from '@next/mdx';
|
||||||
|
import path from 'path';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
|
const filename = fileURLToPath(import.meta.url);
|
||||||
|
const dirname = path.dirname(filename);
|
||||||
|
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
pageExtensions: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx'],
|
serverExternalPackages: ['@mintel/content-engine'],
|
||||||
reactStrictMode: true,
|
|
||||||
output: 'standalone',
|
|
||||||
images: {
|
|
||||||
loader: 'custom',
|
|
||||||
loaderFile: './src/utils/imgproxy-loader.ts',
|
|
||||||
},
|
|
||||||
async rewrites() {
|
async rewrites() {
|
||||||
return [
|
return [
|
||||||
// Umami proxy rewrite handled in app/stats/api/send/route.ts
|
// Umami proxy rewrite handled in app/stats/api/send/route.ts
|
||||||
@@ -27,6 +25,13 @@ const nextConfig = {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
webpack: (config) => {
|
||||||
|
config.resolve.alias = {
|
||||||
|
...config.resolve.alias,
|
||||||
|
'@mintel/content-engine': path.resolve(dirname, 'node_modules/@mintel/content-engine'),
|
||||||
|
};
|
||||||
|
return config;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const withMDX = createMDX({
|
const withMDX = createMDX({
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "Technical problem solver's blog - practical insights and learning notes",
|
"description": "Technical problem solver's blog - practical insights and learning notes",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "rm -rf .next && next dev",
|
"dev": "pnpm run seed:context && next dev --turbo",
|
||||||
|
"seed:context": "tsx ./seed-context.ts",
|
||||||
"build": "next build --webpack",
|
"build": "next build --webpack",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "eslint app src scripts video",
|
"lint": "eslint app src scripts video",
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
"@payloadcms/email-nodemailer": "^3.77.0",
|
"@payloadcms/email-nodemailer": "^3.77.0",
|
||||||
"@payloadcms/next": "^3.77.0",
|
"@payloadcms/next": "^3.77.0",
|
||||||
"@payloadcms/richtext-lexical": "^3.77.0",
|
"@payloadcms/richtext-lexical": "^3.77.0",
|
||||||
|
"@payloadcms/ui": "^3.77.0",
|
||||||
"@react-pdf/renderer": "^4.3.2",
|
"@react-pdf/renderer": "^4.3.2",
|
||||||
"@remotion/bundler": "^4.0.414",
|
"@remotion/bundler": "^4.0.414",
|
||||||
"@remotion/cli": "^4.0.414",
|
"@remotion/cli": "^4.0.414",
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ export interface Config {
|
|||||||
users: User;
|
users: User;
|
||||||
media: Media;
|
media: Media;
|
||||||
posts: Post;
|
posts: Post;
|
||||||
|
inquiries: Inquiry;
|
||||||
|
redirects: Redirect;
|
||||||
|
"context-files": ContextFile;
|
||||||
"payload-kv": PayloadKv;
|
"payload-kv": PayloadKv;
|
||||||
"payload-locked-documents": PayloadLockedDocument;
|
"payload-locked-documents": PayloadLockedDocument;
|
||||||
"payload-preferences": PayloadPreference;
|
"payload-preferences": PayloadPreference;
|
||||||
@@ -80,6 +83,9 @@ export interface Config {
|
|||||||
users: UsersSelect<false> | UsersSelect<true>;
|
users: UsersSelect<false> | UsersSelect<true>;
|
||||||
media: MediaSelect<false> | MediaSelect<true>;
|
media: MediaSelect<false> | MediaSelect<true>;
|
||||||
posts: PostsSelect<false> | PostsSelect<true>;
|
posts: PostsSelect<false> | PostsSelect<true>;
|
||||||
|
inquiries: InquiriesSelect<false> | InquiriesSelect<true>;
|
||||||
|
redirects: RedirectsSelect<false> | RedirectsSelect<true>;
|
||||||
|
"context-files": ContextFilesSelect<false> | ContextFilesSelect<true>;
|
||||||
"payload-kv": PayloadKvSelect<false> | PayloadKvSelect<true>;
|
"payload-kv": PayloadKvSelect<false> | PayloadKvSelect<true>;
|
||||||
"payload-locked-documents":
|
"payload-locked-documents":
|
||||||
| PayloadLockedDocumentsSelect<false>
|
| PayloadLockedDocumentsSelect<false>
|
||||||
@@ -95,8 +101,12 @@ export interface Config {
|
|||||||
defaultIDType: number;
|
defaultIDType: number;
|
||||||
};
|
};
|
||||||
fallbackLocale: null;
|
fallbackLocale: null;
|
||||||
globals: {};
|
globals: {
|
||||||
globalsSelect: {};
|
"ai-settings": AiSetting;
|
||||||
|
};
|
||||||
|
globalsSelect: {
|
||||||
|
"ai-settings": AiSettingsSelect<false> | AiSettingsSelect<true>;
|
||||||
|
};
|
||||||
locale: null;
|
locale: null;
|
||||||
user: User;
|
user: User;
|
||||||
jobs: {
|
jobs: {
|
||||||
@@ -201,12 +211,99 @@ export interface Post {
|
|||||||
title: string;
|
title: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
/**
|
||||||
|
* Set a future date and save as 'Published' to schedule this post. It will not appear on the frontend until this date is reached.
|
||||||
|
*/
|
||||||
date: string;
|
date: string;
|
||||||
tags: {
|
tags: {
|
||||||
|
/**
|
||||||
|
* Kategorisiere diesen Post mit einem eindeutigen Tag
|
||||||
|
*/
|
||||||
tag?: string | null;
|
tag?: string | null;
|
||||||
id?: string | null;
|
id?: string | null;
|
||||||
}[];
|
}[];
|
||||||
thumbnail?: string | null;
|
/**
|
||||||
|
* The main hero image for the blog post.
|
||||||
|
*/
|
||||||
|
featuredImage?: (number | null) | Media;
|
||||||
|
content?: {
|
||||||
|
root: {
|
||||||
|
type: string;
|
||||||
|
children: {
|
||||||
|
type: any;
|
||||||
|
version: number;
|
||||||
|
[k: string]: unknown;
|
||||||
|
}[];
|
||||||
|
direction: ("ltr" | "rtl") | null;
|
||||||
|
format: "left" | "start" | "center" | "right" | "end" | "justify" | "";
|
||||||
|
indent: number;
|
||||||
|
version: number;
|
||||||
|
};
|
||||||
|
[k: string]: unknown;
|
||||||
|
} | null;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
_status?: ("draft" | "published") | null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Contact form leads and inquiries.
|
||||||
|
*
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "inquiries".
|
||||||
|
*/
|
||||||
|
export interface Inquiry {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
companyName?: string | null;
|
||||||
|
projectType?: string | null;
|
||||||
|
message?: string | null;
|
||||||
|
isFreeText?: boolean | null;
|
||||||
|
/**
|
||||||
|
* The JSON data from the configurator.
|
||||||
|
*/
|
||||||
|
config?:
|
||||||
|
| {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
| unknown[]
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "redirects".
|
||||||
|
*/
|
||||||
|
export interface Redirect {
|
||||||
|
id: number;
|
||||||
|
/**
|
||||||
|
* The old URL slug that should be redirected (e.g. 'old-post-name')
|
||||||
|
*/
|
||||||
|
from: string;
|
||||||
|
/**
|
||||||
|
* The new URL slug to redirect to (e.g. 'new-awesome-post')
|
||||||
|
*/
|
||||||
|
to: string;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "context-files".
|
||||||
|
*/
|
||||||
|
export interface ContextFile {
|
||||||
|
id: number;
|
||||||
|
/**
|
||||||
|
* Exact filename (e.g. 'strategy.md'). The system uses this to identify the document during prompt generation.
|
||||||
|
*/
|
||||||
|
filename: string;
|
||||||
|
/**
|
||||||
|
* The raw markdown/text content of the document.
|
||||||
|
*/
|
||||||
content: string;
|
content: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
@@ -246,6 +343,18 @@ export interface PayloadLockedDocument {
|
|||||||
| ({
|
| ({
|
||||||
relationTo: "posts";
|
relationTo: "posts";
|
||||||
value: number | Post;
|
value: number | Post;
|
||||||
|
} | null)
|
||||||
|
| ({
|
||||||
|
relationTo: "inquiries";
|
||||||
|
value: number | Inquiry;
|
||||||
|
} | null)
|
||||||
|
| ({
|
||||||
|
relationTo: "redirects";
|
||||||
|
value: number | Redirect;
|
||||||
|
} | null)
|
||||||
|
| ({
|
||||||
|
relationTo: "context-files";
|
||||||
|
value: number | ContextFile;
|
||||||
} | null);
|
} | null);
|
||||||
globalSlug?: string | null;
|
globalSlug?: string | null;
|
||||||
user: {
|
user: {
|
||||||
@@ -378,7 +487,43 @@ export interface PostsSelect<T extends boolean = true> {
|
|||||||
tag?: T;
|
tag?: T;
|
||||||
id?: T;
|
id?: T;
|
||||||
};
|
};
|
||||||
thumbnail?: T;
|
featuredImage?: T;
|
||||||
|
content?: T;
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
_status?: T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "inquiries_select".
|
||||||
|
*/
|
||||||
|
export interface InquiriesSelect<T extends boolean = true> {
|
||||||
|
name?: T;
|
||||||
|
email?: T;
|
||||||
|
companyName?: T;
|
||||||
|
projectType?: T;
|
||||||
|
message?: T;
|
||||||
|
isFreeText?: T;
|
||||||
|
config?: T;
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "redirects_select".
|
||||||
|
*/
|
||||||
|
export interface RedirectsSelect<T extends boolean = true> {
|
||||||
|
from?: T;
|
||||||
|
to?: T;
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "context-files_select".
|
||||||
|
*/
|
||||||
|
export interface ContextFilesSelect<T extends boolean = true> {
|
||||||
|
filename?: T;
|
||||||
content?: T;
|
content?: T;
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
@@ -423,6 +568,39 @@ export interface PayloadMigrationsSelect<T extends boolean = true> {
|
|||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "ai-settings".
|
||||||
|
*/
|
||||||
|
export interface AiSetting {
|
||||||
|
id: number;
|
||||||
|
/**
|
||||||
|
* List of trusted B2B/Tech sources (e.g. 'Vercel Blog', 'Fireship', 'Theo - t3.gg') the AI should prioritize when researching facts or videos. This overrides the hardcoded defaults.
|
||||||
|
*/
|
||||||
|
customSources?:
|
||||||
|
| {
|
||||||
|
sourceName: string;
|
||||||
|
id?: string | null;
|
||||||
|
}[]
|
||||||
|
| null;
|
||||||
|
updatedAt?: string | null;
|
||||||
|
createdAt?: string | null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "ai-settings_select".
|
||||||
|
*/
|
||||||
|
export interface AiSettingsSelect<T extends boolean = true> {
|
||||||
|
customSources?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
sourceName?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
globalType?: T;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "auth".
|
* via the `definition` "auth".
|
||||||
|
|||||||