- Add uload project with apps/web structure
- Reorganize from flat to monorepo structure
- Remove PocketBase binary and local data
- Update to pnpm and @uload/web namespace
- Add picture project to monorepo
- Remove embedded git repository
- Unify all package names to @{project}/{app} schema:
- @maerchenzauber/* (was @storyteller/*)
- @manacore/* (was manacore-*, manacore)
- @manadeck/* (was web, backend, manadeck)
- @memoro/* (was memoro-web, landing, memoro)
- @picture/* (already unified)
- @uload/web
- Add convenient dev scripts for all apps:
- pnpm dev:{project}:web
- pnpm dev:{project}:landing
- pnpm dev:{project}:mobile
- pnpm dev:{project}:backend
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
10 KiB
Blog-System Integration für uload - Vorschläge & Konzepte
Übersicht
Nach Analyse des bestehenden uload-Projekts (SvelteKit + PocketBase) präsentiere ich hier verschiedene Ansätze zur Integration eines Blog-Systems. Das Projekt hat aktuell kein Blog-System, würde aber stark von Content Marketing profitieren.
Option 1: Vollständige PocketBase-Integration (Empfohlen) ⭐
Konzept
Blog-System komplett in PocketBase integriert mit eigenem Admin-Interface.
Architektur
PocketBase Collections:
├── blog_posts
│ ├── id
│ ├── slug (unique)
│ ├── title
│ ├── excerpt
│ ├── content (rich text/markdown)
│ ├── featured_image
│ ├── author (relation zu users)
│ ├── category (relation)
│ ├── tags (relation, many-to-many)
│ ├── status (draft/published/archived)
│ ├── published_at
│ ├── meta_title
│ ├── meta_description
│ ├── og_image
│ ├── views_count
│ └── reading_time
│
├── blog_categories
│ ├── id
│ ├── name
│ ├── slug
│ ├── description
│ └── color
│
├── blog_tags
│ ├── id
│ ├── name
│ ├── slug
│ └── usage_count
│
└── blog_comments (optional)
├── id
├── post_id (relation)
├── user_id (relation)
├── content
├── is_approved
└── parent_id (für Antworten)
Routes-Struktur
src/routes/
├── blog/
│ ├── +page.svelte # Blog-Übersicht
│ ├── +page.server.ts # Blog-Liste laden
│ ├── [slug]/
│ │ ├── +page.svelte # Einzelner Artikel
│ │ └── +page.server.ts # Artikel + Kommentare laden
│ ├── category/[category]/
│ │ ├── +page.svelte # Kategorie-Ansicht
│ │ └── +page.server.ts
│ └── tag/[tag]/
│ ├── +page.svelte # Tag-Ansicht
│ └── +page.server.ts
│
└── (app)/admin/blog/ # Admin-Bereich
├── +page.svelte # Artikel-Liste
├── +page.server.ts
├── new/
│ ├── +page.svelte # Neuer Artikel
│ └── +page.server.ts
└── [id]/edit/
├── +page.svelte # Artikel bearbeiten
└── +page.server.ts
Vorteile
- ✅ Nahtlose Integration in bestehendes System
- ✅ Nutzt vorhandene Auth & User-System
- ✅ Einheitliche Datenbank
- ✅ Einfaches Backup & Migration
- ✅ DSGVO-konform mit einem System
- ✅ Kein zusätzlicher Service
Nachteile
- ❌ Entwicklungsaufwand für Editor
- ❌ Keine vorgefertigten Blog-Features
Implementierungszeit
- Basis-Version: 2-3 Tage
- Vollversion mit Editor: 5-7 Tage
Option 2: Markdown-basiertes System (Static/MDX)
Konzept
Blog-Artikel als Markdown-Dateien im Repository, Build-Zeit-Rendering.
Struktur
src/content/blog/
├── 2024-01-15-psychologie-kurzer-urls.md
├── 2024-01-20-link-tracking-guide.md
└── _drafts/
└── upcoming-post.md
# Frontmatter Example:
---
title: "Die Psychologie kurzer URLs"
excerpt: "Warum 42% weniger Klicks..."
author: "Till Schneider"
date: "2024-01-15"
category: "Psychology"
tags: ["urls", "psychology", "conversion"]
image: "/blog/images/psychology-urls.jpg"
---
Vorteile
- ✅ Versionskontrolle via Git
- ✅ Kein CMS/Datenbank nötig
- ✅ Sehr schnelle Ladezeiten
- ✅ Einfache Markdown-Bearbeitung
- ✅ Perfekt für technische Autoren
Nachteile
- ❌ Keine dynamischen Features (Kommentare, Likes)
- ❌ Deployment nötig für neue Posts
- ❌ Keine nicht-technischen Autoren
Tools
- mdsvex für Markdown-Processing
- rehype/remark für Erweiterungen
- Shiki für Syntax-Highlighting
Implementierungszeit
- 1-2 Tage
Option 3: Headless CMS Integration
Konzept
Externes CMS für Content-Management, SvelteKit als Frontend.
Empfohlene Services
3a. Strapi (Self-hosted)
// Integration via REST API
const posts = await fetch('https://cms.ulo.ad/api/posts?populate=*');
- ✅ Open Source
- ✅ Volle Kontrolle
- ✅ Rich Editor
- ❌ Hosting-Aufwand
3b. Directus (Self-hosted)
- ✅ Bessere UI als Strapi
- ✅ GraphQL Support
- ✅ Sehr flexibel
3c. Contentful (SaaS)
- ✅ Professionelles CMS
- ✅ Kein Hosting
- ❌ Kosten bei Skalierung
- ❌ Vendor Lock-in
Implementierungszeit
- 3-4 Tage (mit Setup)
Option 4: Hybrid-Lösung (MDX + PocketBase)
Konzept
Artikel als MDX-Dateien, Metadaten und Interaktionen in PocketBase.
Workflow
- Artikel schreiben in MDX
- Build-Process liest MDX
- Metadaten → PocketBase
- Kommentare/Likes → PocketBase
- Analytics → PocketBase
Vorteile
- ✅ Beste aus beiden Welten
- ✅ Git-Versionierung für Content
- ✅ Dynamische Features möglich
- ✅ Optimale Performance
Implementierungszeit
- 3-4 Tage
Option 5: Notion als CMS
Konzept
Notion-API als Content-Source, Cache in PocketBase.
// Notion API Integration
import { Client } from '@notionhq/client';
const notion = new Client({ auth: process.env.NOTION_KEY });
const posts = await notion.databases.query({
database_id: BLOG_DATABASE_ID
});
Vorteile
- ✅ Fantastischer Editor
- ✅ Team-Kollaboration
- ✅ Keine Entwicklung nötig
Nachteile
- ❌ API-Limits
- ❌ Abhängigkeit von Notion
- ❌ Performance (ohne Caching)
Implementierungszeit
- 2 Tage
Empfehlung & Begründung
🏆 Primär: Option 1 (PocketBase-Integration)
Warum:
- Konsistenz: Ein System für alles
- Kontrolle: Volle Datenhoheit
- Performance: Keine externen API-Calls
- Features: Alle dynamischen Features möglich
- Skalierbar: Wächst mit dem Projekt
🥈 Alternative: Option 4 (Hybrid MDX + PocketBase)
Wann sinnvoll:
- Wenn Git-basierter Workflow gewünscht
- Wenn mehrere technische Autoren
- Wenn Version Control wichtig
Implementierungsplan für Option 1
Phase 1: Datenbank-Setup (Tag 1)
# Collections erstellen
- blog_posts
- blog_categories
- blog_tags
- blog_post_tags (junction table)
Phase 2: API & Server-Routes (Tag 1-2)
// +page.server.ts Beispiele
- GET /blog - Liste mit Pagination
- GET /blog/[slug] - Einzelartikel
- POST /blog/[slug]/view - View counter
- GET /blog/feed.xml - RSS Feed
Phase 3: Frontend-Komponenten (Tag 2-3)
<!-- Komponenten -->
- BlogCard.svelte
- BlogPost.svelte
- BlogSidebar.svelte
- ShareButtons.svelte
- ReadingProgress.svelte
- TableOfContents.svelte
Phase 4: Admin-Interface (Tag 3-4)
<!-- Admin-Bereich -->
- PostEditor.svelte (mit Tiptap/ProseMirror)
- MediaUpload.svelte
- SEOSettings.svelte
- PublishSettings.svelte
Phase 5: Features & Optimierung (Tag 4-5)
- SEO-Optimierung
- Social Media Cards
- RSS/Atom Feed
- Sitemap-Integration
- Search-Funktion
- Related Posts
- Newsletter-Integration
Phase 6: Analytics & Performance (Tag 5)
- View-Tracking
- Reading-Time
- Scroll-Tracking
- Performance-Optimierung
- Image-Lazy-Loading
Technische Details für Implementation
Rich-Text Editor Optionen
- Tiptap (Empfohlen)
<script>
import { Editor } from '@tiptap/core';
import StarterKit from '@tiptap/starter-kit';
const editor = new Editor({
extensions: [StarterKit],
content: post.content
});
</script>
- Lexical (Facebook)
- ProseMirror (Low-Level)
- SimpleMDE (Markdown)
SEO-Optimierung
<!-- +page.svelte -->
<svelte:head>
<title>{post.meta_title || post.title}</title>
<meta name="description" content={post.meta_description} />
<!-- Open Graph -->
<meta property="og:title" content={post.title} />
<meta property="og:description" content={post.excerpt} />
<meta property="og:image" content={post.og_image} />
<!-- Schema.org -->
<script type="application/ld+json">
{JSON.stringify({
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": post.title,
"datePublished": post.published_at,
"author": {
"@type": "Person",
"name": post.author.name
}
})}
</script>
</svelte:head>
Performance-Optimierung
// Image optimization
import { imagetools } from 'vite-imagetools';
// Lazy loading
import { inview } from 'svelte-inview';
// Content caching
const CACHE_DURATION = 60 * 5; // 5 Minuten
// Reading time calculation
function calculateReadingTime(content: string): number {
const wordsPerMinute = 200;
const words = content.split(/\s+/).length;
return Math.ceil(words / wordsPerMinute);
}
Migrations-Strategie
Falls später ein Wechsel nötig:
- Export-Funktion in PocketBase
- Standard-Format (JSON/Markdown)
- Import-Scripts vorbereiten
- URL-Redirects einrichten
Kosten-Nutzen-Analyse
Option 1 (PocketBase)
- Kosten: 5-7 Tage Entwicklung
- Nutzen: Vollständige Integration, keine laufenden Kosten
- ROI: Hoch
Option 2 (Markdown)
- Kosten: 1-2 Tage Entwicklung
- Nutzen: Einfach, schnell
- ROI: Mittel
Option 3 (Headless CMS)
- Kosten: 3-4 Tage + laufende Kosten
- Nutzen: Professionelles CMS
- ROI: Mittel
Nächste Schritte
- Entscheidung für einen Ansatz
- Prototyp erstellen (1 Tag)
- Feedback einholen
- Vollständige Implementation
- Content-Migration (falls vorhanden)
- Launch mit 3-5 Artikeln
Beispiel-Implementation starten
# Für Option 1 (PocketBase):
npm run dev:all # Backend + Frontend starten
# Collections via MCP erstellen
# oder via PocketBase Admin UI
# Routes erstellen
mkdir -p src/routes/blog
touch src/routes/blog/+page.svelte
touch src/routes/blog/+page.server.ts
# Komponenten
mkdir -p src/lib/components/blog
touch src/lib/components/blog/BlogCard.svelte
Empfehlung: Starten Sie mit Option 1 (PocketBase-Integration) als MVP und erweitern Sie schrittweise. Dies gibt Ihnen maximale Flexibilität bei minimalem initialen Aufwand.