refactor: Consolidate standalone services into admin-v2, add new SDK modules
Remove standalone services (ai-compliance-sdk root, developer-portal, dsms-gateway, dsms-node, night-scheduler) and legacy compliance/dsgvo pages. Add new SDK pipeline modules (academy, document-crawler, dsb-portal, incidents, whistleblower, reporting, sso, multi-tenant, industry-templates). Add drafting engine, legal corpus files (AT/CH/DE), pitch-deck, blog and Förderantrag pages. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
67
pitch-deck/lib/animations.ts
Normal file
67
pitch-deck/lib/animations.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
export const fadeIn = {
|
||||
initial: { opacity: 0 },
|
||||
animate: { opacity: 1 },
|
||||
exit: { opacity: 0 },
|
||||
transition: { duration: 0.5 },
|
||||
}
|
||||
|
||||
export const fadeInUp = {
|
||||
initial: { opacity: 0, y: 40 },
|
||||
animate: { opacity: 1, y: 0 },
|
||||
exit: { opacity: 0, y: -20 },
|
||||
transition: { duration: 0.6, ease: [0.22, 1, 0.36, 1] },
|
||||
}
|
||||
|
||||
export const fadeInDown = {
|
||||
initial: { opacity: 0, y: -40 },
|
||||
animate: { opacity: 1, y: 0 },
|
||||
transition: { duration: 0.6, ease: [0.22, 1, 0.36, 1] },
|
||||
}
|
||||
|
||||
export const fadeInLeft = {
|
||||
initial: { opacity: 0, x: -60 },
|
||||
animate: { opacity: 1, x: 0 },
|
||||
transition: { duration: 0.6, ease: [0.22, 1, 0.36, 1] },
|
||||
}
|
||||
|
||||
export const fadeInRight = {
|
||||
initial: { opacity: 0, x: 60 },
|
||||
animate: { opacity: 1, x: 0 },
|
||||
transition: { duration: 0.6, ease: [0.22, 1, 0.36, 1] },
|
||||
}
|
||||
|
||||
export const scaleIn = {
|
||||
initial: { opacity: 0, scale: 0.8 },
|
||||
animate: { opacity: 1, scale: 1 },
|
||||
transition: { duration: 0.5, ease: [0.22, 1, 0.36, 1] },
|
||||
}
|
||||
|
||||
export const slideVariants = {
|
||||
enter: (direction: number) => ({
|
||||
x: direction > 0 ? '100%' : '-100%',
|
||||
opacity: 0,
|
||||
}),
|
||||
center: {
|
||||
x: 0,
|
||||
opacity: 1,
|
||||
},
|
||||
exit: (direction: number) => ({
|
||||
x: direction < 0 ? '100%' : '-100%',
|
||||
opacity: 0,
|
||||
}),
|
||||
}
|
||||
|
||||
export const staggerContainer = {
|
||||
animate: {
|
||||
transition: {
|
||||
staggerChildren: 0.1,
|
||||
delayChildren: 0.2,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export const staggerItem = {
|
||||
initial: { opacity: 0, y: 20 },
|
||||
animate: { opacity: 1, y: 0 },
|
||||
transition: { duration: 0.5 },
|
||||
}
|
||||
10
pitch-deck/lib/db.ts
Normal file
10
pitch-deck/lib/db.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Pool } from 'pg'
|
||||
|
||||
const pool = new Pool({
|
||||
connectionString: process.env.DATABASE_URL || 'postgres://breakpilot:breakpilot123@localhost:5432/breakpilot_db',
|
||||
max: 5,
|
||||
idleTimeoutMillis: 30000,
|
||||
connectionTimeoutMillis: 5000,
|
||||
})
|
||||
|
||||
export default pool
|
||||
109
pitch-deck/lib/hooks/useFinancialModel.ts
Normal file
109
pitch-deck/lib/hooks/useFinancialModel.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useEffect, useCallback, useRef } from 'react'
|
||||
import { FMScenario, FMResult, FMComputeResponse } from '../types'
|
||||
|
||||
export function useFinancialModel() {
|
||||
const [scenarios, setScenarios] = useState<FMScenario[]>([])
|
||||
const [activeScenarioId, setActiveScenarioId] = useState<string | null>(null)
|
||||
const [compareMode, setCompareMode] = useState(false)
|
||||
const [results, setResults] = useState<Map<string, FMComputeResponse>>(new Map())
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [computing, setComputing] = useState(false)
|
||||
const computeTimer = useRef<NodeJS.Timeout | null>(null)
|
||||
|
||||
// Load scenarios on mount
|
||||
useEffect(() => {
|
||||
async function load() {
|
||||
try {
|
||||
const res = await fetch('/api/financial-model')
|
||||
if (res.ok) {
|
||||
const data: FMScenario[] = await res.json()
|
||||
setScenarios(data)
|
||||
const defaultScenario = data.find(s => s.is_default) || data[0]
|
||||
if (defaultScenario) {
|
||||
setActiveScenarioId(defaultScenario.id)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to load financial model:', err)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
load()
|
||||
}, [])
|
||||
|
||||
// Compute when active scenario changes
|
||||
useEffect(() => {
|
||||
if (activeScenarioId && !results.has(activeScenarioId)) {
|
||||
compute(activeScenarioId)
|
||||
}
|
||||
}, [activeScenarioId]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
const compute = useCallback(async (scenarioId: string) => {
|
||||
setComputing(true)
|
||||
try {
|
||||
const res = await fetch('/api/financial-model/compute', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ scenarioId }),
|
||||
})
|
||||
if (res.ok) {
|
||||
const data: FMComputeResponse = await res.json()
|
||||
setResults(prev => new Map(prev).set(scenarioId, data))
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Compute failed:', err)
|
||||
} finally {
|
||||
setComputing(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const updateAssumption = useCallback(async (scenarioId: string, key: string, value: number | number[]) => {
|
||||
// Optimistic update in local state
|
||||
setScenarios(prev => prev.map(s => {
|
||||
if (s.id !== scenarioId) return s
|
||||
return {
|
||||
...s,
|
||||
assumptions: s.assumptions.map(a => a.key === key ? { ...a, value } : a),
|
||||
}
|
||||
}))
|
||||
|
||||
// Save to DB
|
||||
await fetch('/api/financial-model/assumptions', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ scenarioId, key, value }),
|
||||
})
|
||||
|
||||
// Debounced recompute
|
||||
if (computeTimer.current) clearTimeout(computeTimer.current)
|
||||
computeTimer.current = setTimeout(() => compute(scenarioId), 300)
|
||||
}, [compute])
|
||||
|
||||
const computeAll = useCallback(async () => {
|
||||
for (const s of scenarios) {
|
||||
await compute(s.id)
|
||||
}
|
||||
}, [scenarios, compute])
|
||||
|
||||
const activeScenario = scenarios.find(s => s.id === activeScenarioId) || null
|
||||
const activeResults = activeScenarioId ? results.get(activeScenarioId) || null : null
|
||||
|
||||
return {
|
||||
scenarios,
|
||||
activeScenario,
|
||||
activeScenarioId,
|
||||
setActiveScenarioId,
|
||||
activeResults,
|
||||
results,
|
||||
loading,
|
||||
computing,
|
||||
compareMode,
|
||||
setCompareMode,
|
||||
compute,
|
||||
computeAll,
|
||||
updateAssumption,
|
||||
}
|
||||
}
|
||||
98
pitch-deck/lib/hooks/useKeyboard.ts
Normal file
98
pitch-deck/lib/hooks/useKeyboard.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useCallback } from 'react'
|
||||
|
||||
interface UseKeyboardProps {
|
||||
onNext: () => void
|
||||
onPrev: () => void
|
||||
onFirst: () => void
|
||||
onLast: () => void
|
||||
onOverview: () => void
|
||||
onFullscreen: () => void
|
||||
onLanguageToggle: () => void
|
||||
onMenuToggle: () => void
|
||||
onGoToSlide: (index: number) => void
|
||||
enabled?: boolean
|
||||
}
|
||||
|
||||
export function useKeyboard({
|
||||
onNext,
|
||||
onPrev,
|
||||
onFirst,
|
||||
onLast,
|
||||
onOverview,
|
||||
onFullscreen,
|
||||
onLanguageToggle,
|
||||
onMenuToggle,
|
||||
onGoToSlide,
|
||||
enabled = true,
|
||||
}: UseKeyboardProps) {
|
||||
const handleKeyDown = useCallback(
|
||||
(e: KeyboardEvent) => {
|
||||
if (!enabled) return
|
||||
|
||||
const target = e.target as HTMLElement
|
||||
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {
|
||||
return
|
||||
}
|
||||
|
||||
switch (e.key) {
|
||||
case 'ArrowRight':
|
||||
case ' ':
|
||||
case 'Enter':
|
||||
e.preventDefault()
|
||||
onNext()
|
||||
break
|
||||
case 'ArrowLeft':
|
||||
e.preventDefault()
|
||||
onPrev()
|
||||
break
|
||||
case 'Escape':
|
||||
e.preventDefault()
|
||||
onOverview()
|
||||
break
|
||||
case 'f':
|
||||
case 'F':
|
||||
e.preventDefault()
|
||||
onFullscreen()
|
||||
break
|
||||
case 'Home':
|
||||
e.preventDefault()
|
||||
onFirst()
|
||||
break
|
||||
case 'End':
|
||||
e.preventDefault()
|
||||
onLast()
|
||||
break
|
||||
case 'l':
|
||||
case 'L':
|
||||
e.preventDefault()
|
||||
onLanguageToggle()
|
||||
break
|
||||
case 'm':
|
||||
case 'M':
|
||||
e.preventDefault()
|
||||
onMenuToggle()
|
||||
break
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
e.preventDefault()
|
||||
onGoToSlide(parseInt(e.key) - 1)
|
||||
break
|
||||
}
|
||||
},
|
||||
[enabled, onNext, onPrev, onFirst, onLast, onOverview, onFullscreen, onLanguageToggle, onMenuToggle, onGoToSlide]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('keydown', handleKeyDown)
|
||||
return () => window.removeEventListener('keydown', handleKeyDown)
|
||||
}, [handleKeyDown])
|
||||
}
|
||||
39
pitch-deck/lib/hooks/useLanguage.ts
Normal file
39
pitch-deck/lib/hooks/useLanguage.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
'use client'
|
||||
|
||||
import { createContext, useContext, useState, useCallback, ReactNode } from 'react'
|
||||
import { Language } from '../types'
|
||||
import React from 'react'
|
||||
|
||||
interface LanguageContextType {
|
||||
lang: Language
|
||||
toggleLanguage: () => void
|
||||
setLanguage: (lang: Language) => void
|
||||
}
|
||||
|
||||
const LanguageContext = createContext<LanguageContextType>({
|
||||
lang: 'de',
|
||||
toggleLanguage: () => {},
|
||||
setLanguage: () => {},
|
||||
})
|
||||
|
||||
export function LanguageProvider({ children }: { children: ReactNode }) {
|
||||
const [lang, setLang] = useState<Language>('de')
|
||||
|
||||
const toggleLanguage = useCallback(() => {
|
||||
setLang(prev => prev === 'de' ? 'en' : 'de')
|
||||
}, [])
|
||||
|
||||
const setLanguage = useCallback((newLang: Language) => {
|
||||
setLang(newLang)
|
||||
}, [])
|
||||
|
||||
return React.createElement(
|
||||
LanguageContext.Provider,
|
||||
{ value: { lang, toggleLanguage, setLanguage } },
|
||||
children
|
||||
)
|
||||
}
|
||||
|
||||
export function useLanguage() {
|
||||
return useContext(LanguageContext)
|
||||
}
|
||||
29
pitch-deck/lib/hooks/usePitchData.ts
Normal file
29
pitch-deck/lib/hooks/usePitchData.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useEffect } from 'react'
|
||||
import { PitchData } from '../types'
|
||||
|
||||
export function usePitchData() {
|
||||
const [data, setData] = useState<PitchData | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchData() {
|
||||
try {
|
||||
const res = await fetch('/api/data')
|
||||
if (!res.ok) throw new Error(`HTTP ${res.status}`)
|
||||
const json = await res.json()
|
||||
setData(json)
|
||||
} catch (err) {
|
||||
console.error('Failed to load pitch data:', err)
|
||||
setError(err instanceof Error ? err.message : 'Unknown error')
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
fetchData()
|
||||
}, [])
|
||||
|
||||
return { data, loading, error }
|
||||
}
|
||||
92
pitch-deck/lib/hooks/useSlideNavigation.ts
Normal file
92
pitch-deck/lib/hooks/useSlideNavigation.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useCallback } from 'react'
|
||||
import { SlideId } from '../types'
|
||||
|
||||
const SLIDE_ORDER: SlideId[] = [
|
||||
'cover',
|
||||
'problem',
|
||||
'solution',
|
||||
'product',
|
||||
'how-it-works',
|
||||
'market',
|
||||
'business-model',
|
||||
'traction',
|
||||
'competition',
|
||||
'team',
|
||||
'technology',
|
||||
'financials',
|
||||
'the-ask',
|
||||
'ai-qa',
|
||||
'appendix',
|
||||
'annex-infra',
|
||||
'annex-ai-stack',
|
||||
'annex-rag',
|
||||
'annex-security',
|
||||
'annex-devops',
|
||||
'annex-agent-arch',
|
||||
'annex-agent-rag',
|
||||
'annex-agent-workflow',
|
||||
'annex-usp-overview',
|
||||
'annex-usp-comparison',
|
||||
'annex-usp-moat',
|
||||
'annex-roadmap-2027',
|
||||
'annex-roadmap-2028',
|
||||
]
|
||||
|
||||
export const TOTAL_SLIDES = SLIDE_ORDER.length
|
||||
|
||||
export function useSlideNavigation() {
|
||||
const [currentIndex, setCurrentIndex] = useState(0)
|
||||
const [direction, setDirection] = useState(0)
|
||||
const [visitedSlides, setVisitedSlides] = useState<Set<number>>(new Set([0]))
|
||||
const [showOverview, setShowOverview] = useState(false)
|
||||
|
||||
const currentSlide = SLIDE_ORDER[currentIndex]
|
||||
|
||||
const goToSlide = useCallback((index: number) => {
|
||||
if (index < 0 || index >= TOTAL_SLIDES) return
|
||||
setDirection(index > currentIndex ? 1 : -1)
|
||||
setCurrentIndex(index)
|
||||
setVisitedSlides(prev => new Set([...prev, index]))
|
||||
setShowOverview(false)
|
||||
}, [currentIndex])
|
||||
|
||||
const nextSlide = useCallback(() => {
|
||||
if (currentIndex < TOTAL_SLIDES - 1) {
|
||||
goToSlide(currentIndex + 1)
|
||||
}
|
||||
}, [currentIndex, goToSlide])
|
||||
|
||||
const prevSlide = useCallback(() => {
|
||||
if (currentIndex > 0) {
|
||||
goToSlide(currentIndex - 1)
|
||||
}
|
||||
}, [currentIndex, goToSlide])
|
||||
|
||||
const goToFirst = useCallback(() => goToSlide(0), [goToSlide])
|
||||
const goToLast = useCallback(() => goToSlide(TOTAL_SLIDES - 1), [goToSlide])
|
||||
|
||||
const toggleOverview = useCallback(() => {
|
||||
setShowOverview(prev => !prev)
|
||||
}, [])
|
||||
|
||||
return {
|
||||
currentIndex,
|
||||
currentSlide,
|
||||
direction,
|
||||
visitedSlides,
|
||||
showOverview,
|
||||
totalSlides: TOTAL_SLIDES,
|
||||
slideOrder: SLIDE_ORDER,
|
||||
goToSlide,
|
||||
nextSlide,
|
||||
prevSlide,
|
||||
goToFirst,
|
||||
goToLast,
|
||||
toggleOverview,
|
||||
setShowOverview,
|
||||
isFirst: currentIndex === 0,
|
||||
isLast: currentIndex === TOTAL_SLIDES - 1,
|
||||
}
|
||||
}
|
||||
522
pitch-deck/lib/i18n.ts
Normal file
522
pitch-deck/lib/i18n.ts
Normal file
@@ -0,0 +1,522 @@
|
||||
import { Language } from './types'
|
||||
|
||||
const translations = {
|
||||
de: {
|
||||
nav: {
|
||||
slides: 'Slides',
|
||||
fullscreen: 'Vollbild',
|
||||
language: 'Sprache',
|
||||
},
|
||||
slideNames: [
|
||||
'Cover',
|
||||
'Das Problem',
|
||||
'Die Loesung',
|
||||
'Produkte',
|
||||
'So funktioniert\'s',
|
||||
'Markt',
|
||||
'Geschaeftsmodell',
|
||||
'Traction',
|
||||
'Wettbewerb',
|
||||
'Team',
|
||||
'Technologie',
|
||||
'Finanzen',
|
||||
'The Ask',
|
||||
'KI Q&A',
|
||||
'Appendix',
|
||||
'Infrastruktur',
|
||||
'KI-Stack',
|
||||
'RAG Pipeline',
|
||||
'Sicherheit',
|
||||
'DevOps & CI/CD',
|
||||
'Agent Architektur',
|
||||
'Rechtsdokumente',
|
||||
'Compliance Workflow',
|
||||
'5 USPs',
|
||||
'Wettbewerbsvergleich',
|
||||
'Marktposition',
|
||||
'Roadmap 2027',
|
||||
'Roadmap 2028',
|
||||
],
|
||||
cover: {
|
||||
tagline: 'Datensouveraenitaet meets KI-Compliance',
|
||||
subtitle: 'Seed · 2026-2027',
|
||||
cta: 'Pitch starten',
|
||||
},
|
||||
problem: {
|
||||
title: 'Das Problem',
|
||||
subtitle: 'Compliance-Komplexitaet ueberfordert den Mittelstand',
|
||||
cards: [
|
||||
{
|
||||
title: 'DSGVO',
|
||||
stat: '4.1 Mrd EUR',
|
||||
desc: 'Bussgelder seit 2018 in der EU. 83% der KMUs sind nicht vollstaendig konform.',
|
||||
},
|
||||
{
|
||||
title: 'AI Act',
|
||||
stat: 'Aug 2025',
|
||||
desc: 'Neue EU-Verordnung tritt in Kraft. Unternehmen muessen KI-Systeme klassifizieren und dokumentieren.',
|
||||
},
|
||||
{
|
||||
title: 'NIS2',
|
||||
stat: '30.000+',
|
||||
desc: 'Unternehmen in Deutschland neu betroffen. Cybersecurity-Anforderungen steigen massiv.',
|
||||
},
|
||||
],
|
||||
quote: 'Unternehmen brauchen keine weiteren Compliance-Tools — sie brauchen eine KI, die Compliance fuer sie erledigt.',
|
||||
},
|
||||
solution: {
|
||||
title: 'Die Loesung',
|
||||
subtitle: 'ComplAI — Compliance auf Autopilot',
|
||||
pillars: [
|
||||
{
|
||||
title: 'Self-Hosted',
|
||||
desc: 'Eigene Hardware im Serverraum. Kein Byte verlaesst das Unternehmen. Volle Datensouveraenitaet.',
|
||||
icon: 'server',
|
||||
},
|
||||
{
|
||||
title: 'Auto-Compliance',
|
||||
desc: 'KI erledigt DSGVO, AI Act und NIS2 automatisch. Dokumentation, Audits und Updates — alles KI-gesteuert.',
|
||||
icon: 'shield',
|
||||
},
|
||||
{
|
||||
title: 'KI-Assistent',
|
||||
desc: 'Vollautonomer Kundensupport. Beantwortet Fragen, aendert Dokumente, bereitet Audits vor — 24/7.',
|
||||
icon: 'bot',
|
||||
},
|
||||
],
|
||||
},
|
||||
product: {
|
||||
title: 'Unsere Produkte',
|
||||
subtitle: 'Drei Tiers fuer jede Unternehmensgroesse',
|
||||
monthly: '/Monat',
|
||||
hardware: 'Hardware',
|
||||
llm: 'KI-Modell',
|
||||
popular: 'Beliebt',
|
||||
features: 'Features',
|
||||
},
|
||||
howItWorks: {
|
||||
title: 'So funktioniert\'s',
|
||||
subtitle: 'In 4 Schritten zur vollstaendigen Compliance',
|
||||
steps: [
|
||||
{
|
||||
title: 'Hardware aufstellen',
|
||||
desc: 'Mac Mini oder Mac Studio im Serverraum anschliessen. Plug & Play — keine Cloud noetig.',
|
||||
},
|
||||
{
|
||||
title: 'KI konfigurieren',
|
||||
desc: 'Branche, Groesse und Regularien angeben. Die KI erstellt automatisch alle Compliance-Dokumente.',
|
||||
},
|
||||
{
|
||||
title: 'Compliance automatisieren',
|
||||
desc: 'Laufende Ueberwachung, automatische Updates bei Rechtsaenderungen und Audit-Vorbereitung.',
|
||||
},
|
||||
{
|
||||
title: 'Audit bestehen',
|
||||
desc: 'Vollstaendige Dokumentation auf Knopfdruck. Behoerdenanfragen werden KI-gestuetzt beantwortet.',
|
||||
},
|
||||
],
|
||||
},
|
||||
market: {
|
||||
title: 'Marktchance',
|
||||
subtitle: 'Der Compliance-Markt waechst zweistellig',
|
||||
tam: 'TAM',
|
||||
sam: 'SAM',
|
||||
som: 'SOM',
|
||||
tamLabel: 'Total Addressable Market',
|
||||
samLabel: 'Serviceable Addressable Market',
|
||||
somLabel: 'Serviceable Obtainable Market',
|
||||
source: 'Quelle',
|
||||
growth: 'Wachstum p.a.',
|
||||
},
|
||||
businessModel: {
|
||||
title: 'Geschaeftsmodell',
|
||||
subtitle: 'Recurring Revenue mit Hardware-Moat',
|
||||
unitEconomics: 'Unit Economics',
|
||||
amortization: 'Amortisation',
|
||||
margin: 'Marge',
|
||||
months: 'Monate',
|
||||
recurringRevenue: 'Recurring Revenue',
|
||||
hardwareCost: 'Hardware-EK',
|
||||
operatingCost: 'Betriebskosten',
|
||||
},
|
||||
traction: {
|
||||
title: 'Traction & Meilensteine',
|
||||
subtitle: 'Unser bisheriger Fortschritt',
|
||||
completed: 'Abgeschlossen',
|
||||
inProgress: 'In Arbeit',
|
||||
planned: 'Geplant',
|
||||
},
|
||||
competition: {
|
||||
title: 'Wettbewerb',
|
||||
subtitle: 'Was uns differenziert',
|
||||
feature: 'Feature',
|
||||
selfHosted: 'Self-Hosted',
|
||||
integratedAI: 'Integrierte KI',
|
||||
autonomousSupport: 'Autonomer Support',
|
||||
yes: 'Ja',
|
||||
no: 'Nein',
|
||||
partial: 'Teilweise',
|
||||
},
|
||||
team: {
|
||||
title: 'Das Team',
|
||||
subtitle: 'Gruender mit Domain-Expertise',
|
||||
equity: 'Equity',
|
||||
expertise: 'Expertise',
|
||||
},
|
||||
technology: {
|
||||
title: 'Technologie-Roadmap',
|
||||
subtitle: 'Von MVP zu Full Autonomy — 5-Jahres-Technologieplan',
|
||||
timelineTitle: 'Meilensteine 2026-2030',
|
||||
stackTitle: 'Tech-Stack',
|
||||
phases: [
|
||||
{
|
||||
year: '2026',
|
||||
phase: 'Foundation & MVP',
|
||||
techs: ['Self-Hosted LLM (32B)', 'Apple M2 Mini', 'Basic Compliance SDK', 'OCR Pipeline'],
|
||||
},
|
||||
{
|
||||
year: '2027',
|
||||
phase: 'Product-Market Fit',
|
||||
techs: ['Multi-Model Router', 'RAG 2.0 mit Qdrant', 'Auto Compliance-Scan', 'Echtzeit-Monitoring'],
|
||||
},
|
||||
{
|
||||
year: '2028',
|
||||
phase: 'Enterprise Scale',
|
||||
techs: ['Federated Learning', 'Cluster-Management', 'API Marketplace', 'Multi-Tenant'],
|
||||
},
|
||||
{
|
||||
year: '2029',
|
||||
phase: 'AI Platform',
|
||||
techs: ['Custom Fine-Tuned (40B+)', 'Predictive Compliance', 'Auto-Audits', 'Partner-Integrationen'],
|
||||
},
|
||||
{
|
||||
year: '2030',
|
||||
phase: 'Full Autonomy',
|
||||
techs: ['Agent-Netzwerk', 'Self-Healing', 'Zero-Day Compliance', '1000B Parameter'],
|
||||
},
|
||||
],
|
||||
layers: [
|
||||
{ name: 'Application', techs: 'Next.js, React, TailwindCSS, REST/GraphQL API' },
|
||||
{ name: 'AI/ML', techs: 'Qwen 32B → 1000B, RAG Pipeline, NLP, OCR (PaddleOCR)' },
|
||||
{ name: 'Infrastructure', techs: 'Apple Silicon (M2/M4 Pro), Docker, Self-Hosted' },
|
||||
{ name: 'Security', techs: 'BSI-TR-03161, E2E Verschluesselung, Vault' },
|
||||
{ name: 'Data', techs: 'PostgreSQL + PostGIS, Qdrant (Vektoren), MinIO (S3)' },
|
||||
],
|
||||
},
|
||||
financials: {
|
||||
title: 'Finanzprognose',
|
||||
subtitle: 'AI-First Kostenstruktur — skaliert ohne lineares Personalwachstum',
|
||||
revenue: 'Umsatz',
|
||||
costs: 'Kosten',
|
||||
customers: 'Kunden',
|
||||
mrr: 'MRR',
|
||||
arr: 'ARR',
|
||||
burnRate: 'Burn Rate',
|
||||
employees: 'Mitarbeiter',
|
||||
year: 'Jahr',
|
||||
sliderGrowth: 'Wachstumsrate',
|
||||
sliderChurn: 'Churn Rate',
|
||||
sliderArpu: 'ARPU',
|
||||
adjustAssumptions: 'Annahmen anpassen',
|
||||
},
|
||||
theAsk: {
|
||||
title: 'The Ask',
|
||||
subtitle: 'Gestaffelte Finanzierung 2026-2027',
|
||||
amount: 'Funding',
|
||||
instrument: 'Instrument',
|
||||
useOfFunds: 'Use of Funds',
|
||||
engineering: 'Engineering',
|
||||
sales: 'Vertrieb',
|
||||
hardware: 'Hardware',
|
||||
personnel: 'Personal',
|
||||
legal: 'Legal',
|
||||
reserve: 'Reserve',
|
||||
targetDate: 'Zeitraum',
|
||||
},
|
||||
aiqa: {
|
||||
title: 'Fragen? Die KI antwortet.',
|
||||
subtitle: 'Stellen Sie Ihre Investorenfragen — unser AI Agent antwortet mit Echtdaten.',
|
||||
placeholder: 'Stellen Sie eine Frage zum Investment...',
|
||||
send: 'Senden',
|
||||
thinking: 'Denke nach...',
|
||||
suggestions: [
|
||||
'Wie skaliert das Geschaeftsmodell?',
|
||||
'Was ist der unfaire Vorteil?',
|
||||
'Wie sieht die Exit-Strategie aus?',
|
||||
'Warum Self-Hosting statt Cloud?',
|
||||
],
|
||||
},
|
||||
},
|
||||
en: {
|
||||
nav: {
|
||||
slides: 'Slides',
|
||||
fullscreen: 'Fullscreen',
|
||||
language: 'Language',
|
||||
},
|
||||
slideNames: [
|
||||
'Cover',
|
||||
'The Problem',
|
||||
'The Solution',
|
||||
'Products',
|
||||
'How It Works',
|
||||
'Market',
|
||||
'Business Model',
|
||||
'Traction',
|
||||
'Competition',
|
||||
'Team',
|
||||
'Technology',
|
||||
'Financials',
|
||||
'The Ask',
|
||||
'AI Q&A',
|
||||
'Appendix',
|
||||
'Infrastructure',
|
||||
'AI Stack',
|
||||
'RAG Pipeline',
|
||||
'Security',
|
||||
'DevOps & CI/CD',
|
||||
'Agent Architecture',
|
||||
'Legal Documents',
|
||||
'Compliance Workflow',
|
||||
'5 USPs',
|
||||
'Competitor Comparison',
|
||||
'Market Position',
|
||||
'Roadmap 2027',
|
||||
'Roadmap 2028',
|
||||
],
|
||||
cover: {
|
||||
tagline: 'Data Sovereignty meets AI Compliance',
|
||||
subtitle: 'Seed · 2026-2027',
|
||||
cta: 'Start Pitch',
|
||||
},
|
||||
problem: {
|
||||
title: 'The Problem',
|
||||
subtitle: 'Compliance complexity overwhelms SMEs',
|
||||
cards: [
|
||||
{
|
||||
title: 'GDPR',
|
||||
stat: 'EUR 4.1B',
|
||||
desc: 'in fines since 2018 across the EU. 83% of SMEs are not fully compliant.',
|
||||
},
|
||||
{
|
||||
title: 'AI Act',
|
||||
stat: 'Aug 2025',
|
||||
desc: 'New EU regulation takes effect. Companies must classify and document AI systems.',
|
||||
},
|
||||
{
|
||||
title: 'NIS2',
|
||||
stat: '30,000+',
|
||||
desc: 'companies newly affected in Germany. Cybersecurity requirements increase massively.',
|
||||
},
|
||||
],
|
||||
quote: 'Companies don\'t need more compliance tools — they need an AI that handles compliance for them.',
|
||||
},
|
||||
solution: {
|
||||
title: 'The Solution',
|
||||
subtitle: 'ComplAI — Compliance on Autopilot',
|
||||
pillars: [
|
||||
{
|
||||
title: 'Self-Hosted',
|
||||
desc: 'Own hardware in your server room. No data leaves the company. Full data sovereignty.',
|
||||
icon: 'server',
|
||||
},
|
||||
{
|
||||
title: 'Auto-Compliance',
|
||||
desc: 'AI handles GDPR, AI Act and NIS2 automatically. Documentation, audits and updates — all AI-powered.',
|
||||
icon: 'shield',
|
||||
},
|
||||
{
|
||||
title: 'AI Assistant',
|
||||
desc: 'Fully autonomous customer support. Answers questions, modifies documents, prepares audits — 24/7.',
|
||||
icon: 'bot',
|
||||
},
|
||||
],
|
||||
},
|
||||
product: {
|
||||
title: 'Our Products',
|
||||
subtitle: 'Three tiers for every company size',
|
||||
monthly: '/month',
|
||||
hardware: 'Hardware',
|
||||
llm: 'AI Model',
|
||||
popular: 'Popular',
|
||||
features: 'Features',
|
||||
},
|
||||
howItWorks: {
|
||||
title: 'How It Works',
|
||||
subtitle: 'Full compliance in 4 steps',
|
||||
steps: [
|
||||
{
|
||||
title: 'Set Up Hardware',
|
||||
desc: 'Connect Mac Mini or Mac Studio in your server room. Plug & Play — no cloud needed.',
|
||||
},
|
||||
{
|
||||
title: 'Configure AI',
|
||||
desc: 'Specify industry, size, and regulations. The AI automatically creates all compliance documents.',
|
||||
},
|
||||
{
|
||||
title: 'Automate Compliance',
|
||||
desc: 'Continuous monitoring, automatic updates for regulatory changes and audit preparation.',
|
||||
},
|
||||
{
|
||||
title: 'Pass Audits',
|
||||
desc: 'Complete documentation at the push of a button. Authority inquiries answered AI-powered.',
|
||||
},
|
||||
],
|
||||
},
|
||||
market: {
|
||||
title: 'Market Opportunity',
|
||||
subtitle: 'The compliance market grows double-digit',
|
||||
tam: 'TAM',
|
||||
sam: 'SAM',
|
||||
som: 'SOM',
|
||||
tamLabel: 'Total Addressable Market',
|
||||
samLabel: 'Serviceable Addressable Market',
|
||||
somLabel: 'Serviceable Obtainable Market',
|
||||
source: 'Source',
|
||||
growth: 'Growth p.a.',
|
||||
},
|
||||
businessModel: {
|
||||
title: 'Business Model',
|
||||
subtitle: 'Recurring Revenue with Hardware Moat',
|
||||
unitEconomics: 'Unit Economics',
|
||||
amortization: 'Amortization',
|
||||
margin: 'Margin',
|
||||
months: 'months',
|
||||
recurringRevenue: 'Recurring Revenue',
|
||||
hardwareCost: 'Hardware Cost',
|
||||
operatingCost: 'Operating Cost',
|
||||
},
|
||||
traction: {
|
||||
title: 'Traction & Milestones',
|
||||
subtitle: 'Our progress so far',
|
||||
completed: 'Completed',
|
||||
inProgress: 'In Progress',
|
||||
planned: 'Planned',
|
||||
},
|
||||
competition: {
|
||||
title: 'Competition',
|
||||
subtitle: 'What differentiates us',
|
||||
feature: 'Feature',
|
||||
selfHosted: 'Self-Hosted',
|
||||
integratedAI: 'Integrated AI',
|
||||
autonomousSupport: 'Autonomous Support',
|
||||
yes: 'Yes',
|
||||
no: 'No',
|
||||
partial: 'Partial',
|
||||
},
|
||||
team: {
|
||||
title: 'The Team',
|
||||
subtitle: 'Founders with domain expertise',
|
||||
equity: 'Equity',
|
||||
expertise: 'Expertise',
|
||||
},
|
||||
technology: {
|
||||
title: 'Technology Roadmap',
|
||||
subtitle: 'From MVP to Full Autonomy — 5-Year Technology Plan',
|
||||
timelineTitle: 'Milestones 2026-2030',
|
||||
stackTitle: 'Tech Stack',
|
||||
phases: [
|
||||
{
|
||||
year: '2026',
|
||||
phase: 'Foundation & MVP',
|
||||
techs: ['Self-Hosted LLM (32B)', 'Apple M2 Mini', 'Basic Compliance SDK', 'OCR Pipeline'],
|
||||
},
|
||||
{
|
||||
year: '2027',
|
||||
phase: 'Product-Market Fit',
|
||||
techs: ['Multi-Model Router', 'RAG 2.0 with Qdrant', 'Auto Compliance Scan', 'Real-time Monitoring'],
|
||||
},
|
||||
{
|
||||
year: '2028',
|
||||
phase: 'Enterprise Scale',
|
||||
techs: ['Federated Learning', 'Cluster Management', 'API Marketplace', 'Multi-Tenant'],
|
||||
},
|
||||
{
|
||||
year: '2029',
|
||||
phase: 'AI Platform',
|
||||
techs: ['Custom Fine-Tuned (40B+)', 'Predictive Compliance', 'Auto-Audits', 'Partner Integrations'],
|
||||
},
|
||||
{
|
||||
year: '2030',
|
||||
phase: 'Full Autonomy',
|
||||
techs: ['Agent Network', 'Self-Healing', 'Zero-Day Compliance', '1000B Parameters'],
|
||||
},
|
||||
],
|
||||
layers: [
|
||||
{ name: 'Application', techs: 'Next.js, React, TailwindCSS, REST/GraphQL API' },
|
||||
{ name: 'AI/ML', techs: 'Qwen 32B → 1000B, RAG Pipeline, NLP, OCR (PaddleOCR)' },
|
||||
{ name: 'Infrastructure', techs: 'Apple Silicon (M2/M4 Pro), Docker, Self-Hosted' },
|
||||
{ name: 'Security', techs: 'BSI-TR-03161, E2E Encryption, Vault' },
|
||||
{ name: 'Data', techs: 'PostgreSQL + PostGIS, Qdrant (Vectors), MinIO (S3)' },
|
||||
],
|
||||
},
|
||||
financials: {
|
||||
title: 'Financial Projections',
|
||||
subtitle: 'AI-First cost structure — scales without linear headcount growth',
|
||||
revenue: 'Revenue',
|
||||
costs: 'Costs',
|
||||
customers: 'Customers',
|
||||
mrr: 'MRR',
|
||||
arr: 'ARR',
|
||||
burnRate: 'Burn Rate',
|
||||
employees: 'Employees',
|
||||
year: 'Year',
|
||||
sliderGrowth: 'Growth Rate',
|
||||
sliderChurn: 'Churn Rate',
|
||||
sliderArpu: 'ARPU',
|
||||
adjustAssumptions: 'Adjust Assumptions',
|
||||
},
|
||||
theAsk: {
|
||||
title: 'The Ask',
|
||||
subtitle: 'Staged Funding 2026-2027',
|
||||
amount: 'Funding',
|
||||
instrument: 'Instrument',
|
||||
useOfFunds: 'Use of Funds',
|
||||
engineering: 'Engineering',
|
||||
sales: 'Sales',
|
||||
hardware: 'Hardware',
|
||||
personnel: 'Personnel',
|
||||
legal: 'Legal',
|
||||
reserve: 'Reserve',
|
||||
targetDate: 'Timeline',
|
||||
},
|
||||
aiqa: {
|
||||
title: 'Questions? The AI answers.',
|
||||
subtitle: 'Ask your investor questions — our AI agent responds with real data.',
|
||||
placeholder: 'Ask a question about the investment...',
|
||||
send: 'Send',
|
||||
thinking: 'Thinking...',
|
||||
suggestions: [
|
||||
'How does the business model scale?',
|
||||
'What is the unfair advantage?',
|
||||
'What does the exit strategy look like?',
|
||||
'Why self-hosting instead of cloud?',
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export function t(lang: Language): typeof translations.de {
|
||||
return translations[lang]
|
||||
}
|
||||
|
||||
export function formatEur(value: number, lang: Language): string {
|
||||
if (value >= 1_000_000_000) {
|
||||
const v = (value / 1_000_000_000).toFixed(1)
|
||||
return lang === 'de' ? `${v} Mrd. EUR` : `EUR ${v}B`
|
||||
}
|
||||
if (value >= 1_000_000) {
|
||||
const v = (value / 1_000_000).toFixed(1)
|
||||
return lang === 'de' ? `${v} Mio. EUR` : `EUR ${v}M`
|
||||
}
|
||||
if (value >= 1_000) {
|
||||
const v = (value / 1_000).toFixed(0)
|
||||
return lang === 'de' ? `${v}k EUR` : `EUR ${v}k`
|
||||
}
|
||||
return lang === 'de' ? `${value} EUR` : `EUR ${value}`
|
||||
}
|
||||
|
||||
export function formatNumber(value: number): string {
|
||||
return new Intl.NumberFormat('de-DE').format(value)
|
||||
}
|
||||
|
||||
export default translations
|
||||
244
pitch-deck/lib/types.ts
Normal file
244
pitch-deck/lib/types.ts
Normal file
@@ -0,0 +1,244 @@
|
||||
export interface PitchCompany {
|
||||
id: number
|
||||
name: string
|
||||
legal_form: string
|
||||
founding_date: string
|
||||
tagline_de: string
|
||||
tagline_en: string
|
||||
mission_de: string
|
||||
mission_en: string
|
||||
website: string
|
||||
hq_city: string
|
||||
}
|
||||
|
||||
export interface PitchTeamMember {
|
||||
id: number
|
||||
name: string
|
||||
role_de: string
|
||||
role_en: string
|
||||
bio_de: string
|
||||
bio_en: string
|
||||
equity_pct: number
|
||||
expertise: string[]
|
||||
linkedin_url: string
|
||||
photo_url: string
|
||||
}
|
||||
|
||||
export interface PitchFinancial {
|
||||
id: number
|
||||
year: number
|
||||
revenue_eur: number
|
||||
costs_eur: number
|
||||
mrr_eur: number
|
||||
burn_rate_eur: number
|
||||
customers_count: number
|
||||
employees_count: number
|
||||
arr_eur: number
|
||||
}
|
||||
|
||||
export interface PitchMarket {
|
||||
id: number
|
||||
market_segment: string
|
||||
label: string
|
||||
value_eur: number
|
||||
growth_rate_pct: number
|
||||
source: string
|
||||
}
|
||||
|
||||
export interface PitchCompetitor {
|
||||
id: number
|
||||
name: string
|
||||
customers_count: number
|
||||
pricing_range: string
|
||||
strengths: string[]
|
||||
weaknesses: string[]
|
||||
website: string
|
||||
}
|
||||
|
||||
export interface PitchFeature {
|
||||
id: number
|
||||
feature_name_de: string
|
||||
feature_name_en: string
|
||||
category: string
|
||||
breakpilot: boolean
|
||||
proliance: boolean
|
||||
dataguard: boolean
|
||||
heydata: boolean
|
||||
is_differentiator: boolean
|
||||
}
|
||||
|
||||
export interface PitchMilestone {
|
||||
id: number
|
||||
milestone_date: string
|
||||
title_de: string
|
||||
title_en: string
|
||||
description_de: string
|
||||
description_en: string
|
||||
status: 'completed' | 'in_progress' | 'planned'
|
||||
category: string
|
||||
}
|
||||
|
||||
export interface PitchMetric {
|
||||
id: number
|
||||
metric_name: string
|
||||
label_de: string
|
||||
label_en: string
|
||||
value: string
|
||||
unit: string
|
||||
is_live: boolean
|
||||
}
|
||||
|
||||
export interface PitchFunding {
|
||||
id: number
|
||||
round_name: string
|
||||
amount_eur: number
|
||||
use_of_funds: { category: string; percentage: number; label_de: string; label_en: string }[]
|
||||
instrument: string
|
||||
target_date: string
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface PitchProduct {
|
||||
id: number
|
||||
name: string
|
||||
hardware: string
|
||||
hardware_cost_eur: number
|
||||
monthly_price_eur: number
|
||||
llm_model: string
|
||||
llm_size: string
|
||||
llm_capability_de: string
|
||||
llm_capability_en: string
|
||||
features_de: string[]
|
||||
features_en: string[]
|
||||
is_popular: boolean
|
||||
operating_cost_eur: number
|
||||
}
|
||||
|
||||
export interface PitchData {
|
||||
company: PitchCompany
|
||||
team: PitchTeamMember[]
|
||||
financials: PitchFinancial[]
|
||||
market: PitchMarket[]
|
||||
competitors: PitchCompetitor[]
|
||||
features: PitchFeature[]
|
||||
milestones: PitchMilestone[]
|
||||
metrics: PitchMetric[]
|
||||
funding: PitchFunding
|
||||
products: PitchProduct[]
|
||||
}
|
||||
|
||||
// Financial Model Types
|
||||
export interface FMScenario {
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
is_default: boolean
|
||||
color: string
|
||||
assumptions: FMAssumption[]
|
||||
}
|
||||
|
||||
export interface FMAssumption {
|
||||
id: string
|
||||
scenario_id: string
|
||||
key: string
|
||||
label_de: string
|
||||
label_en: string
|
||||
value: number | number[]
|
||||
value_type: 'scalar' | 'step' | 'timeseries'
|
||||
unit: string
|
||||
min_value: number | null
|
||||
max_value: number | null
|
||||
step_size: number | null
|
||||
category: string
|
||||
sort_order: number
|
||||
}
|
||||
|
||||
export interface FMResult {
|
||||
month: number
|
||||
year: number
|
||||
month_in_year: number
|
||||
new_customers: number
|
||||
churned_customers: number
|
||||
total_customers: number
|
||||
mrr_eur: number
|
||||
arr_eur: number
|
||||
revenue_eur: number
|
||||
cogs_eur: number
|
||||
personnel_eur: number
|
||||
infra_eur: number
|
||||
marketing_eur: number
|
||||
total_costs_eur: number
|
||||
employees_count: number
|
||||
gross_margin_pct: number
|
||||
burn_rate_eur: number
|
||||
runway_months: number
|
||||
cac_eur: number
|
||||
ltv_eur: number
|
||||
ltv_cac_ratio: number
|
||||
cash_balance_eur: number
|
||||
cumulative_revenue_eur: number
|
||||
// Detail costs
|
||||
admin_costs_eur: number
|
||||
office_costs_eur: number
|
||||
founding_costs_eur: number
|
||||
ihk_eur: number
|
||||
depreciation_eur: number
|
||||
interest_expense_eur: number
|
||||
taxes_eur: number
|
||||
net_income_eur: number
|
||||
ebit_eur: number
|
||||
software_licenses_eur: number
|
||||
travel_costs_eur: number
|
||||
funding_eur: number
|
||||
}
|
||||
|
||||
export interface FMComputeResponse {
|
||||
scenario_id: string
|
||||
results: FMResult[]
|
||||
summary: {
|
||||
final_arr: number
|
||||
final_customers: number
|
||||
break_even_month: number | null
|
||||
final_runway: number
|
||||
final_ltv_cac: number
|
||||
peak_burn: number
|
||||
total_funding_needed: number
|
||||
}
|
||||
}
|
||||
|
||||
export type Language = 'de' | 'en'
|
||||
|
||||
export interface ChatMessage {
|
||||
role: 'user' | 'assistant'
|
||||
content: string
|
||||
}
|
||||
|
||||
export type SlideId =
|
||||
| 'cover'
|
||||
| 'problem'
|
||||
| 'solution'
|
||||
| 'product'
|
||||
| 'how-it-works'
|
||||
| 'market'
|
||||
| 'business-model'
|
||||
| 'traction'
|
||||
| 'competition'
|
||||
| 'team'
|
||||
| 'technology'
|
||||
| 'financials'
|
||||
| 'the-ask'
|
||||
| 'ai-qa'
|
||||
| 'appendix'
|
||||
| 'annex-infra'
|
||||
| 'annex-ai-stack'
|
||||
| 'annex-rag'
|
||||
| 'annex-security'
|
||||
| 'annex-devops'
|
||||
| 'annex-agent-arch'
|
||||
| 'annex-agent-rag'
|
||||
| 'annex-agent-workflow'
|
||||
| 'annex-usp-overview'
|
||||
| 'annex-usp-comparison'
|
||||
| 'annex-usp-moat'
|
||||
| 'annex-roadmap-2027'
|
||||
| 'annex-roadmap-2028'
|
||||
Reference in New Issue
Block a user