Compare commits
9 Commits
content/we
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 3fac158185 | |||
| 001c8514b5 | |||
| 00a8e3248f | |||
| 9951a357ac | |||
| 3395e6ebf8 | |||
| 55c25ca203 | |||
| 53808c416a | |||
| 9dad18daa5 | |||
| d4b8c1ce4a |
@@ -158,22 +158,25 @@ jobs:
|
||||
run: |
|
||||
echo "Disk space before nuclear prune:"
|
||||
df -h
|
||||
|
||||
|
||||
# Massive cleanup of pre-installed runner software to free up ~5GB+
|
||||
# These are standard on VM-based runners and often unnecessary
|
||||
sudo rm -rf /usr/share/dotnet || true
|
||||
sudo rm -rf /usr/local/lib/android || true
|
||||
sudo rm -rf /opt/ghc || true
|
||||
sudo rm -rf /opt/hostedtoolcache/CodeQL || true
|
||||
|
||||
|
||||
# Comprehensive Docker purge
|
||||
docker buildx stop || true
|
||||
docker buildx rm -a || true
|
||||
docker rm -fv $(docker ps -aq --filter "ancestor=moby/buildkit") || true
|
||||
docker system prune -af --volumes
|
||||
docker builder prune -af
|
||||
docker buildx prune -af
|
||||
|
||||
|
||||
# Clean temp build artifacts
|
||||
rm -rf /tmp/docker-actions-toolkit-* || true
|
||||
|
||||
|
||||
echo "Disk space after nuclear prune:"
|
||||
df -h
|
||||
continue-on-error: true
|
||||
@@ -241,8 +244,6 @@ jobs:
|
||||
DIRECTUS_URL: ${{ needs.prepare.outputs.directus_url }}
|
||||
DIRECTUS_HOST: cms.${{ needs.prepare.outputs.traefik_host }}
|
||||
|
||||
|
||||
|
||||
# Mail
|
||||
MAIL_HOST: ${{ secrets.SMTP_HOST || vars.SMTP_HOST }}
|
||||
MAIL_PORT: ${{ secrets.SMTP_PORT || vars.SMTP_PORT || '587' }}
|
||||
@@ -427,7 +428,7 @@ jobs:
|
||||
|
||||
echo "Purging S3 cache for ${{ env.S3_PREFIX }} ..."
|
||||
rclone --config rclone.conf delete mintel-s3:${{ env.S3_BUCKET }}/${{ env.S3_PREFIX }}/cache/ --include "*" || true
|
||||
|
||||
|
||||
rm rclone.conf rclone-current-linux-amd64.deb
|
||||
|
||||
- name: 🧹 Post-Deploy Cleanup (Runner)
|
||||
@@ -453,7 +454,7 @@ jobs:
|
||||
COUNT=0
|
||||
MAX=24
|
||||
URL="${{ needs.prepare.outputs.next_public_url }}"
|
||||
|
||||
|
||||
echo "Verifying $URL is responsive..."
|
||||
while [ $COUNT -lt $MAX ]; do
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$URL/" || echo "000")
|
||||
@@ -465,7 +466,7 @@ jobs:
|
||||
sleep 5
|
||||
COUNT=$((COUNT + 1))
|
||||
done
|
||||
|
||||
|
||||
if [ "$STATUS" != "200" ]; then
|
||||
echo "❌ Site failed smoke test after 2 minutes! (Status: $STATUS)"
|
||||
exit 1
|
||||
@@ -475,7 +476,7 @@ jobs:
|
||||
shell: sh
|
||||
run: |
|
||||
BASE_URL="${{ needs.prepare.outputs.next_public_url }}"
|
||||
|
||||
|
||||
echo "Verifying case study page..."
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/case-studies/klz-cables")
|
||||
if [ "$STATUS" != "200" ]; then
|
||||
@@ -483,7 +484,7 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ Case study page UP"
|
||||
|
||||
|
||||
echo "Verifying breeze CSS (root path)..."
|
||||
CSS_PATH="/assets/klz-cables.com/wp-content/cache/breeze-minification/css/breeze_klz-cables-com-1-10895.css"
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL$CSS_PATH")
|
||||
@@ -492,7 +493,7 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ Root asset path OK"
|
||||
|
||||
|
||||
echo "Verifying breeze CSS (relative path from case-study)..."
|
||||
REL_CSS_PATH="/case-studies/assets/klz-cables.com/wp-content/cache/breeze-minification/css/breeze_klz-cables-com-1-10895.css"
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL$REL_CSS_PATH")
|
||||
|
||||
30
apps/web/app/api/debug-mdx/route.ts
Normal file
30
apps/web/app/api/debug-mdx/route.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { revalidatePath } from "next/cache";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const POSTS_DIR = path.join(process.cwd(), "content/blog");
|
||||
let files = [];
|
||||
if (fs.existsSync(POSTS_DIR)) {
|
||||
files = fs.readdirSync(POSTS_DIR);
|
||||
}
|
||||
|
||||
// Revalidate the two problematic pages
|
||||
revalidatePath("/blog/website-as-a-service");
|
||||
revalidatePath("/blog/zero-overhead-agencies");
|
||||
revalidatePath("/blog"); // also bust the blog list cache
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
cwd: process.cwd(),
|
||||
postsDir: POSTS_DIR,
|
||||
postsDirExists: fs.existsSync(POSTS_DIR),
|
||||
files: files,
|
||||
message: "Cache revalidated for specific paths",
|
||||
});
|
||||
} catch (err: any) {
|
||||
return NextResponse.json({ success: false, error: err.message });
|
||||
}
|
||||
}
|
||||
25
apps/web/app/debug-mdx/route.ts
Normal file
25
apps/web/app/debug-mdx/route.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { NextResponse, NextRequest } from "next/server";
|
||||
import { revalidatePath } from "next/cache";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const searchParams = request.nextUrl.searchParams;
|
||||
const pathParam = searchParams.get("path") || "/";
|
||||
const typeParam =
|
||||
(searchParams.get("type") as "page" | "layout") || "layout";
|
||||
|
||||
// Revalidate the requested path (defaults to entire app via layout)
|
||||
revalidatePath(pathParam, typeParam);
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
revalidatedPath: pathParam,
|
||||
revalidatedType: typeParam,
|
||||
message: `Cache revalidated for ${pathParam} (${typeParam})`,
|
||||
});
|
||||
} catch (err: any) {
|
||||
return NextResponse.json({ success: false, error: err.message });
|
||||
}
|
||||
}
|
||||
@@ -28,13 +28,7 @@ tags: ["business", "management", "strategy"]
|
||||
Dazu kommt das <Marker>Opportunitätsrisiko</Marker>: Was hätte das Unternehmen in diesen fünf Stunden erreichen können? Ein entscheidendes Verkaufsgespräch mehr? Eine strategische Prozessoptimierung? Die Verwaltung von IT-Infrastruktur sollte niemals die Kernaufgabe eines Nicht-IT-Unternehmens sein.
|
||||
</Paragraph>
|
||||
|
||||
<ArticleQuote
|
||||
quote="The most expensive software is the one that requires your constant attention to keep it running safely."
|
||||
author="Digital Economics"
|
||||
isCompany={true}
|
||||
source="SaaS Industry Report"
|
||||
translated={false}
|
||||
/>
|
||||
<ArticleQuote quote="The most expensive software is the one that requires your constant attention to keep it running safely." author="Digital Economics" isCompany={true} source="SaaS Industry Report" translated={false} />
|
||||
|
||||
<H2>Website as a Service: Das Ende des Overheads</H2>
|
||||
|
||||
@@ -72,14 +66,7 @@ tags: ["business", "management", "strategy"]
|
||||
In einem WaaS-Modell übernehme ich als Entwickler nicht nur die inhaltlichen Änderungen, sondern baue die Seite von Grund auf auf einer modernen, statischen Architektur (Jamstack / Next.js). Das bedeutet: Die Seite wird im Vorfeld generiert. Es gibt keine Datenbank, die live am Netz hängt und gehackt werden könnte.
|
||||
</Paragraph>
|
||||
|
||||
<ComparisonRow
|
||||
description="Wie unterscheidet sich WaaS von klassischem Hosting?"
|
||||
negativeLabel="Klassisches Hosting & CMS"
|
||||
negativeText="Sie sind selbst für Updates, Backups und Plugin-Kompatibilität verantwortlich. Die Seite ist ein Sicherheitsrisiko und veraltet technologisch schnell."
|
||||
positiveLabel="Sorglos-Paket (WaaS)"
|
||||
positiveText="Proaktives Monitoring, unsichtbare Updates und sofortige strukturelle Anpassungen durch einen Experten. Kein Stress, absolute Sicherheit und volle redaktionelle Kontrolle."
|
||||
showShare={true}
|
||||
/>
|
||||
<ComparisonRow description="Wie unterscheidet sich WaaS von klassischem Hosting?" negativeLabel="Klassisches Hosting & CMS" negativeText="Sie sind selbst für Updates, Backups und Plugin-Kompatibilität verantwortlich. Die Seite ist ein Sicherheitsrisiko und veraltet technologisch schnell." positiveLabel="Sorglos-Paket (WaaS)" positiveText="Proaktives Monitoring, unsichtbare Updates und sofortige strukturelle Anpassungen durch einen Experten. Kein Stress, absolute Sicherheit und volle redaktionelle Kontrolle." showShare={true} />
|
||||
|
||||
<Paragraph>
|
||||
Das Ergebnis: Die Seite kann faktisch nicht gehackt werden. [Updates und Wartung](/blog/why-websites-break-after-updates) laufen unsichtbar im Hintergrund ab, und die Ladezeiten sind extrem optimiert, da nur statische Dateien (HTML/CSS/JS) vom Server ausgeliefert werden.
|
||||
@@ -97,13 +84,7 @@ tags: ["business", "management", "strategy"]
|
||||
Diese <Marker>Budgetsicherheit</Marker> ist für B2B-Unternehmen extrem wertvoll. Unvorhergesehene Serverausfälle oder nötige Sicherheits-Patches sind nicht mehr Ihr finanzielles Risiko, sondern mein technisches. Es liegt also in meinem absoluten Eigeninteresse, die Architektur von Tag eins an so robust und fehlerfrei wie möglich zu bauen. Das ist das Prinzip des [strategischen Festpreises](/blog/fixed-price-digital-projects).
|
||||
</Paragraph>
|
||||
|
||||
<LeadMagnet
|
||||
title="Bereit für Zero Overhead?"
|
||||
description="Lassen Sie uns Ihre aktuelle Website analysieren. Ich zeige Ihnen, wie wir den Aufwand für Sie auf null reduzieren können."
|
||||
buttonText="Sorglos-Paket anfragen"
|
||||
href="/contact"
|
||||
variant="standard"
|
||||
/>
|
||||
<LeadMagnet title="Bereit für Zero Overhead?" description="Lassen Sie uns Ihre aktuelle Website analysieren. Ich zeige Ihnen, wie wir den Aufwand für Sie auf null reduzieren können." buttonText="Sorglos-Paket anfragen" href="/contact" variant="standard" />
|
||||
|
||||
<H2>Fazit: Kaufen Sie Zeit, keine Software</H2>
|
||||
|
||||
|
||||
@@ -28,13 +28,7 @@ tags: ["management", "strategy", "efficiency"]
|
||||
Das Problem dabei ist nicht nur der aufgeblähte Preis, sondern die **Geschwindigkeit**. Wenn Sie eine einfache inhaltliche oder funktionale Anpassung anfordern, geht die E-Mail an den Projektmanager. Dieser schreibt ein Ticket für den Designer. Der Designer macht einen Entwurf. Der Projektmanager schickt Ihnen den Entwurf. Sie geben Feedback. Das Ticket geht zurück zum Designer, dann zum Entwickler, dann in die QA, dann wieder zu Ihnen.
|
||||
</Paragraph>
|
||||
|
||||
<ArticleQuote
|
||||
quote="Every layer of communication halves the precision and doubles the time required to execute a task. In software, middle management is often a bug, not a feature."
|
||||
author="Lean Engineering Principles"
|
||||
isCompany={false}
|
||||
source="The Minimalist Developer"
|
||||
translated={false}
|
||||
/>
|
||||
<ArticleQuote quote="Every layer of communication halves the precision and doubles the time required to execute a task. In software, middle management is often a bug, not a feature." author="Lean Engineering Principles" isCompany={false} source="The Minimalist Developer" translated={false} />
|
||||
|
||||
<H2>Der Lean-Ansatz: Ein Ansprechpartner, volle Verantwortung</H2>
|
||||
|
||||
@@ -72,14 +66,7 @@ tags: ["management", "strategy", "efficiency"]
|
||||
Wenn man den Overhead eliminiert, kann man auf [hochperformante, moderne Stacks (Jamstack, Next.js)](/blog/digital-longevity-architecture) setzen. Diese wären für ein heterogenes Team oft zu komplex im Setup, können von einem Senior-Entwickler aber in einem Bruchteil der Zeit fehlerfrei und in industrieller Qualität gebaut werden.
|
||||
</Paragraph>
|
||||
|
||||
<ComparisonRow
|
||||
description="Wofür bezahlen Sie wirklich?"
|
||||
negativeLabel="Klassische Agentur"
|
||||
negativeText="Sie finanzieren Meetings, interne Abstimmungen, Projektmanagement-Tools, Büromieten und Junior-Gehälter."
|
||||
positiveLabel="Lean Engineer (Zero Overhead)"
|
||||
positiveText="Sie investieren 100% Ihres Budgets in pure Code-Qualität, High-End Design und technologische Langlebigkeit."
|
||||
showShare={true}
|
||||
/>
|
||||
<ComparisonRow description="Wofür bezahlen Sie wirklich?" negativeLabel="Klassische Agentur" negativeText="Sie finanzieren Meetings, interne Abstimmungen, Projektmanagement-Tools, Büromieten und Junior-Gehälter." positiveLabel="Lean Engineer (Zero Overhead)" positiveText="Sie investieren 100% Ihres Budgets in pure Code-Qualität, High-End Design und technologische Langlebigkeit." showShare={true} />
|
||||
|
||||
<StatsGrid stats="60%|Weniger Meetings|durch direkten Kontakt~3x|Schnellere Umsetzung|durch fehlende Feedback-Schleifen~100%|Verantwortung|bei einer einzigen Person" />
|
||||
|
||||
@@ -103,13 +90,7 @@ tags: ["management", "strategy", "efficiency"]
|
||||
Aber für 90% der B2B-Unternehmen, die eine hochprofessionelle, blitzschnelle und zukunftssichere Plattform brauchen, um digitale Dominanz auszustrahlen und Leads zu generieren? Dafür ist eine Agentur meistens Overkill – und ein massiver Rendite-Killer.
|
||||
</Paragraph>
|
||||
|
||||
<LeadMagnet
|
||||
title="Machen wir es unkompliziert."
|
||||
description="Lassen Sie uns den administrativen Overhead streichen. In einem kurzen Call klären wir die Fakten, danach erhalten Sie ein glasklares Angebot."
|
||||
buttonText="Jetzt Blueprint-Call anfragen"
|
||||
href="/contact"
|
||||
variant="standard"
|
||||
/>
|
||||
<LeadMagnet title="Machen wir es unkompliziert." description="Lassen Sie uns den administrativen Overhead streichen. In einem kurzen Call klären wir die Fakten, danach erhalten Sie ein glasklares Angebot." buttonText="Jetzt Blueprint-Call anfragen" href="/contact" variant="standard" />
|
||||
|
||||
<FAQSection>
|
||||
<H3>Was passiert, wenn der alleinige Entwickler ausfällt?</H3>
|
||||
|
||||
@@ -71,6 +71,10 @@ const nextConfig = {
|
||||
},
|
||||
// In Standalone mode, Next.js expects the tracing root to be the monorepo root
|
||||
outputFileTracingRoot: path.join(dirname, '../../'),
|
||||
outputFileTracingIncludes: {
|
||||
'/(site)/blog/[slug]': ['./content/blog/**/*'],
|
||||
'/blog/[slug]': ['./content/blog/**/*'],
|
||||
},
|
||||
};
|
||||
|
||||
const withMDX = createMDX({});
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import * as React from "react";
|
||||
import { useState, useMemo, useEffect, useRef } from "react";
|
||||
import { motion } from "framer-motion";
|
||||
import * as confetti from "canvas-confetti";
|
||||
import confetti from "canvas-confetti";
|
||||
import {
|
||||
Layers,
|
||||
BrainCircuit,
|
||||
|
||||
Reference in New Issue
Block a user