feat: Add DevSecOps tools, Woodpecker proxy, Vault persistent storage, pitch-deck annex slides
All checks were successful
CI / test-bqas (push) Successful in 32s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 46s
CI / test-python-voice (push) Successful in 38s
All checks were successful
CI / test-bqas (push) Successful in 32s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 46s
CI / test-python-voice (push) Successful in 38s
- Install Gitleaks, Trivy, Grype, Syft, Semgrep, Bandit in backend-core Dockerfile - Add Woodpecker SQLite proxy API (fallback without API token) - Mount woodpecker_data volume read-only to backend-core - Add backend proxy fallback in admin-core Woodpecker route - Add Vault file-based persistent storage (config.hcl, init-vault.sh) - Auto-init, unseal and root-token persistence for Vault - Add 6 pitch-deck annex slides (Assumptions, Architecture, GTM, Regulatory, Engineering, AI Pipeline) - Dynamic margin/amortization KPIs in BusinessModelSlide - Market sources modal with citations in MarketSlide - Redesign nginx landing page to 3-column layout (Lehrer/Compliance/Core) - Extend MkDocs nav with Services and SDK documentation sections - Add SDK Protection architecture doc Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { Language } from '@/lib/types'
|
||||
import { Language, PitchFunding } from '@/lib/types'
|
||||
import { t } from '@/lib/i18n'
|
||||
import { ArrowRight } from 'lucide-react'
|
||||
import GradientText from '../ui/GradientText'
|
||||
@@ -10,11 +10,36 @@ import BrandName from '../ui/BrandName'
|
||||
interface CoverSlideProps {
|
||||
lang: Language
|
||||
onNext: () => void
|
||||
funding?: PitchFunding
|
||||
}
|
||||
|
||||
export default function CoverSlide({ lang, onNext }: CoverSlideProps) {
|
||||
function formatRoundLabel(funding: PitchFunding | undefined): string {
|
||||
if (!funding) return 'Pre-Seed'
|
||||
// Extract a short round label from round_name
|
||||
const name = funding.round_name || ''
|
||||
if (name.toLowerCase().includes('seed')) return 'Pre-Seed'
|
||||
if (name.toLowerCase().includes('series a')) return 'Series A'
|
||||
return 'Pre-Seed'
|
||||
}
|
||||
|
||||
function formatQuarter(dateStr: string | undefined): string {
|
||||
if (!dateStr) return ''
|
||||
try {
|
||||
const d = new Date(dateStr)
|
||||
const quarter = Math.ceil((d.getMonth() + 1) / 3)
|
||||
return `Q${quarter} ${d.getFullYear()}`
|
||||
} catch {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
export default function CoverSlide({ lang, onNext, funding }: CoverSlideProps) {
|
||||
const i = t(lang)
|
||||
|
||||
const roundLabel = formatRoundLabel(funding)
|
||||
const quarter = formatQuarter(funding?.target_date)
|
||||
const subtitle = quarter ? `${roundLabel} · ${quarter}` : roundLabel
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center text-center min-h-[70vh]">
|
||||
{/* Logo / Brand */}
|
||||
@@ -63,14 +88,14 @@ export default function CoverSlide({ lang, onNext }: CoverSlideProps) {
|
||||
{i.cover.tagline}
|
||||
</motion.p>
|
||||
|
||||
{/* Subtitle */}
|
||||
{/* Subtitle — dynamisch aus Funding */}
|
||||
<motion.p
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.5, delay: 0.8 }}
|
||||
className="text-sm text-white/30 font-mono tracking-wider mb-12"
|
||||
>
|
||||
{i.cover.subtitle}
|
||||
{subtitle}
|
||||
</motion.p>
|
||||
|
||||
{/* CTA */}
|
||||
|
||||
Reference in New Issue
Block a user