Skip to content

Instantly share code, notes, and snippets.

View julrich's full-sized avatar
🍋
squeezing!

Jonas Ulrich julrich

🍋
squeezing!
View GitHub Profile

Content Operations – n8n Workflows mit dem Storyblok MCP Server

This document describes automation workflows that editors can build using n8n connected to the Storyblok MCP Server via an MCP client node. Each workflow combines MCP tools with external n8n nodes to automate content production, quality assurance, and housekeeping.


🔴 Höchste Priorität: Content-Produktion automatisieren

1. Bulk-Seiten-Generierung aus Datenquellen

@julrich
julrich / stackbit.config.ts
Created February 4, 2026 10:11
Stackbit config export
export default defineStackbitConfig({
stackbitVersion: "~0.6.0",
ssgName: "custom",
devCommand: [
"npm run _assemble:build:tokens",
"npx @11ty/eleventy --serve --port={PORT} --incremental --config=scripts/stackbit.eleventy.js",
].join(" && "),
experimental: {
ssg: {
name: "eleventy",
@julrich
julrich / .rm-distrc.schema.json
Created February 24, 2025 11:54
Complex CLI task
{
"definitions": {},
"$schema": "http://json-schema.org/draft-06/schema#",
"$id": "https://ruhmesmeile.com/rm-dist.json",
"type": "object",
"title": "ruhmesmeile Basiswebsite / rm-dist configuration",
"required": [
"project",
"configuration",
"remote",
@julrich
julrich / hero.schema.json
Created August 1, 2024 13:51
JSON Schema for UI / content
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://schema.redacted.de/hero.schema.json",
"title": "Hero",
"description": "Prominente Bild- oder Videodarstellung mit Option für Text und Cta",
"type": "object",
"properties": {
"textPosition": {
"type": "string",
"title": "Textposition",
@julrich
julrich / Providers.tsx
Last active May 9, 2024 16:15
Unpic blurhash handling with React
function isStoryblokAsset(object: unknown): object is AssetStoryblok {
return (object as AssetStoryblok)?.filename !== undefined;
}
const Picture = forwardRef<
HTMLImageElement,
PictureProps & ImgHTMLAttributes<HTMLImageElement>
>(({ src, lazy, ...props }, ref) => {
const internalRef = useRef<HTMLImageElement>(null);
@julrich
julrich / prepareProject.js
Created April 30, 2024 12:12
Storyblok Node.js script
const fs = require("node:fs");
const PromiseThrottle = require("promise-throttle");
const FormData = require("form-data");
const { traverse } = require("object-traversal");
const sizeOf = require("image-size");
const StoryblokClient = require("storyblok-js-client");
const { v4: uuidv4 } = require("uuid");
const jsonpointer = require("jsonpointer");
const designSystemPresets = require("@kickstartds/ds-agency-premium/presets.json");
const generatedComponents = require("../cms/components.123456.json");
# Set the `immutable` cache control options only for assets with a cache busting `v` argument
map $arg_v $asset_immutable {
"" "";
default "immutable";
}
##
# Connection header for WebSocket reverse proxy
##
map $http_upgrade $connection_upgrade {
@julrich
julrich / cport.json
Created April 3, 2024 13:35
Conversion result for kickstartDS Schema and cport converter
{
"components": [
{
"id": "headline",
"name": "Headline",
"groups": [
{
"id": "default",
"name": "Default",
"contentTypeId": "headline",
@julrich
julrich / createPresets.test.ts
Last active January 29, 2024 11:58
Storybook "Extraction" revamped
/// <reference types="vite/client"/>
// @vitest-environment happy-dom
import path from "node:path";
import fs from "node:fs";
import fg from "fast-glob";
import { describe, test } from "vitest";
import { ReactRenderer, composeStories } from "@storybook/react";
import { Store_CSFExports } from "@storybook/types";
import reactElementToJSXString from "react-element-to-jsx-string";
@julrich
julrich / csf.patch
Created January 26, 2024 08:24
Add a `gt` operator for array / count controls
diff --git a/node_modules/@storybook/csf/dist/index.mjs b/node_modules/@storybook/csf/dist/index.mjs
index 537d489..3ddcc5f 100644
--- a/node_modules/@storybook/csf/dist/index.mjs
+++ b/node_modules/@storybook/csf/dist/index.mjs
@@ -1,3 +1,3 @@
-var B=Object.create;var R=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var h=Object.getPrototypeOf,w=Object.prototype.hasOwnProperty;var I=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports);var E=(r,e,n,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of C(e))!w.call(r,a)&&a!==n&&R(r,a,{get:()=>e[a],enumerable:!(t=b(e,a))||t.enumerable});return r};var v=(r,e,n)=>(n=r!=null?B(h(r)):{},E(e||!r||!r.__esModule?R(n,"default",{value:r,enumerable:!0}):n,r));var x=I(T=>{Object.defineProperty(T,"__esModule",{value:!0}),T.isEqual=function(){var r=Object.prototype.toString,e=Object.getPrototypeOf,n=Object.getOwnPropertySymbols?function(t){return Object.keys(t).concat(Object.getOwnPropertySymbols(t))}:Object.keys;r