Portfolio case studies

This commit is contained in:
Jake Shore 2026-02-15 11:52:08 -05:00
commit e3145d4bf7
6 changed files with 2522 additions and 0 deletions

485
ai-ad-engine.html Normal file
View File

@ -0,0 +1,485 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Ad Creative Engine — Case Study</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--accent: #00d4ff;
--accent-dark: #0099cc;
--accent-glow: rgba(0,212,255,0.15);
--bg-primary: #0a0a0a;
--bg-secondary: #111827;
--text-primary: #f1f5f9;
--text-secondary: #94a3b8;
--border-color: rgba(255,255,255,0.08);
--glass-bg: rgba(255,255,255,0.03);
--glass-border: rgba(255,255,255,0.06);
}
html { scroll-behavior: smooth; }
body {
font-family: 'Inter', -apple-system, sans-serif;
background: linear-gradient(135deg, var(--bg-primary) 0%, var(--bg-secondary) 50%, #0d1520 100%);
color: var(--text-primary);
min-height: 100vh;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
body::before {
content: '';
position: fixed; top: 0; left: 0; right: 0; bottom: 0;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.03'/%3E%3C/svg%3E");
pointer-events: none; z-index: 0;
}
.container { max-width: 900px; margin: 0 auto; padding: 0 24px; position: relative; z-index: 1; }
/* Back link */
.back {
display: inline-flex; align-items: center; gap: 8px;
padding: 20px 0; color: var(--text-secondary); text-decoration: none;
font-size: 0.9rem; font-weight: 500; transition: color 0.2s;
}
.back:hover { color: var(--accent); }
/* Hero */
.hero {
text-align: center;
padding: 60px 0 80px;
animation: fadeInUp 0.8s ease-out;
}
.hero-label {
display: inline-flex; align-items: center; gap: 8px;
padding: 6px 16px; border-radius: 100px;
background: var(--accent-glow); border: 1px solid rgba(0,212,255,0.2);
font-size: 12px; font-weight: 600; color: var(--accent);
text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 24px;
}
.hero h1 {
font-size: clamp(2.2rem, 5vw, 3.5rem);
font-weight: 800; line-height: 1.1;
letter-spacing: -0.03em; margin-bottom: 16px;
}
.hero h1 span {
background: linear-gradient(135deg, var(--accent), var(--accent-dark));
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
}
.hero .hook {
font-size: 1.25rem; color: var(--text-secondary);
font-style: italic; font-weight: 300;
}
/* Section */
.section {
padding: 60px 0;
animation: fadeInUp 0.6s ease-out both;
}
.section:nth-child(3) { animation-delay: 0.1s; }
.section:nth-child(4) { animation-delay: 0.15s; }
.section:nth-child(5) { animation-delay: 0.2s; }
.section-label {
font-size: 11px; font-weight: 700; text-transform: uppercase;
letter-spacing: 0.12em; color: var(--accent); margin-bottom: 12px;
}
.section h2 {
font-size: 1.8rem; font-weight: 700; margin-bottom: 16px;
letter-spacing: -0.02em;
}
.section p { color: var(--text-secondary); font-size: 1.05rem; line-height: 1.8; max-width: 700px; }
/* Glass card */
.glass {
background: var(--glass-bg); border: 1px solid var(--glass-border);
border-radius: 16px; padding: 32px; backdrop-filter: blur(10px);
}
/* Solution list */
.solution-list { list-style: none; margin-top: 20px; }
.solution-list li {
padding: 12px 0; border-bottom: 1px solid var(--border-color);
color: var(--text-secondary); font-size: 1rem; display: flex; align-items: flex-start; gap: 12px;
}
.solution-list li:last-child { border-bottom: none; }
.solution-list .check {
color: var(--accent); font-weight: 700; font-size: 1.1rem; flex-shrink: 0; margin-top: 1px;
}
/* Flow diagram */
.flow {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 12px;
margin-top: 24px;
}
.flow-step {
background: var(--glass-bg); border: 1px solid var(--glass-border);
border-radius: 14px; padding: 20px 14px; text-align: center;
position: relative; transition: border-color 0.3s, transform 0.3s;
}
.flow-step:hover {
border-color: rgba(0,212,255,0.3); transform: translateY(-3px);
}
.flow-step .num {
width: 28px; height: 28px; border-radius: 50%;
background: var(--accent-glow); border: 1px solid rgba(0,212,255,0.3);
display: flex; align-items: center; justify-content: center;
font-size: 12px; font-weight: 700; color: var(--accent);
margin: 0 auto 12px;
}
.flow-step .icon { font-size: 24px; margin-bottom: 8px; }
.flow-step .label { font-size: 0.8rem; font-weight: 600; color: var(--text-primary); line-height: 1.3; }
.flow-step .sublabel { font-size: 0.7rem; color: var(--text-secondary); margin-top: 4px; }
/* Arrow between steps */
.flow-step:not(:last-child)::after {
content: '→'; position: absolute; right: -16px; top: 50%;
transform: translateY(-50%); color: var(--accent); font-size: 14px; opacity: 0.5;
}
/* Tech pills */
.tech-grid {
display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px;
}
.tech-pill {
padding: 8px 18px; border-radius: 100px;
background: var(--glass-bg); border: 1px solid var(--glass-border);
font-size: 0.85rem; font-weight: 500; color: var(--text-secondary);
transition: border-color 0.2s, color 0.2s;
}
.tech-pill:hover { border-color: rgba(0,212,255,0.3); color: var(--accent); }
/* Results grid */
.results-grid {
display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-top: 24px;
}
.result-card {
background: var(--glass-bg); border: 1px solid var(--glass-border);
border-radius: 16px; padding: 28px 20px; text-align: center;
transition: border-color 0.3s, transform 0.3s;
}
.result-card:hover { border-color: rgba(0,212,255,0.3); transform: translateY(-3px); }
.result-card .number {
font-size: 2rem; font-weight: 800; letter-spacing: -0.03em;
background: linear-gradient(135deg, var(--accent), var(--accent-dark));
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
margin-bottom: 6px;
}
.result-card .label { font-size: 0.8rem; color: var(--text-secondary); font-weight: 500; }
/* Mockup */
.mockup-container {
margin-top: 24px; border-radius: 16px; overflow: hidden;
background: linear-gradient(135deg, #0c1222, #111d33);
border: 1px solid var(--glass-border); padding: 24px;
}
.mockup-titlebar {
display: flex; align-items: center; gap: 8px; margin-bottom: 20px;
}
.mockup-dot {
width: 12px; height: 12px; border-radius: 50%;
}
.mockup-dot.r { background: #ef4444; }
.mockup-dot.y { background: #f59e0b; }
.mockup-dot.g { background: #10b981; }
.mockup-url-bar {
flex: 1; margin-left: 16px; height: 36px; border-radius: 8px;
background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.1);
display: flex; align-items: center; padding: 0 14px;
font-size: 13px; color: var(--text-secondary);
}
.mockup-input-area {
background: rgba(255,255,255,0.04); border: 1px solid rgba(0,212,255,0.2);
border-radius: 12px; padding: 16px 20px; margin-bottom: 24px;
display: flex; align-items: center; gap: 12px;
}
.mockup-input-area .icon { color: var(--accent); font-size: 18px; }
.mockup-input-area .text { color: var(--text-secondary); font-size: 0.9rem; flex: 1; }
.mockup-input-area .btn {
padding: 8px 20px; border-radius: 8px;
background: linear-gradient(135deg, var(--accent), var(--accent-dark));
color: #000; font-size: 13px; font-weight: 700; white-space: nowrap;
}
.mockup-formats {
display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px;
}
.mockup-format-card {
background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06);
border-radius: 10px; padding: 20px; text-align: center;
transition: border-color 0.2s;
}
.mockup-format-card:hover { border-color: rgba(0,212,255,0.3); }
.mockup-format-card .fmt-icon { font-size: 28px; margin-bottom: 8px; }
.mockup-format-card .fmt-label { font-size: 0.8rem; font-weight: 600; color: var(--text-primary); }
.mockup-format-card .fmt-status {
font-size: 0.7rem; color: var(--accent); margin-top: 4px;
display: flex; align-items: center; justify-content: center; gap: 4px;
}
.mockup-format-card .fmt-status .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
/* Format content previews */
.fmt-preview {
margin-top: 10px; padding: 8px; border-radius: 6px;
background: rgba(0,0,0,0.3); min-height: 40px;
}
.fmt-preview-line {
height: 6px; border-radius: 3px; background: rgba(255,255,255,0.08); margin-bottom: 4px;
}
.fmt-preview-line:nth-child(2) { width: 70%; }
.fmt-preview-line:nth-child(3) { width: 50%; }
/* CTA */
.cta {
text-align: center; padding: 80px 0;
animation: fadeInUp 0.6s ease-out both; animation-delay: 0.3s;
}
.cta h2 {
font-size: 2rem; font-weight: 700; margin-bottom: 12px;
letter-spacing: -0.02em;
}
.cta p { color: var(--text-secondary); margin-bottom: 28px; font-size: 1.05rem; }
.cta-btn {
display: inline-flex; align-items: center; gap: 8px;
padding: 14px 32px; border-radius: 12px;
background: linear-gradient(135deg, var(--accent), var(--accent-dark));
color: #000; font-weight: 700; font-size: 1rem;
text-decoration: none; transition: transform 0.2s, box-shadow 0.2s;
}
.cta-btn:hover {
transform: translateY(-2px);
box-shadow: 0 8px 30px rgba(0,212,255,0.3);
}
/* Footer */
.footer {
text-align: center; padding: 40px 0;
border-top: 1px solid var(--border-color);
}
.footer .badge {
display: inline-flex; align-items: center; gap: 6px;
padding: 6px 14px; border-radius: 8px;
background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06);
font-size: 12px; color: var(--text-secondary);
}
/* Animations */
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(24px); }
to { opacity: 1; transform: translateY(0); }
}
/* Mobile */
@media (max-width: 768px) {
.hero { padding: 40px 0 50px; }
.flow { grid-template-columns: 1fr; gap: 8px; }
.flow-step:not(:last-child)::after {
content: '↓'; right: auto; left: 50%; top: auto; bottom: -14px;
transform: translateX(-50%);
}
.results-grid { grid-template-columns: repeat(2, 1fr); }
.mockup-formats { grid-template-columns: 1fr 1fr; }
.section h2 { font-size: 1.4rem; }
}
@media (max-width: 480px) {
.results-grid { grid-template-columns: 1fr; }
.mockup-formats { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="container">
<a href="index.html" class="back">← Back to Portfolio</a>
<section class="hero">
<div class="hero-label">⚡ AI + Creative Automation</div>
<h1>AI Ad <span>Creative Engine</span></h1>
<p class="hook">"From URL to 6 ad formats in 60 seconds"</p>
</section>
<section class="section">
<div class="section-label">The Challenge</div>
<h2>Creative at Scale is Broken</h2>
<div class="glass">
<p>Marketing teams spend <strong style="color:var(--text-primary)">$15K/month</strong> on creative agencies and wait weeks for ad variations. Testing 30 creatives to find 3 winners is too expensive and slow. The entire workflow — from brief to production-ready creative — needs to collapse from weeks to seconds.</p>
</div>
</section>
<section class="section">
<div class="section-label">The Solution</div>
<h2>Brand DNA → Production Ads, Instantly</h2>
<p>Built an AI engine that scrapes any website URL, extracts brand DNA (voice, colors, positioning), and generates production-ready ad concepts in 6 formats:</p>
<ul class="solution-list">
<li><span class="check"></span> Scrapes any URL to extract brand voice, colors, and positioning automatically</li>
<li><span class="check"></span> Claude generates hooks, copy, and ad concepts tailored to the brand</li>
<li><span class="check"></span> Renders 6 distinct ad formats: memes, iMessage threads, tweets, stat cards, UGC reviews, and billboards</li>
<li><span class="check"></span> Feedback loop lets users refine and train the model on brand preferences</li>
<li><span class="check"></span> Zero design skills needed — production-ready output from day one</li>
</ul>
</section>
<section class="section">
<div class="section-label">How It Works</div>
<h2>5-Step Pipeline</h2>
<div class="flow">
<div class="flow-step">
<div class="num">1</div>
<div class="icon">🔗</div>
<div class="label">Paste URL</div>
<div class="sublabel">Any website</div>
</div>
<div class="flow-step">
<div class="num">2</div>
<div class="icon">🔍</div>
<div class="label">AI Scrapes Brand</div>
<div class="sublabel">Voice, colors, tone</div>
</div>
<div class="flow-step">
<div class="num">3</div>
<div class="icon">✍️</div>
<div class="label">Claude Writes Hooks</div>
<div class="sublabel">Copy &amp; concepts</div>
</div>
<div class="flow-step">
<div class="num">4</div>
<div class="icon">🎨</div>
<div class="label">Renders 6 Formats</div>
<div class="sublabel">Production-ready</div>
</div>
<div class="flow-step">
<div class="num">5</div>
<div class="icon">🔄</div>
<div class="label">Feedback Loop</div>
<div class="sublabel">Trains the model</div>
</div>
</div>
</section>
<section class="section">
<div class="section-label">Tech Stack</div>
<h2>Built With</h2>
<div class="tech-grid">
<span class="tech-pill">Claude API</span>
<span class="tech-pill">Node.js</span>
<span class="tech-pill">Web Scraping</span>
<span class="tech-pill">HTML/CSS</span>
<span class="tech-pill">Gemini (images)</span>
<span class="tech-pill">Puppeteer</span>
<span class="tech-pill">Express</span>
</div>
</section>
<section class="section">
<div class="section-label">Results</div>
<h2>Impact at a Glance</h2>
<div class="results-grid">
<div class="result-card">
<div class="number">60s</div>
<div class="label">Generation Time</div>
</div>
<div class="result-card">
<div class="number">6</div>
<div class="label">Ad Formats Per Run</div>
</div>
<div class="result-card">
<div class="number">50×</div>
<div class="label">Creative Output vs Manual</div>
</div>
<div class="result-card">
<div class="number">$0</div>
<div class="label">Design Skills Needed</div>
</div>
</div>
</section>
<section class="section">
<div class="section-label">Product Preview</div>
<h2>The Interface</h2>
<div class="mockup-container">
<div class="mockup-titlebar">
<span class="mockup-dot r"></span>
<span class="mockup-dot y"></span>
<span class="mockup-dot g"></span>
<div class="mockup-url-bar">ad-engine.app/generate</div>
</div>
<div class="mockup-input-area">
<span class="icon">🔗</span>
<span class="text">https://your-brand.com</span>
<span class="btn">Generate Ads →</span>
</div>
<div class="mockup-formats">
<div class="mockup-format-card">
<div class="fmt-icon">😂</div>
<div class="fmt-label">Meme</div>
<div class="fmt-status"><span class="dot"></span> Generated</div>
<div class="fmt-preview">
<div class="fmt-preview-line"></div>
<div class="fmt-preview-line"></div>
<div class="fmt-preview-line"></div>
</div>
</div>
<div class="mockup-format-card">
<div class="fmt-icon">💬</div>
<div class="fmt-label">iMessage</div>
<div class="fmt-status"><span class="dot"></span> Generated</div>
<div class="fmt-preview">
<div class="fmt-preview-line"></div>
<div class="fmt-preview-line"></div>
</div>
</div>
<div class="mockup-format-card">
<div class="fmt-icon">🐦</div>
<div class="fmt-label">Tweet</div>
<div class="fmt-status"><span class="dot"></span> Generated</div>
<div class="fmt-preview">
<div class="fmt-preview-line"></div>
<div class="fmt-preview-line"></div>
<div class="fmt-preview-line"></div>
</div>
</div>
<div class="mockup-format-card">
<div class="fmt-icon">📊</div>
<div class="fmt-label">Stat Card</div>
<div class="fmt-status"><span class="dot"></span> Generated</div>
<div class="fmt-preview">
<div class="fmt-preview-line"></div>
<div class="fmt-preview-line"></div>
</div>
</div>
<div class="mockup-format-card">
<div class="fmt-icon"></div>
<div class="fmt-label">UGC Review</div>
<div class="fmt-status"><span class="dot"></span> Generated</div>
<div class="fmt-preview">
<div class="fmt-preview-line"></div>
<div class="fmt-preview-line"></div>
<div class="fmt-preview-line"></div>
</div>
</div>
<div class="mockup-format-card">
<div class="fmt-icon">🏙️</div>
<div class="fmt-label">Billboard</div>
<div class="fmt-status"><span class="dot"></span> Generated</div>
<div class="fmt-preview">
<div class="fmt-preview-line"></div>
<div class="fmt-preview-line"></div>
</div>
</div>
</div>
</div>
</section>
<section class="cta">
<h2>Want something like this?</h2>
<p>Let's talk about automating your creative workflow.</p>
<a href="mailto:hello@example.com" class="cta-btn">Get in Touch →</a>
</section>
<footer class="footer">
<div class="badge">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
Built with Claude Code
</div>
</footer>
</div>
</body>
</html>

456
credispo.html Normal file
View File

@ -0,0 +1,456 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CREdispo — Commercial Real Estate Lead Gen Case Study</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--accent: #10b981;
--accent-dark: #059669;
--accent-glow: rgba(16,185,129,0.15);
--bg-primary: #0a0a0a;
--bg-secondary: #111827;
--text-primary: #f1f5f9;
--text-secondary: #94a3b8;
--border-color: rgba(255,255,255,0.08);
--glass-bg: rgba(255,255,255,0.03);
--glass-border: rgba(255,255,255,0.06);
}
html { scroll-behavior: smooth; }
body {
font-family: 'Inter', -apple-system, sans-serif;
background: linear-gradient(135deg, var(--bg-primary) 0%, var(--bg-secondary) 50%, #0a1510 100%);
color: var(--text-primary); min-height: 100vh; line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
body::before {
content: ''; position: fixed; top: 0; left: 0; right: 0; bottom: 0;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.03'/%3E%3C/svg%3E");
pointer-events: none; z-index: 0;
}
.container { max-width: 900px; margin: 0 auto; padding: 0 24px; position: relative; z-index: 1; }
.back {
display: inline-flex; align-items: center; gap: 8px;
padding: 20px 0; color: var(--text-secondary); text-decoration: none;
font-size: 0.9rem; font-weight: 500; transition: color 0.2s;
}
.back:hover { color: var(--accent); }
.hero { text-align: center; padding: 60px 0 80px; animation: fadeInUp 0.8s ease-out; }
.hero-label {
display: inline-flex; align-items: center; gap: 8px;
padding: 6px 16px; border-radius: 100px;
background: var(--accent-glow); border: 1px solid rgba(16,185,129,0.2);
font-size: 12px; font-weight: 600; color: var(--accent);
text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 24px;
}
.hero h1 { font-size: clamp(2.2rem, 5vw, 3.5rem); font-weight: 800; line-height: 1.1; letter-spacing: -0.03em; margin-bottom: 16px; }
.hero h1 span {
background: linear-gradient(135deg, var(--accent), #34d399);
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
}
.hero .hook { font-size: 1.25rem; color: var(--text-secondary); font-style: italic; font-weight: 300; }
.section { padding: 60px 0; animation: fadeInUp 0.6s ease-out both; }
.section-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em; color: var(--accent); margin-bottom: 12px; }
.section h2 { font-size: 1.8rem; font-weight: 700; margin-bottom: 16px; letter-spacing: -0.02em; }
.section p { color: var(--text-secondary); font-size: 1.05rem; line-height: 1.8; max-width: 700px; }
.glass { background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: 16px; padding: 32px; backdrop-filter: blur(10px); }
.solution-list { list-style: none; margin-top: 20px; }
.solution-list li { padding: 12px 0; border-bottom: 1px solid var(--border-color); color: var(--text-secondary); font-size: 1rem; display: flex; align-items: flex-start; gap: 12px; }
.solution-list li:last-child { border-bottom: none; }
.solution-list .check { color: var(--accent); font-weight: 700; font-size: 1.1rem; flex-shrink: 0; }
/* Flow */
.flow { display: grid; grid-template-columns: repeat(6, 1fr); gap: 10px; margin-top: 24px; }
.flow-step {
background: var(--glass-bg); border: 1px solid var(--glass-border);
border-radius: 14px; padding: 18px 10px; text-align: center;
position: relative; transition: border-color 0.3s, transform 0.3s;
}
.flow-step:hover { border-color: rgba(16,185,129,0.3); transform: translateY(-3px); }
.flow-step .num {
width: 26px; height: 26px; border-radius: 50%;
background: var(--accent-glow); border: 1px solid rgba(16,185,129,0.3);
display: flex; align-items: center; justify-content: center;
font-size: 11px; font-weight: 700; color: var(--accent); margin: 0 auto 10px;
}
.flow-step .icon { font-size: 22px; margin-bottom: 6px; }
.flow-step .label { font-size: 0.75rem; font-weight: 600; color: var(--text-primary); line-height: 1.3; }
.flow-step .sublabel { font-size: 0.65rem; color: var(--text-secondary); margin-top: 3px; }
.flow-step:not(:last-child)::after {
content: '→'; position: absolute; right: -13px; top: 50%;
transform: translateY(-50%); color: var(--accent); font-size: 12px; opacity: 0.5;
}
.tech-grid { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.tech-pill {
padding: 8px 18px; border-radius: 100px;
background: var(--glass-bg); border: 1px solid var(--glass-border);
font-size: 0.85rem; font-weight: 500; color: var(--text-secondary);
transition: border-color 0.2s, color 0.2s;
}
.tech-pill:hover { border-color: rgba(16,185,129,0.3); color: var(--accent); }
.results-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-top: 24px; }
.result-card {
background: var(--glass-bg); border: 1px solid var(--glass-border);
border-radius: 16px; padding: 28px 20px; text-align: center;
transition: border-color 0.3s, transform 0.3s;
}
.result-card:hover { border-color: rgba(16,185,129,0.3); transform: translateY(-3px); }
.result-card .number {
font-size: 2rem; font-weight: 800; letter-spacing: -0.03em;
background: linear-gradient(135deg, var(--accent), #34d399);
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
margin-bottom: 6px;
}
.result-card .label { font-size: 0.8rem; color: var(--text-secondary); font-weight: 500; }
/* Dashboard Mockup */
.mockup-container {
margin-top: 24px; border-radius: 16px; overflow: hidden;
background: linear-gradient(135deg, #0c1210, #0f1a15);
border: 1px solid var(--glass-border); padding: 24px;
}
.mockup-titlebar { display: flex; align-items: center; gap: 8px; margin-bottom: 20px; }
.mockup-dot { width: 12px; height: 12px; border-radius: 50%; }
.mockup-dot.r { background: #ef4444; } .mockup-dot.y { background: #f59e0b; } .mockup-dot.g { background: #10b981; }
.mockup-url-bar {
flex: 1; margin-left: 16px; height: 36px; border-radius: 8px;
background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.1);
display: flex; align-items: center; padding: 0 14px; font-size: 13px; color: var(--text-secondary);
}
/* Dashboard layout */
.dash-top { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; gap: 10px; margin-bottom: 16px; }
.dash-stat {
background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06);
border-radius: 10px; padding: 14px; text-align: center;
}
.dash-stat .ds-num { font-size: 1.4rem; font-weight: 800; color: var(--accent); }
.dash-stat .ds-label { font-size: 0.7rem; color: var(--text-secondary); margin-top: 2px; }
/* Table */
.dash-table {
width: 100%; border-collapse: collapse; margin-bottom: 16px;
}
.dash-table th {
text-align: left; font-size: 0.7rem; font-weight: 600; color: var(--text-secondary);
text-transform: uppercase; letter-spacing: 0.08em; padding: 10px 12px;
border-bottom: 1px solid rgba(255,255,255,0.06);
}
.dash-table td {
padding: 12px; font-size: 0.8rem; color: var(--text-secondary);
border-bottom: 1px solid rgba(255,255,255,0.04);
}
.dash-table tr:hover td { background: rgba(255,255,255,0.02); }
.score-badge {
display: inline-flex; align-items: center; gap: 4px;
padding: 3px 10px; border-radius: 100px; font-size: 0.7rem; font-weight: 700;
}
.score-badge.high { background: rgba(16,185,129,0.15); color: #10b981; }
.score-badge.mid { background: rgba(245,158,11,0.15); color: #f59e0b; }
.score-badge.low { background: rgba(239,68,68,0.15); color: #ef4444; }
.prop-name { color: var(--text-primary); font-weight: 600; }
/* Map mockup */
.dash-map {
background: rgba(255,255,255,0.02); border: 1px solid rgba(255,255,255,0.06);
border-radius: 10px; height: 140px; position: relative; overflow: hidden;
}
/* Grid lines for map feel */
.dash-map::before {
content: '';
position: absolute; top: 0; left: 0; right: 0; bottom: 0;
background:
linear-gradient(rgba(16,185,129,0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(16,185,129,0.03) 1px, transparent 1px);
background-size: 30px 30px;
}
.map-pin {
position: absolute; width: 10px; height: 10px; border-radius: 50%;
border: 2px solid; transform: translate(-50%, -50%);
}
.map-pin::after {
content: ''; position: absolute; width: 20px; height: 20px;
border-radius: 50%; top: -5px; left: -5px;
animation: ping 2s ease-out infinite;
}
.map-pin.high { border-color: #10b981; background: rgba(16,185,129,0.3); }
.map-pin.high::after { background: rgba(16,185,129,0.15); }
.map-pin.mid { border-color: #f59e0b; background: rgba(245,158,11,0.3); }
.map-pin.mid::after { background: rgba(245,158,11,0.15); }
.map-pin.low { border-color: #ef4444; background: rgba(239,68,68,0.3); }
.map-pin.low::after { background: rgba(239,68,68,0.15); }
.map-label {
position: absolute; bottom: 8px; right: 12px;
font-size: 0.7rem; color: var(--text-secondary); opacity: 0.5;
}
.cta { text-align: center; padding: 80px 0; animation: fadeInUp 0.6s ease-out both; animation-delay: 0.3s; }
.cta h2 { font-size: 2rem; font-weight: 700; margin-bottom: 12px; letter-spacing: -0.02em; }
.cta p { color: var(--text-secondary); margin-bottom: 28px; font-size: 1.05rem; }
.cta-btn {
display: inline-flex; align-items: center; gap: 8px;
padding: 14px 32px; border-radius: 12px;
background: linear-gradient(135deg, var(--accent), var(--accent-dark));
color: #000; font-weight: 700; font-size: 1rem;
text-decoration: none; transition: transform 0.2s, box-shadow 0.2s;
}
.cta-btn:hover { transform: translateY(-2px); box-shadow: 0 8px 30px rgba(16,185,129,0.3); }
.footer { text-align: center; padding: 40px 0; border-top: 1px solid var(--border-color); }
.footer .badge {
display: inline-flex; align-items: center; gap: 6px;
padding: 6px 14px; border-radius: 8px;
background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06);
font-size: 12px; color: var(--text-secondary);
}
@keyframes fadeInUp { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: translateY(0); } }
@keyframes ping { 0% { transform: scale(1); opacity: 0.6; } 100% { transform: scale(2.5); opacity: 0; } }
@media (max-width: 768px) {
.hero { padding: 40px 0 50px; }
.flow { grid-template-columns: repeat(3, 1fr); gap: 8px; }
.flow-step:nth-child(3)::after, .flow-step:nth-child(6)::after { display: none; }
.results-grid { grid-template-columns: repeat(2, 1fr); }
.dash-top { grid-template-columns: repeat(2, 1fr); }
.dash-table { font-size: 0.75rem; }
.section h2 { font-size: 1.4rem; }
}
@media (max-width: 480px) {
.flow { grid-template-columns: 1fr 1fr; }
.results-grid { grid-template-columns: 1fr; }
.dash-top { grid-template-columns: 1fr 1fr; }
}
</style>
</head>
<body>
<div class="container">
<a href="index.html" class="back">← Back to Portfolio</a>
<section class="hero">
<div class="hero-label">🏢 Lead Gen Automation</div>
<h1>CREdispo — <span>CRE Lead Gen</span></h1>
<p class="hook">"Automated pipeline from property data to qualified leads"</p>
</section>
<section class="section">
<div class="section-label">The Challenge</div>
<h2>Manual Prospecting Is a Time Sink</h2>
<div class="glass">
<p>Commercial real estate investors waste hours manually searching for properties, cross-referencing owner info, and qualifying leads across <strong style="color:var(--text-primary)">multiple databases</strong>. The process is tedious, error-prone, and burns <strong style="color:var(--text-primary)">20+ hours per week</strong> that should be spent closing deals.</p>
</div>
</section>
<section class="section">
<div class="section-label">The Solution</div>
<h2>20 Hours → 2 Minutes</h2>
<p>Built an automated lead generation platform that handles the entire pipeline:</p>
<ul class="solution-list">
<li><span class="check"></span> Scrapes property databases automatically — no manual searching</li>
<li><span class="check"></span> Enriches records with owner contact information and financial data</li>
<li><span class="check"></span> AI scores leads based on custom investment criteria (cap rate, location, distress signals)</li>
<li><span class="check"></span> Queues outreach with personalized messaging templates</li>
<li><span class="check"></span> Dashboard for 2-minute daily review of top-scored leads</li>
</ul>
</section>
<section class="section">
<div class="section-label">How It Works</div>
<h2>End-to-End Pipeline</h2>
<div class="flow">
<div class="flow-step">
<div class="num">1</div>
<div class="icon">🏗️</div>
<div class="label">Property DBs</div>
<div class="sublabel">Data sources</div>
</div>
<div class="flow-step">
<div class="num">2</div>
<div class="icon">🤖</div>
<div class="label">Auto Scraping</div>
<div class="sublabel">Nightly runs</div>
</div>
<div class="flow-step">
<div class="num">3</div>
<div class="icon">📋</div>
<div class="label">Enrichment</div>
<div class="sublabel">Owner + contact</div>
</div>
<div class="flow-step">
<div class="num">4</div>
<div class="icon">🧠</div>
<div class="label">AI Scoring</div>
<div class="sublabel">Custom criteria</div>
</div>
<div class="flow-step">
<div class="num">5</div>
<div class="icon">📤</div>
<div class="label">Outreach Queue</div>
<div class="sublabel">Auto-personalized</div>
</div>
<div class="flow-step">
<div class="num">6</div>
<div class="icon">📊</div>
<div class="label">Dashboard</div>
<div class="sublabel">2-min review</div>
</div>
</div>
</section>
<section class="section">
<div class="section-label">Tech Stack</div>
<h2>Built With</h2>
<div class="tech-grid">
<span class="tech-pill">Next.js</span>
<span class="tech-pill">PostgreSQL</span>
<span class="tech-pill">Python (scraping)</span>
<span class="tech-pill">AI Scoring</span>
<span class="tech-pill">Reonomy API</span>
<span class="tech-pill">Cloudflare</span>
<span class="tech-pill">Cron Jobs</span>
</div>
</section>
<section class="section">
<div class="section-label">Results</div>
<h2>Impact at a Glance</h2>
<div class="results-grid">
<div class="result-card">
<div class="number">2 min</div>
<div class="label">Daily Review (was 20hrs/wk)</div>
</div>
<div class="result-card">
<div class="number">500+</div>
<div class="label">Leads Per Run</div>
</div>
<div class="result-card">
<div class="number">AI</div>
<div class="label">Scored Lead Quality</div>
</div>
<div class="result-card">
<div class="number">Auto</div>
<div class="label">Outreach Pipeline</div>
</div>
</div>
</section>
<section class="section">
<div class="section-label">Product Preview</div>
<h2>The Dashboard</h2>
<div class="mockup-container">
<div class="mockup-titlebar">
<span class="mockup-dot r"></span>
<span class="mockup-dot y"></span>
<span class="mockup-dot g"></span>
<div class="mockup-url-bar">credispo.app/dashboard</div>
</div>
<!-- Stats row -->
<div class="dash-top">
<div class="dash-stat">
<div class="ds-num">547</div>
<div class="ds-label">Total Leads</div>
</div>
<div class="dash-stat">
<div class="ds-num">84</div>
<div class="ds-label">Hot Leads</div>
</div>
<div class="dash-stat">
<div class="ds-num">23</div>
<div class="ds-label">In Outreach</div>
</div>
<div class="dash-stat">
<div class="ds-num">7</div>
<div class="ds-label">Responded</div>
</div>
</div>
<!-- Table -->
<table class="dash-table">
<thead>
<tr>
<th>Property</th>
<th>Type</th>
<th>Owner</th>
<th>Score</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td class="prop-name">1420 Commerce Blvd</td>
<td>Office</td>
<td>Smith Holdings LLC</td>
<td><span class="score-badge high">● 94</span></td>
<td style="color:var(--accent);">Ready</td>
</tr>
<tr>
<td class="prop-name">890 Industrial Pkwy</td>
<td>Warehouse</td>
<td>Pacific Realty Group</td>
<td><span class="score-badge high">● 87</span></td>
<td style="color:var(--accent);">Ready</td>
</tr>
<tr>
<td class="prop-name">2200 Market St</td>
<td>Retail</td>
<td>Chen Family Trust</td>
<td><span class="score-badge mid">● 72</span></td>
<td style="color:#f59e0b;">Enriching</td>
</tr>
<tr>
<td class="prop-name">455 Tech Center Dr</td>
<td>Office</td>
<td>Vanguard Properties</td>
<td><span class="score-badge mid">● 65</span></td>
<td style="color:#f59e0b;">Enriching</td>
</tr>
<tr>
<td class="prop-name">3100 Riverside Ave</td>
<td>Mixed Use</td>
<td>River Bend Inv.</td>
<td><span class="score-badge low">● 34</span></td>
<td style="color:var(--text-secondary);">Low Priority</td>
</tr>
</tbody>
</table>
<!-- Map -->
<div class="dash-map">
<div class="map-pin high" style="top:25%;left:30%;"></div>
<div class="map-pin high" style="top:40%;left:55%;"></div>
<div class="map-pin mid" style="top:60%;left:35%;"></div>
<div class="map-pin mid" style="top:30%;left:70%;"></div>
<div class="map-pin low" style="top:70%;left:65%;"></div>
<div class="map-pin high" style="top:45%;left:20%;"></div>
<div class="map-pin low" style="top:55%;left:80%;"></div>
<div class="map-pin mid" style="top:20%;left:45%;"></div>
<span class="map-label">Property locations — scored by AI</span>
</div>
</div>
</section>
<section class="cta">
<h2>Want something like this?</h2>
<p>Let's automate your lead generation pipeline.</p>
<a href="mailto:hello@example.com" class="cta-btn">Get in Touch →</a>
</section>
<footer class="footer">
<div class="badge">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
Built with Claude Code
</div>
</footer>
</div>
</body>
</html>

433
genre-universe.html Normal file
View File

@ -0,0 +1,433 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Genre Universe — Interactive Artist Visualization Case Study</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--accent: #ec4899;
--accent-dark: #be185d;
--accent-glow: rgba(236,72,153,0.15);
--bg-primary: #0a0a0a;
--bg-secondary: #111827;
--text-primary: #f1f5f9;
--text-secondary: #94a3b8;
--border-color: rgba(255,255,255,0.08);
--glass-bg: rgba(255,255,255,0.03);
--glass-border: rgba(255,255,255,0.06);
}
html { scroll-behavior: smooth; }
body {
font-family: 'Inter', -apple-system, sans-serif;
background: linear-gradient(135deg, var(--bg-primary) 0%, #0d0a14 50%, #0a0d18 100%);
color: var(--text-primary); min-height: 100vh; line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
body::before {
content: ''; position: fixed; top: 0; left: 0; right: 0; bottom: 0;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.03'/%3E%3C/svg%3E");
pointer-events: none; z-index: 0;
}
.container { max-width: 900px; margin: 0 auto; padding: 0 24px; position: relative; z-index: 1; }
.back {
display: inline-flex; align-items: center; gap: 8px;
padding: 20px 0; color: var(--text-secondary); text-decoration: none;
font-size: 0.9rem; font-weight: 500; transition: color 0.2s;
}
.back:hover { color: var(--accent); }
.hero { text-align: center; padding: 60px 0 80px; animation: fadeInUp 0.8s ease-out; }
.hero-label {
display: inline-flex; align-items: center; gap: 8px;
padding: 6px 16px; border-radius: 100px;
background: var(--accent-glow); border: 1px solid rgba(236,72,153,0.2);
font-size: 12px; font-weight: 600; color: var(--accent);
text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 24px;
}
.hero h1 { font-size: clamp(2.2rem, 5vw, 3.5rem); font-weight: 800; line-height: 1.1; letter-spacing: -0.03em; margin-bottom: 16px; }
.hero h1 span {
background: linear-gradient(135deg, var(--accent), #f472b6, #a855f7);
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
}
.hero .hook { font-size: 1.25rem; color: var(--text-secondary); font-style: italic; font-weight: 300; }
.section { padding: 60px 0; animation: fadeInUp 0.6s ease-out both; }
.section-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em; color: var(--accent); margin-bottom: 12px; }
.section h2 { font-size: 1.8rem; font-weight: 700; margin-bottom: 16px; letter-spacing: -0.02em; }
.section p { color: var(--text-secondary); font-size: 1.05rem; line-height: 1.8; max-width: 700px; }
.glass { background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: 16px; padding: 32px; backdrop-filter: blur(10px); }
.solution-list { list-style: none; margin-top: 20px; }
.solution-list li { padding: 12px 0; border-bottom: 1px solid var(--border-color); color: var(--text-secondary); font-size: 1rem; display: flex; align-items: flex-start; gap: 12px; }
.solution-list li:last-child { border-bottom: none; }
.solution-list .check { color: var(--accent); font-weight: 700; font-size: 1.1rem; flex-shrink: 0; }
/* Flow */
.flow { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; margin-top: 24px; }
.flow-step {
background: var(--glass-bg); border: 1px solid var(--glass-border);
border-radius: 14px; padding: 20px 14px; text-align: center;
position: relative; transition: border-color 0.3s, transform 0.3s;
}
.flow-step:hover { border-color: rgba(236,72,153,0.3); transform: translateY(-3px); }
.flow-step .num {
width: 28px; height: 28px; border-radius: 50%;
background: var(--accent-glow); border: 1px solid rgba(236,72,153,0.3);
display: flex; align-items: center; justify-content: center;
font-size: 12px; font-weight: 700; color: var(--accent); margin: 0 auto 12px;
}
.flow-step .icon { font-size: 24px; margin-bottom: 8px; }
.flow-step .label { font-size: 0.8rem; font-weight: 600; color: var(--text-primary); line-height: 1.3; }
.flow-step .sublabel { font-size: 0.7rem; color: var(--text-secondary); margin-top: 4px; }
.flow-step:not(:last-child)::after {
content: '→'; position: absolute; right: -16px; top: 50%;
transform: translateY(-50%); color: var(--accent); font-size: 14px; opacity: 0.5;
}
.tech-grid { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.tech-pill {
padding: 8px 18px; border-radius: 100px;
background: var(--glass-bg); border: 1px solid var(--glass-border);
font-size: 0.85rem; font-weight: 500; color: var(--text-secondary);
transition: border-color 0.2s, color 0.2s;
}
.tech-pill:hover { border-color: rgba(236,72,153,0.3); color: var(--accent); }
.results-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 16px; margin-top: 24px; }
.result-card {
background: var(--glass-bg); border: 1px solid var(--glass-border);
border-radius: 16px; padding: 28px 16px; text-align: center;
transition: border-color 0.3s, transform 0.3s;
}
.result-card:hover { border-color: rgba(236,72,153,0.3); transform: translateY(-3px); }
.result-card .number {
font-size: 1.8rem; font-weight: 800; letter-spacing: -0.03em;
background: linear-gradient(135deg, var(--accent), #f472b6);
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
margin-bottom: 6px;
}
.result-card .label { font-size: 0.75rem; color: var(--text-secondary); font-weight: 500; }
/* 3D Space Mockup */
.mockup-container {
margin-top: 24px; border-radius: 16px; overflow: hidden;
background: radial-gradient(ellipse at center, #0d0a18 0%, #050308 70%);
border: 1px solid var(--glass-border); padding: 24px;
position: relative; min-height: 500px;
}
.mockup-titlebar { display: flex; align-items: center; gap: 8px; margin-bottom: 24px; position: relative; z-index: 5; }
.mockup-dot { width: 12px; height: 12px; border-radius: 50%; }
.mockup-dot.r { background: #ef4444; } .mockup-dot.y { background: #f59e0b; } .mockup-dot.g { background: #10b981; }
.mockup-url-bar {
flex: 1; margin-left: 16px; height: 36px; border-radius: 8px;
background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.1);
display: flex; align-items: center; padding: 0 14px; font-size: 13px; color: var(--text-secondary);
}
/* Starfield + Nodes */
.space-scene { position: relative; width: 100%; height: 420px; overflow: hidden; }
/* Stars */
.star {
position: absolute; border-radius: 50%; background: white;
animation: twinkle 3s ease-in-out infinite alternate;
}
/* Artist nodes */
.artist-node {
position: absolute; border-radius: 50%;
display: flex; align-items: center; justify-content: center;
transition: transform 0.3s;
z-index: 3;
}
.artist-node:hover { transform: scale(1.3); z-index: 10; }
.artist-node .glow {
position: absolute; width: 200%; height: 200%; border-radius: 50%;
opacity: 0.3; filter: blur(10px);
}
.artist-label {
position: absolute; white-space: nowrap;
font-size: 10px; font-weight: 600; color: rgba(255,255,255,0.7);
pointer-events: none; letter-spacing: 0.02em;
}
/* Connection lines */
.conn-line {
position: absolute; height: 1px; transform-origin: left center;
background: linear-gradient(90deg, rgba(236,72,153,0.2), rgba(168,85,247,0.1));
z-index: 1;
}
/* Axis labels */
.axis-label {
position: absolute; font-size: 10px; font-weight: 600;
color: rgba(255,255,255,0.2); text-transform: uppercase; letter-spacing: 0.1em;
z-index: 4;
}
/* Legend */
.legend {
position: absolute; bottom: 12px; right: 12px; z-index: 5;
display: flex; gap: 14px;
}
.legend-item { display: flex; align-items: center; gap: 6px; font-size: 10px; color: var(--text-secondary); }
.legend-dot { width: 8px; height: 8px; border-radius: 50%; }
.cta { text-align: center; padding: 80px 0; animation: fadeInUp 0.6s ease-out both; animation-delay: 0.3s; }
.cta h2 { font-size: 2rem; font-weight: 700; margin-bottom: 12px; letter-spacing: -0.02em; }
.cta p { color: var(--text-secondary); margin-bottom: 28px; font-size: 1.05rem; }
.cta-btn {
display: inline-flex; align-items: center; gap: 8px;
padding: 14px 32px; border-radius: 12px;
background: linear-gradient(135deg, var(--accent), var(--accent-dark));
color: white; font-weight: 700; font-size: 1rem;
text-decoration: none; transition: transform 0.2s, box-shadow 0.2s;
}
.cta-btn:hover { transform: translateY(-2px); box-shadow: 0 8px 30px rgba(236,72,153,0.3); }
.footer { text-align: center; padding: 40px 0; border-top: 1px solid var(--border-color); }
.footer .badge {
display: inline-flex; align-items: center; gap: 6px;
padding: 6px 14px; border-radius: 8px;
background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06);
font-size: 12px; color: var(--text-secondary);
}
@keyframes fadeInUp { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: translateY(0); } }
@keyframes twinkle { from { opacity: 0.3; } to { opacity: 1; } }
@keyframes float { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@media (max-width: 768px) {
.hero { padding: 40px 0 50px; }
.flow { grid-template-columns: 1fr; gap: 8px; }
.flow-step:not(:last-child)::after { content: '↓'; right: auto; left: 50%; top: auto; bottom: -14px; transform: translateX(-50%); }
.results-grid { grid-template-columns: repeat(2, 1fr); }
.space-scene { height: 300px; }
.section h2 { font-size: 1.4rem; }
}
@media (max-width: 480px) { .results-grid { grid-template-columns: 1fr; } }
</style>
</head>
<body>
<div class="container">
<a href="index.html" class="back">← Back to Portfolio</a>
<section class="hero">
<div class="hero-label">🌌 Data Visualization + 3D</div>
<h1>3D Genre <span>Universe</span></h1>
<p class="hook">"56 artists mapped across 6 audio dimensions in 3D space"</p>
</section>
<section class="section">
<div class="section-label">The Challenge</div>
<h2>Where Do You Fit in the Genre Landscape?</h2>
<div class="glass">
<p>An electronic music artist needed to understand where they fit in the genre landscape relative to peers — for <strong style="color:var(--text-primary)">playlist pitching, branding, and identifying collaboration opportunities</strong>. Traditional genre categorization is flat and subjective. Music lives in a multi-dimensional space that's impossible to see without the right tools.</p>
</div>
</section>
<section class="section">
<div class="section-label">The Solution</div>
<h2>An Interactive 3D Galaxy of Sound</h2>
<p>Built an interactive 3D visualization using Three.js that maps artists across multiple audio dimensions:</p>
<ul class="solution-list">
<li><span class="check"></span> <strong>3 primary axes:</strong> Valence (happy↔sad), Tempo (slow↔fast), Electronic↔Organic</li>
<li><span class="check"></span> <strong>6 spike extensions</strong> per artist: energy, danceability, emotional depth, lyrical complexity, acousticness, production density</li>
<li><span class="check"></span> All data pulled from <strong>Spotify's audio features API</strong> — real data, not guesswork</li>
<li><span class="check"></span> UnrealBloom post-processing for gorgeous glow effects</li>
<li><span class="check"></span> Full orbit controls — zoom, pan, rotate the entire universe</li>
</ul>
</section>
<section class="section">
<div class="section-label">How It Works</div>
<h2>Data → 3D Universe</h2>
<div class="flow">
<div class="flow-step">
<div class="num">1</div>
<div class="icon">🎵</div>
<div class="label">Spotify API</div>
<div class="sublabel">Audio features</div>
</div>
<div class="flow-step">
<div class="num">2</div>
<div class="icon">📊</div>
<div class="label">Feature Extraction</div>
<div class="sublabel">6 dimensions</div>
</div>
<div class="flow-step">
<div class="num">3</div>
<div class="icon">📐</div>
<div class="label">3D Positioning</div>
<div class="sublabel">Algorithm</div>
</div>
<div class="flow-step">
<div class="num">4</div>
<div class="icon"></div>
<div class="label">Three.js Scene</div>
<div class="sublabel">Interactive</div>
</div>
<div class="flow-step">
<div class="num">5</div>
<div class="icon">🌟</div>
<div class="label">Bloom Effects</div>
<div class="sublabel">Post-processing</div>
</div>
</div>
</section>
<section class="section">
<div class="section-label">Tech Stack</div>
<h2>Built With</h2>
<div class="tech-grid">
<span class="tech-pill">Three.js</span>
<span class="tech-pill">Spotify API</span>
<span class="tech-pill">Python</span>
<span class="tech-pill">OrbitControls</span>
<span class="tech-pill">UnrealBloomPass</span>
<span class="tech-pill">CSS2DRenderer</span>
<span class="tech-pill">WebGL</span>
</div>
</section>
<section class="section">
<div class="section-label">Results</div>
<h2>Impact at a Glance</h2>
<div class="results-grid">
<div class="result-card">
<div class="number">56</div>
<div class="label">Artists Mapped</div>
</div>
<div class="result-card">
<div class="number">6</div>
<div class="label">Audio Dimensions</div>
</div>
<div class="result-card">
<div class="number">3D</div>
<div class="label">Interactive Exploration</div>
</div>
<div class="result-card">
<div class="number">Real</div>
<div class="label">Spotify Data</div>
</div>
<div class="result-card">
<div class="number">12</div>
<div class="label">Collaborators Found</div>
</div>
</div>
</section>
<section class="section">
<div class="section-label">Product Preview</div>
<h2>The 3D Universe</h2>
<div class="mockup-container">
<div class="mockup-titlebar">
<span class="mockup-dot r"></span>
<span class="mockup-dot y"></span>
<span class="mockup-dot g"></span>
<div class="mockup-url-bar">genre-universe.app — 56 artists loaded</div>
</div>
<div class="space-scene">
<!-- Stars -->
<div class="star" style="width:1px;height:1px;top:8%;left:12%;animation-delay:0s;"></div>
<div class="star" style="width:2px;height:2px;top:15%;left:45%;animation-delay:0.5s;"></div>
<div class="star" style="width:1px;height:1px;top:22%;left:78%;animation-delay:1s;"></div>
<div class="star" style="width:1px;height:1px;top:35%;left:23%;animation-delay:1.5s;"></div>
<div class="star" style="width:2px;height:2px;top:48%;left:67%;animation-delay:0.3s;"></div>
<div class="star" style="width:1px;height:1px;top:55%;left:88%;animation-delay:0.8s;"></div>
<div class="star" style="width:1px;height:1px;top:62%;left:34%;animation-delay:1.2s;"></div>
<div class="star" style="width:2px;height:2px;top:75%;left:56%;animation-delay:0.6s;"></div>
<div class="star" style="width:1px;height:1px;top:82%;left:15%;animation-delay:1.8s;"></div>
<div class="star" style="width:1px;height:1px;top:88%;left:72%;animation-delay:0.2s;"></div>
<div class="star" style="width:1px;height:1px;top:5%;left:60%;animation-delay:2s;"></div>
<div class="star" style="width:1px;height:1px;top:42%;left:5%;animation-delay:1.1s;"></div>
<div class="star" style="width:2px;height:2px;top:70%;left:90%;animation-delay:0.4s;"></div>
<div class="star" style="width:1px;height:1px;top:30%;left:50%;animation-delay:1.6s;"></div>
<div class="star" style="width:1px;height:1px;top:92%;left:40%;animation-delay:0.9s;"></div>
<!-- Connection lines -->
<div class="conn-line" style="top:28%;left:18%;width:180px;transform:rotate(20deg);"></div>
<div class="conn-line" style="top:45%;left:35%;width:120px;transform:rotate(-15deg);"></div>
<div class="conn-line" style="top:60%;left:50%;width:160px;transform:rotate(30deg);"></div>
<div class="conn-line" style="top:35%;left:55%;width:100px;transform:rotate(-35deg);"></div>
<div class="conn-line" style="top:50%;left:20%;width:140px;transform:rotate(10deg);"></div>
<div class="conn-line" style="top:70%;left:40%;width:110px;transform:rotate(-20deg);"></div>
<div class="conn-line" style="top:25%;left:65%;width:90px;transform:rotate(45deg);"></div>
<!-- Artist nodes — varied sizes/colors -->
<div class="artist-node" style="width:36px;height:36px;top:20%;left:15%;background:radial-gradient(circle,#ec4899,#be185d);box-shadow:0 0 20px rgba(236,72,153,0.5);animation:float 4s ease-in-out infinite;">
<div class="glow" style="background:#ec4899;"></div>
<span class="artist-label" style="top:-18px;left:50%;transform:translateX(-50%);">Odesza</span>
</div>
<div class="artist-node" style="width:28px;height:28px;top:35%;left:30%;background:radial-gradient(circle,#a855f7,#7c3aed);box-shadow:0 0 15px rgba(168,85,247,0.5);animation:float 5s ease-in-out infinite 0.5s;">
<div class="glow" style="background:#a855f7;"></div>
<span class="artist-label" style="top:-18px;left:50%;transform:translateX(-50%);">Flume</span>
</div>
<div class="artist-node" style="width:44px;height:44px;top:45%;left:50%;background:radial-gradient(circle,#f472b6,#ec4899);box-shadow:0 0 30px rgba(244,114,182,0.6);animation:float 3.5s ease-in-out infinite 1s;">
<div class="glow" style="background:#f472b6;"></div>
<span class="artist-label" style="top:-18px;left:50%;transform:translateX(-50%);font-size:12px;color:rgba(255,255,255,0.9);">Your Artist</span>
</div>
<div class="artist-node" style="width:22px;height:22px;top:28%;left:65%;background:radial-gradient(circle,#818cf8,#6366f1);box-shadow:0 0 12px rgba(129,140,248,0.4);animation:float 4.5s ease-in-out infinite 0.3s;">
<div class="glow" style="background:#818cf8;"></div>
<span class="artist-label" style="top:-16px;left:50%;transform:translateX(-50%);">Bonobo</span>
</div>
<div class="artist-node" style="width:30px;height:30px;top:60%;left:25%;background:radial-gradient(circle,#c084fc,#a855f7);box-shadow:0 0 18px rgba(192,132,252,0.5);animation:float 5.5s ease-in-out infinite 0.8s;">
<div class="glow" style="background:#c084fc;"></div>
<span class="artist-label" style="top:-18px;left:50%;transform:translateX(-50%);">Tycho</span>
</div>
<div class="artist-node" style="width:18px;height:18px;top:70%;left:70%;background:radial-gradient(circle,#fb7185,#e11d48);box-shadow:0 0 10px rgba(251,113,133,0.4);animation:float 6s ease-in-out infinite 1.2s;">
<div class="glow" style="background:#fb7185;"></div>
<span class="artist-label" style="top:-16px;left:50%;transform:translateX(-50%);">Rufus</span>
</div>
<div class="artist-node" style="width:24px;height:24px;top:15%;left:80%;background:radial-gradient(circle,#34d399,#10b981);box-shadow:0 0 14px rgba(52,211,153,0.4);animation:float 4s ease-in-out infinite 1.5s;">
<div class="glow" style="background:#34d399;"></div>
<span class="artist-label" style="top:-16px;left:50%;transform:translateX(-50%);">Caribou</span>
</div>
<div class="artist-node" style="width:20px;height:20px;top:80%;left:45%;background:radial-gradient(circle,#fbbf24,#f59e0b);box-shadow:0 0 12px rgba(251,191,36,0.4);animation:float 5s ease-in-out infinite 0.2s;">
<div class="glow" style="background:#fbbf24;"></div>
<span class="artist-label" style="top:-16px;left:50%;transform:translateX(-50%);">Four Tet</span>
</div>
<div class="artist-node" style="width:16px;height:16px;top:50%;left:85%;background:radial-gradient(circle,#60a5fa,#3b82f6);box-shadow:0 0 8px rgba(96,165,250,0.4);animation:float 4.2s ease-in-out infinite 0.7s;">
<div class="glow" style="background:#60a5fa;"></div>
<span class="artist-label" style="top:-16px;left:50%;transform:translateX(-50%);">Jamie xx</span>
</div>
<div class="artist-node" style="width:26px;height:26px;top:38%;left:10%;background:radial-gradient(circle,#f9a8d4,#ec4899);box-shadow:0 0 14px rgba(249,168,212,0.4);animation:float 3.8s ease-in-out infinite 1.1s;">
<div class="glow" style="background:#f9a8d4;"></div>
<span class="artist-label" style="top:-16px;left:50%;transform:translateX(-50%);">Petit Biscuit</span>
</div>
<!-- Axis labels -->
<div class="axis-label" style="bottom:4px;left:4px;">← Sad</div>
<div class="axis-label" style="bottom:4px;right:4px;">Happy →</div>
<div class="axis-label" style="top:4px;left:4px;">Electronic ↑</div>
<div class="axis-label" style="top:4px;right:4px;">Organic ↑</div>
<!-- Legend -->
<div class="legend">
<div class="legend-item"><div class="legend-dot" style="background:#ec4899;"></div>High energy</div>
<div class="legend-item"><div class="legend-dot" style="background:#a855f7;"></div>Mid energy</div>
<div class="legend-item"><div class="legend-dot" style="background:#60a5fa;"></div>Low energy</div>
</div>
</div>
</div>
</section>
<section class="cta">
<h2>Want something like this?</h2>
<p>Let's create stunning data visualizations for your project.</p>
<a href="mailto:hello@example.com" class="cta-btn">Get in Touch →</a>
</section>
<footer class="footer">
<div class="badge">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
Built with Claude Code
</div>
</footer>
</div>
</body>
</html>

389
index.html Normal file
View File

@ -0,0 +1,389 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Jake Shore — AI & Full-Stack Case Studies</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--bg-primary: #0a0a0a;
--bg-secondary: #111827;
--text-primary: #f1f5f9;
--text-secondary: #94a3b8;
--border-color: rgba(255,255,255,0.08);
--glass-bg: rgba(255,255,255,0.03);
--glass-border: rgba(255,255,255,0.06);
}
html { scroll-behavior: smooth; }
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
background: linear-gradient(135deg, var(--bg-primary) 0%, var(--bg-secondary) 50%, #0d1520 100%);
color: var(--text-primary);
min-height: 100vh;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
/* Noise texture overlay */
body::before {
content: '';
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.03'/%3E%3C/svg%3E");
pointer-events: none;
z-index: 0;
}
.container { max-width: 1200px; margin: 0 auto; padding: 0 24px; position: relative; z-index: 1; }
/* Hero */
.hero {
text-align: center;
padding: 100px 0 60px;
animation: fadeInUp 0.8s ease-out;
}
.hero-badge {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 20px;
border-radius: 100px;
background: var(--glass-bg);
border: 1px solid var(--glass-border);
font-size: 13px;
color: var(--text-secondary);
margin-bottom: 32px;
backdrop-filter: blur(10px);
}
.hero-badge .dot {
width: 8px; height: 8px;
border-radius: 50%;
background: #10b981;
animation: pulse 2s ease-in-out infinite;
}
.hero h1 {
font-size: clamp(2.5rem, 5vw, 4rem);
font-weight: 800;
line-height: 1.1;
letter-spacing: -0.03em;
margin-bottom: 20px;
}
.hero h1 span {
background: linear-gradient(135deg, #00d4ff, #8b5cf6, #ec4899);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero p {
font-size: 1.15rem;
color: var(--text-secondary);
max-width: 600px;
margin: 0 auto;
line-height: 1.7;
}
/* Grid */
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 24px;
padding: 40px 0 100px;
}
/* Card */
.card {
position: relative;
background: var(--glass-bg);
border: 1px solid var(--glass-border);
border-radius: 20px;
overflow: hidden;
transition: transform 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
backdrop-filter: blur(10px);
animation: fadeInUp 0.6s ease-out both;
text-decoration: none;
color: inherit;
display: block;
}
.card:nth-child(1) { animation-delay: 0.1s; }
.card:nth-child(2) { animation-delay: 0.2s; }
.card:nth-child(3) { animation-delay: 0.3s; }
.card:nth-child(4) { animation-delay: 0.4s; }
.card:nth-child(5) { animation-delay: 0.5s; }
.card:hover {
transform: translateY(-6px);
box-shadow: 0 20px 60px rgba(0,0,0,0.4);
}
.card:hover .card-stripe { opacity: 1; }
.card:hover .card-arrow { transform: translateX(4px); }
.card-stripe {
position: absolute;
top: 0; left: 0; right: 0;
height: 3px;
opacity: 0.7;
transition: opacity 0.3s ease;
}
.card-body { padding: 32px; }
.card-icon {
width: 48px; height: 48px;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
font-size: 22px;
margin-bottom: 20px;
}
.card h2 {
font-size: 1.35rem;
font-weight: 700;
margin-bottom: 8px;
letter-spacing: -0.02em;
}
.card .hook {
font-size: 0.95rem;
color: var(--text-secondary);
margin-bottom: 20px;
line-height: 1.6;
font-style: italic;
}
.card .tech-pills {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin-bottom: 24px;
}
.card .pill {
font-size: 11px;
padding: 4px 10px;
border-radius: 100px;
background: rgba(255,255,255,0.05);
border: 1px solid rgba(255,255,255,0.08);
color: var(--text-secondary);
font-weight: 500;
}
.card-footer {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px 32px;
border-top: 1px solid var(--border-color);
}
.card-link {
font-size: 0.9rem;
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
}
.card-arrow {
transition: transform 0.3s ease;
font-size: 1.1rem;
}
.card-metric {
font-size: 0.8rem;
color: var(--text-secondary);
}
/* Card accent colors */
.card--cyan:hover { border-color: rgba(0,212,255,0.3); }
.card--cyan .card-stripe { background: linear-gradient(90deg, #00d4ff, #0099cc); }
.card--cyan .card-icon { background: rgba(0,212,255,0.1); color: #00d4ff; }
.card--cyan .card-link { color: #00d4ff; }
.card--purple:hover { border-color: rgba(139,92,246,0.3); }
.card--purple .card-stripe { background: linear-gradient(90deg, #8b5cf6, #6d28d9); }
.card--purple .card-icon { background: rgba(139,92,246,0.1); color: #8b5cf6; }
.card--purple .card-link { color: #8b5cf6; }
.card--amber:hover { border-color: rgba(245,158,11,0.3); }
.card--amber .card-stripe { background: linear-gradient(90deg, #f59e0b, #d97706); }
.card--amber .card-icon { background: rgba(245,158,11,0.1); color: #f59e0b; }
.card--amber .card-link { color: #f59e0b; }
.card--pink:hover { border-color: rgba(236,72,153,0.3); }
.card--pink .card-stripe { background: linear-gradient(90deg, #ec4899, #be185d); }
.card--pink .card-icon { background: rgba(236,72,153,0.1); color: #ec4899; }
.card--pink .card-link { color: #ec4899; }
.card--emerald:hover { border-color: rgba(16,185,129,0.3); }
.card--emerald .card-stripe { background: linear-gradient(90deg, #10b981, #059669); }
.card--emerald .card-icon { background: rgba(16,185,129,0.1); color: #10b981; }
.card--emerald .card-link { color: #10b981; }
/* Footer */
.footer {
text-align: center;
padding: 60px 0 40px;
border-top: 1px solid var(--border-color);
}
.footer p {
color: var(--text-secondary);
font-size: 0.85rem;
margin-bottom: 16px;
}
.footer .badge {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 14px;
border-radius: 8px;
background: rgba(255,255,255,0.03);
border: 1px solid rgba(255,255,255,0.06);
font-size: 12px;
color: var(--text-secondary);
}
.footer .badge svg { width: 14px; height: 14px; }
/* Animations */
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(24px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.5; transform: scale(0.8); }
}
/* Mobile */
@media (max-width: 768px) {
.hero { padding: 70px 0 40px; }
.grid { grid-template-columns: 1fr; gap: 16px; padding: 24px 0 60px; }
.card-body { padding: 24px; }
.card-footer { padding: 16px 24px; }
}
</style>
</head>
<body>
<div class="container">
<header class="hero">
<div class="hero-badge">
<span class="dot"></span>
Available for projects
</div>
<h1>AI-Powered Products,<br><span>Built at Speed</span></h1>
<p>Full-stack development meets AI engineering. From SaaS platforms to 3D visualizations — here's a selection of recent work.</p>
</header>
<div class="grid">
<!-- AI Ad Engine -->
<a href="ai-ad-engine.html" class="card card--cyan">
<div class="card-stripe"></div>
<div class="card-body">
<div class="card-icon"></div>
<h2>AI Ad Creative Engine</h2>
<p class="hook">"From URL to 6 ad formats in 60 seconds"</p>
<div class="tech-pills">
<span class="pill">Claude API</span>
<span class="pill">Node.js</span>
<span class="pill">Web Scraping</span>
<span class="pill">HTML/CSS</span>
</div>
</div>
<div class="card-footer">
<span class="card-link">View Case Study <span class="card-arrow"></span></span>
<span class="card-metric">60s generation</span>
</div>
</a>
<!-- MCP Integrations -->
<a href="mcp-integrations.html" class="card card--purple">
<div class="card-stripe"></div>
<div class="card-body">
<div class="card-icon">🔗</div>
<h2>30+ Enterprise AI Integrations</h2>
<p class="hook">"Connecting AI to every tool your business already uses"</p>
<div class="tech-pills">
<span class="pill">TypeScript</span>
<span class="pill">MCP Protocol</span>
<span class="pill">REST APIs</span>
<span class="pill">OAuth2</span>
</div>
</div>
<div class="card-footer">
<span class="card-link">View Case Study <span class="card-arrow"></span></span>
<span class="card-metric">1,500+ tools</span>
</div>
</a>
<!-- NicheQuiz -->
<a href="nichequiz.html" class="card card--amber">
<div class="card-stripe"></div>
<div class="card-body">
<div class="card-icon">🧠</div>
<h2>TheNicheQuiz.com — AI Quiz Platform</h2>
<p class="hook">"Full SaaS product from idea to live in one session"</p>
<div class="tech-pills">
<span class="pill">Next.js</span>
<span class="pill">PostgreSQL</span>
<span class="pill">Stripe</span>
<span class="pill">Claude API</span>
</div>
</div>
<div class="card-footer">
<span class="card-link">View Case Study <span class="card-arrow"></span></span>
<span class="card-metric">Idea → Live in 1 day</span>
</div>
</a>
<!-- Genre Universe -->
<a href="genre-universe.html" class="card card--pink">
<div class="card-stripe"></div>
<div class="card-body">
<div class="card-icon">🌌</div>
<h2>3D Genre Universe</h2>
<p class="hook">"56 artists mapped across 6 audio dimensions in 3D space"</p>
<div class="tech-pills">
<span class="pill">Three.js</span>
<span class="pill">Spotify API</span>
<span class="pill">Python</span>
<span class="pill">WebGL</span>
</div>
</div>
<div class="card-footer">
<span class="card-link">View Case Study <span class="card-arrow"></span></span>
<span class="card-metric">56 artists, 6D</span>
</div>
</a>
<!-- CREdispo -->
<a href="credispo.html" class="card card--emerald">
<div class="card-stripe"></div>
<div class="card-body">
<div class="card-icon">🏢</div>
<h2>CREdispo — CRE Lead Gen</h2>
<p class="hook">"Automated pipeline from property data to qualified leads"</p>
<div class="tech-pills">
<span class="pill">Next.js</span>
<span class="pill">PostgreSQL</span>
<span class="pill">Python</span>
<span class="pill">AI Scoring</span>
</div>
</div>
<div class="card-footer">
<span class="card-link">View Case Study <span class="card-arrow"></span></span>
<span class="card-metric">20hrs → 2min</span>
</div>
</a>
</div>
<footer class="footer">
<p>Want to see what I can build for you?</p>
<div class="badge">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
Built with Claude Code
</div>
</footer>
</div>
</body>
</html>

386
mcp-integrations.html Normal file
View File

@ -0,0 +1,386 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>30+ Enterprise AI Integrations — Case Study</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--accent: #8b5cf6;
--accent-dark: #6d28d9;
--accent-glow: rgba(139,92,246,0.15);
--bg-primary: #0a0a0a;
--bg-secondary: #111827;
--text-primary: #f1f5f9;
--text-secondary: #94a3b8;
--border-color: rgba(255,255,255,0.08);
--glass-bg: rgba(255,255,255,0.03);
--glass-border: rgba(255,255,255,0.06);
}
html { scroll-behavior: smooth; }
body {
font-family: 'Inter', -apple-system, sans-serif;
background: linear-gradient(135deg, var(--bg-primary) 0%, var(--bg-secondary) 50%, #0d1520 100%);
color: var(--text-primary); min-height: 100vh; line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
body::before {
content: ''; position: fixed; top: 0; left: 0; right: 0; bottom: 0;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.03'/%3E%3C/svg%3E");
pointer-events: none; z-index: 0;
}
.container { max-width: 900px; margin: 0 auto; padding: 0 24px; position: relative; z-index: 1; }
.back {
display: inline-flex; align-items: center; gap: 8px;
padding: 20px 0; color: var(--text-secondary); text-decoration: none;
font-size: 0.9rem; font-weight: 500; transition: color 0.2s;
}
.back:hover { color: var(--accent); }
.hero { text-align: center; padding: 60px 0 80px; animation: fadeInUp 0.8s ease-out; }
.hero-label {
display: inline-flex; align-items: center; gap: 8px;
padding: 6px 16px; border-radius: 100px;
background: var(--accent-glow); border: 1px solid rgba(139,92,246,0.2);
font-size: 12px; font-weight: 600; color: var(--accent);
text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 24px;
}
.hero h1 { font-size: clamp(2.2rem, 5vw, 3.5rem); font-weight: 800; line-height: 1.1; letter-spacing: -0.03em; margin-bottom: 16px; }
.hero h1 span {
background: linear-gradient(135deg, var(--accent), #a78bfa);
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
}
.hero .hook { font-size: 1.25rem; color: var(--text-secondary); font-style: italic; font-weight: 300; }
.section { padding: 60px 0; animation: fadeInUp 0.6s ease-out both; }
.section-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em; color: var(--accent); margin-bottom: 12px; }
.section h2 { font-size: 1.8rem; font-weight: 700; margin-bottom: 16px; letter-spacing: -0.02em; }
.section p { color: var(--text-secondary); font-size: 1.05rem; line-height: 1.8; max-width: 700px; }
.glass { background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: 16px; padding: 32px; backdrop-filter: blur(10px); }
.solution-list { list-style: none; margin-top: 20px; }
.solution-list li { padding: 12px 0; border-bottom: 1px solid var(--border-color); color: var(--text-secondary); font-size: 1rem; display: flex; align-items: flex-start; gap: 12px; }
.solution-list li:last-child { border-bottom: none; }
.solution-list .check { color: var(--accent); font-weight: 700; font-size: 1.1rem; flex-shrink: 0; }
/* Hub and spoke */
.hub-spoke { position: relative; width: 100%; max-width: 600px; margin: 40px auto; aspect-ratio: 1; }
.hub-center {
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
width: 100px; height: 100px; border-radius: 50%;
background: linear-gradient(135deg, var(--accent), var(--accent-dark));
display: flex; align-items: center; justify-content: center; flex-direction: column;
font-size: 28px; z-index: 2;
box-shadow: 0 0 60px rgba(139,92,246,0.4), 0 0 120px rgba(139,92,246,0.1);
}
.hub-center .hub-label { font-size: 10px; font-weight: 700; color: white; margin-top: 2px; letter-spacing: 0.05em; }
.spoke-node {
position: absolute; width: 72px; height: 72px; border-radius: 50%;
background: var(--glass-bg); border: 1px solid var(--glass-border);
display: flex; align-items: center; justify-content: center; flex-direction: column;
font-size: 11px; font-weight: 600; color: var(--text-secondary); text-align: center;
transform: translate(-50%, -50%);
transition: border-color 0.3s, transform 0.3s, box-shadow 0.3s;
backdrop-filter: blur(5px);
}
.spoke-node:hover {
border-color: rgba(139,92,246,0.4); transform: translate(-50%, -50%) scale(1.1);
box-shadow: 0 0 20px rgba(139,92,246,0.2);
}
.spoke-node .s-icon { font-size: 20px; margin-bottom: 2px; }
/* Connecting lines done via SVG */
.spoke-lines {
position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 0;
}
.spoke-lines line { stroke: rgba(139,92,246,0.15); stroke-width: 1; stroke-dasharray: 4 4; }
/* 12 nodes around circle */
.spoke-node:nth-child(1) { top: 5%; left: 50%; }
.spoke-node:nth-child(2) { top: 11%; left: 75%; }
.spoke-node:nth-child(3) { top: 27%; left: 92%; }
.spoke-node:nth-child(4) { top: 50%; left: 97%; }
.spoke-node:nth-child(5) { top: 73%; left: 92%; }
.spoke-node:nth-child(6) { top: 89%; left: 75%; }
.spoke-node:nth-child(7) { top: 95%; left: 50%; }
.spoke-node:nth-child(8) { top: 89%; left: 25%; }
.spoke-node:nth-child(9) { top: 73%; left: 8%; }
.spoke-node:nth-child(10) { top: 50%; left: 3%; }
.spoke-node:nth-child(11) { top: 27%; left: 8%; }
.spoke-node:nth-child(12) { top: 11%; left: 25%; }
/* Outer ring count badge */
.outer-badge {
display: inline-flex; align-items: center; gap: 6px; margin-top: 16px;
padding: 8px 20px; border-radius: 100px;
background: var(--accent-glow); border: 1px solid rgba(139,92,246,0.2);
font-size: 13px; font-weight: 600; color: var(--accent);
}
.tech-grid { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.tech-pill {
padding: 8px 18px; border-radius: 100px;
background: var(--glass-bg); border: 1px solid var(--glass-border);
font-size: 0.85rem; font-weight: 500; color: var(--text-secondary);
transition: border-color 0.2s, color 0.2s;
}
.tech-pill:hover { border-color: rgba(139,92,246,0.3); color: var(--accent); }
.results-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-top: 24px; }
.result-card {
background: var(--glass-bg); border: 1px solid var(--glass-border);
border-radius: 16px; padding: 28px 20px; text-align: center;
transition: border-color 0.3s, transform 0.3s;
}
.result-card:hover { border-color: rgba(139,92,246,0.3); transform: translateY(-3px); }
.result-card .number {
font-size: 2rem; font-weight: 800; letter-spacing: -0.03em;
background: linear-gradient(135deg, var(--accent), #a78bfa);
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
margin-bottom: 6px;
}
.result-card .label { font-size: 0.8rem; color: var(--text-secondary); font-weight: 500; }
/* Mockup: Hub-spoke diagram */
.mockup-container {
margin-top: 24px; border-radius: 16px; overflow: hidden;
background: linear-gradient(135deg, #0c0f1a, #13102a);
border: 1px solid var(--glass-border); padding: 32px;
}
.mockup-titlebar { display: flex; align-items: center; gap: 8px; margin-bottom: 24px; }
.mockup-dot { width: 12px; height: 12px; border-radius: 50%; }
.mockup-dot.r { background: #ef4444; } .mockup-dot.y { background: #f59e0b; } .mockup-dot.g { background: #10b981; }
.mockup-url-bar {
flex: 1; margin-left: 16px; height: 36px; border-radius: 8px;
background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.1);
display: flex; align-items: center; padding: 0 14px; font-size: 13px; color: var(--text-secondary);
}
/* Integration list mockup */
.int-list { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.int-item {
background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06);
border-radius: 10px; padding: 14px; display: flex; align-items: center; gap: 10px;
}
.int-icon {
width: 32px; height: 32px; border-radius: 8px;
display: flex; align-items: center; justify-content: center; font-size: 16px; flex-shrink: 0;
}
.int-info .int-name { font-size: 0.8rem; font-weight: 600; color: var(--text-primary); }
.int-info .int-tools { font-size: 0.7rem; color: var(--text-secondary); }
.int-status { margin-left: auto; width: 8px; height: 8px; border-radius: 50%; background: #10b981; flex-shrink: 0; }
.cta { text-align: center; padding: 80px 0; animation: fadeInUp 0.6s ease-out both; animation-delay: 0.3s; }
.cta h2 { font-size: 2rem; font-weight: 700; margin-bottom: 12px; letter-spacing: -0.02em; }
.cta p { color: var(--text-secondary); margin-bottom: 28px; font-size: 1.05rem; }
.cta-btn {
display: inline-flex; align-items: center; gap: 8px;
padding: 14px 32px; border-radius: 12px;
background: linear-gradient(135deg, var(--accent), var(--accent-dark));
color: white; font-weight: 700; font-size: 1rem;
text-decoration: none; transition: transform 0.2s, box-shadow 0.2s;
}
.cta-btn:hover { transform: translateY(-2px); box-shadow: 0 8px 30px rgba(139,92,246,0.3); }
.footer { text-align: center; padding: 40px 0; border-top: 1px solid var(--border-color); }
.footer .badge {
display: inline-flex; align-items: center; gap: 6px;
padding: 6px 14px; border-radius: 8px;
background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06);
font-size: 12px; color: var(--text-secondary);
}
@keyframes fadeInUp { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: translateY(0); } }
@media (max-width: 768px) {
.hero { padding: 40px 0 50px; }
.hub-spoke { max-width: 340px; }
.spoke-node { width: 56px; height: 56px; font-size: 9px; }
.spoke-node .s-icon { font-size: 16px; }
.hub-center { width: 76px; height: 76px; font-size: 22px; }
.results-grid { grid-template-columns: repeat(2, 1fr); }
.int-list { grid-template-columns: 1fr; }
.section h2 { font-size: 1.4rem; }
}
</style>
</head>
<body>
<div class="container">
<a href="index.html" class="back">← Back to Portfolio</a>
<section class="hero">
<div class="hero-label">🔗 Enterprise AI Infrastructure</div>
<h1>30+ Enterprise <span>AI Integrations</span></h1>
<p class="hook">"Connecting AI to every tool your business already uses"</p>
</section>
<section class="section">
<div class="section-label">The Challenge</div>
<h2>AI Is Isolated From Your Tools</h2>
<div class="glass">
<p>Businesses run on <strong style="color:var(--text-primary)">1020+ SaaS tools</strong> — but AI can't talk to any of them. Manual data entry between systems wastes <strong style="color:var(--text-primary)">20+ hours per week</strong>. Every "AI transformation" project stalls because the AI has no access to real business data.</p>
</div>
</section>
<section class="section">
<div class="section-label">The Solution</div>
<h2>MCP: AI Talks to Everything</h2>
<p>Built 30+ MCP (Model Context Protocol) server integrations that let AI agents directly control business tools:</p>
<ul class="solution-list">
<li><span class="check"></span> <strong>Stripe</strong> — Create invoices, check subscriptions, process refunds via AI</li>
<li><span class="check"></span> <strong>HubSpot</strong> — Update CRM records, log activities, manage deals hands-free</li>
<li><span class="check"></span> <strong>Salesforce</strong> — Query pipeline, update opportunities, generate reports</li>
<li><span class="check"></span> <strong>Notion</strong> — Create pages, update databases, manage project wikis</li>
<li><span class="check"></span> <strong>26+ more</strong> — Slack, GitHub, Linear, Jira, Google Workspace, and beyond</li>
</ul>
</section>
<section class="section">
<div class="section-label">How It Works</div>
<h2>Hub-and-Spoke Architecture</h2>
<div class="hub-spoke">
<svg class="spoke-lines" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet">
<line x1="50" y1="50" x2="50" y2="5" /><line x1="50" y1="50" x2="75" y2="11" />
<line x1="50" y1="50" x2="92" y2="27" /><line x1="50" y1="50" x2="97" y2="50" />
<line x1="50" y1="50" x2="92" y2="73" /><line x1="50" y1="50" x2="75" y2="89" />
<line x1="50" y1="50" x2="50" y2="95" /><line x1="50" y1="50" x2="25" y2="89" />
<line x1="50" y1="50" x2="8" y2="73" /><line x1="50" y1="50" x2="3" y2="50" />
<line x1="50" y1="50" x2="8" y2="27" /><line x1="50" y1="50" x2="25" y2="11" />
</svg>
<div class="spoke-node"><span class="s-icon">💳</span>Stripe</div>
<div class="spoke-node"><span class="s-icon">🟠</span>HubSpot</div>
<div class="spoke-node"><span class="s-icon">☁️</span>Salesforce</div>
<div class="spoke-node"><span class="s-icon">📝</span>Notion</div>
<div class="spoke-node"><span class="s-icon">💬</span>Slack</div>
<div class="spoke-node"><span class="s-icon">🐙</span>GitHub</div>
<div class="spoke-node"><span class="s-icon">📋</span>Linear</div>
<div class="spoke-node"><span class="s-icon">🎯</span>Jira</div>
<div class="spoke-node"><span class="s-icon">📧</span>Gmail</div>
<div class="spoke-node"><span class="s-icon">📊</span>Sheets</div>
<div class="spoke-node"><span class="s-icon">📁</span>Drive</div>
<div class="spoke-node"><span class="s-icon">📅</span>Calendar</div>
<div class="hub-center">
🧠
<span class="hub-label">AI + MCP</span>
</div>
</div>
<div style="text-align:center;">
<span class="outer-badge">+ 18 more integrations</span>
</div>
</section>
<section class="section">
<div class="section-label">Tech Stack</div>
<h2>Built With</h2>
<div class="tech-grid">
<span class="tech-pill">TypeScript</span>
<span class="tech-pill">MCP Protocol</span>
<span class="tech-pill">REST APIs</span>
<span class="tech-pill">OAuth2</span>
<span class="tech-pill">Node.js</span>
<span class="tech-pill">30+ SaaS APIs</span>
<span class="tech-pill">JSON-RPC</span>
<span class="tech-pill">Zod Validation</span>
</div>
</section>
<section class="section">
<div class="section-label">Results</div>
<h2>Impact at a Glance</h2>
<div class="results-grid">
<div class="result-card">
<div class="number">30+</div>
<div class="label">Integrations Built</div>
</div>
<div class="result-card">
<div class="number">1,500+</div>
<div class="label">AI-Callable Tools</div>
</div>
<div class="result-card">
<div class="number">20+</div>
<div class="label">Hrs/Week Saved</div>
</div>
<div class="result-card">
<div class="number">Any AI</div>
<div class="label">Claude, GPT, etc.</div>
</div>
</div>
</section>
<section class="section">
<div class="section-label">Product Preview</div>
<h2>Integration Dashboard</h2>
<div class="mockup-container">
<div class="mockup-titlebar">
<span class="mockup-dot r"></span>
<span class="mockup-dot y"></span>
<span class="mockup-dot g"></span>
<div class="mockup-url-bar">mcp-hub.app/integrations</div>
</div>
<div class="int-list">
<div class="int-item">
<div class="int-icon" style="background:rgba(99,102,241,0.1);">💳</div>
<div class="int-info"><div class="int-name">Stripe</div><div class="int-tools">47 tools</div></div>
<div class="int-status"></div>
</div>
<div class="int-item">
<div class="int-icon" style="background:rgba(249,115,22,0.1);">🟠</div>
<div class="int-info"><div class="int-name">HubSpot</div><div class="int-tools">62 tools</div></div>
<div class="int-status"></div>
</div>
<div class="int-item">
<div class="int-icon" style="background:rgba(59,130,246,0.1);">☁️</div>
<div class="int-info"><div class="int-name">Salesforce</div><div class="int-tools">58 tools</div></div>
<div class="int-status"></div>
</div>
<div class="int-item">
<div class="int-icon" style="background:rgba(255,255,255,0.05);">📝</div>
<div class="int-info"><div class="int-name">Notion</div><div class="int-tools">35 tools</div></div>
<div class="int-status"></div>
</div>
<div class="int-item">
<div class="int-icon" style="background:rgba(139,92,246,0.1);">💬</div>
<div class="int-info"><div class="int-name">Slack</div><div class="int-tools">28 tools</div></div>
<div class="int-status"></div>
</div>
<div class="int-item">
<div class="int-icon" style="background:rgba(255,255,255,0.05);">🐙</div>
<div class="int-info"><div class="int-name">GitHub</div><div class="int-tools">44 tools</div></div>
<div class="int-status"></div>
</div>
<div class="int-item">
<div class="int-icon" style="background:rgba(99,102,241,0.1);">📋</div>
<div class="int-info"><div class="int-name">Linear</div><div class="int-tools">31 tools</div></div>
<div class="int-status"></div>
</div>
<div class="int-item">
<div class="int-icon" style="background:rgba(59,130,246,0.1);">🎯</div>
<div class="int-info"><div class="int-name">Jira</div><div class="int-tools">39 tools</div></div>
<div class="int-status"></div>
</div>
<div class="int-item">
<div class="int-icon" style="background:rgba(234,179,8,0.1);">📊</div>
<div class="int-info"><div class="int-name">Google Sheets</div><div class="int-tools">22 tools</div></div>
<div class="int-status"></div>
</div>
</div>
</div>
</section>
<section class="cta">
<h2>Want something like this?</h2>
<p>Let's connect your AI to the tools your team already uses.</p>
<a href="mailto:hello@example.com" class="cta-btn">Get in Touch →</a>
</section>
<footer class="footer">
<div class="badge">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
Built with Claude Code
</div>
</footer>
</div>
</body>
</html>

373
nichequiz.html Normal file
View File

@ -0,0 +1,373 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TheNicheQuiz.com — AI Quiz Platform Case Study</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--accent: #f59e0b;
--accent-dark: #d97706;
--accent-glow: rgba(245,158,11,0.15);
--bg-primary: #0a0a0a;
--bg-secondary: #111827;
--text-primary: #f1f5f9;
--text-secondary: #94a3b8;
--border-color: rgba(255,255,255,0.08);
--glass-bg: rgba(255,255,255,0.03);
--glass-border: rgba(255,255,255,0.06);
}
html { scroll-behavior: smooth; }
body {
font-family: 'Inter', -apple-system, sans-serif;
background: linear-gradient(135deg, var(--bg-primary) 0%, var(--bg-secondary) 50%, #0d1520 100%);
color: var(--text-primary); min-height: 100vh; line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
body::before {
content: ''; position: fixed; top: 0; left: 0; right: 0; bottom: 0;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.03'/%3E%3C/svg%3E");
pointer-events: none; z-index: 0;
}
.container { max-width: 900px; margin: 0 auto; padding: 0 24px; position: relative; z-index: 1; }
.back {
display: inline-flex; align-items: center; gap: 8px;
padding: 20px 0; color: var(--text-secondary); text-decoration: none;
font-size: 0.9rem; font-weight: 500; transition: color 0.2s;
}
.back:hover { color: var(--accent); }
.hero { text-align: center; padding: 60px 0 80px; animation: fadeInUp 0.8s ease-out; }
.hero-label {
display: inline-flex; align-items: center; gap: 8px;
padding: 6px 16px; border-radius: 100px;
background: var(--accent-glow); border: 1px solid rgba(245,158,11,0.2);
font-size: 12px; font-weight: 600; color: var(--accent);
text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 24px;
}
.hero h1 { font-size: clamp(2.2rem, 5vw, 3.5rem); font-weight: 800; line-height: 1.1; letter-spacing: -0.03em; margin-bottom: 16px; }
.hero h1 span {
background: linear-gradient(135deg, var(--accent), #fbbf24);
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
}
.hero .hook { font-size: 1.25rem; color: var(--text-secondary); font-style: italic; font-weight: 300; }
.section { padding: 60px 0; animation: fadeInUp 0.6s ease-out both; }
.section-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em; color: var(--accent); margin-bottom: 12px; }
.section h2 { font-size: 1.8rem; font-weight: 700; margin-bottom: 16px; letter-spacing: -0.02em; }
.section p { color: var(--text-secondary); font-size: 1.05rem; line-height: 1.8; max-width: 700px; }
.glass { background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: 16px; padding: 32px; backdrop-filter: blur(10px); }
.solution-list { list-style: none; margin-top: 20px; }
.solution-list li { padding: 12px 0; border-bottom: 1px solid var(--border-color); color: var(--text-secondary); font-size: 1rem; display: flex; align-items: flex-start; gap: 12px; }
.solution-list li:last-child { border-bottom: none; }
.solution-list .check { color: var(--accent); font-weight: 700; font-size: 1.1rem; flex-shrink: 0; }
/* Flow */
.flow { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; margin-top: 24px; }
.flow-step {
background: var(--glass-bg); border: 1px solid var(--glass-border);
border-radius: 14px; padding: 20px 14px; text-align: center;
position: relative; transition: border-color 0.3s, transform 0.3s;
}
.flow-step:hover { border-color: rgba(245,158,11,0.3); transform: translateY(-3px); }
.flow-step .num {
width: 28px; height: 28px; border-radius: 50%;
background: var(--accent-glow); border: 1px solid rgba(245,158,11,0.3);
display: flex; align-items: center; justify-content: center;
font-size: 12px; font-weight: 700; color: var(--accent); margin: 0 auto 12px;
}
.flow-step .icon { font-size: 24px; margin-bottom: 8px; }
.flow-step .label { font-size: 0.8rem; font-weight: 600; color: var(--text-primary); line-height: 1.3; }
.flow-step .sublabel { font-size: 0.7rem; color: var(--text-secondary); margin-top: 4px; }
.flow-step:not(:last-child)::after {
content: '→'; position: absolute; right: -16px; top: 50%;
transform: translateY(-50%); color: var(--accent); font-size: 14px; opacity: 0.5;
}
.tech-grid { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.tech-pill {
padding: 8px 18px; border-radius: 100px;
background: var(--glass-bg); border: 1px solid var(--glass-border);
font-size: 0.85rem; font-weight: 500; color: var(--text-secondary);
transition: border-color 0.2s, color 0.2s;
}
.tech-pill:hover { border-color: rgba(245,158,11,0.3); color: var(--accent); }
.results-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-top: 24px; }
.result-card {
background: var(--glass-bg); border: 1px solid var(--glass-border);
border-radius: 16px; padding: 28px 20px; text-align: center;
transition: border-color 0.3s, transform 0.3s;
}
.result-card:hover { border-color: rgba(245,158,11,0.3); transform: translateY(-3px); }
.result-card .number {
font-size: 2rem; font-weight: 800; letter-spacing: -0.03em;
background: linear-gradient(135deg, var(--accent), #fbbf24);
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
margin-bottom: 6px;
}
.result-card .label { font-size: 0.8rem; color: var(--text-secondary); font-weight: 500; }
/* Quiz Mockup */
.mockup-container {
margin-top: 24px; border-radius: 16px; overflow: hidden;
background: linear-gradient(135deg, #121016, #1a1520);
border: 1px solid var(--glass-border); padding: 24px;
}
.mockup-titlebar { display: flex; align-items: center; gap: 8px; margin-bottom: 24px; }
.mockup-dot { width: 12px; height: 12px; border-radius: 50%; }
.mockup-dot.r { background: #ef4444; } .mockup-dot.y { background: #f59e0b; } .mockup-dot.g { background: #10b981; }
.mockup-url-bar {
flex: 1; margin-left: 16px; height: 36px; border-radius: 8px;
background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.1);
display: flex; align-items: center; padding: 0 14px; font-size: 13px; color: var(--text-secondary);
}
/* Quiz UI mockup */
.quiz-mock { max-width: 500px; margin: 0 auto; }
.quiz-progress-bar {
height: 6px; border-radius: 3px;
background: rgba(255,255,255,0.06); margin-bottom: 8px; overflow: hidden;
}
.quiz-progress-fill {
height: 100%; width: 60%; border-radius: 3px;
background: linear-gradient(90deg, var(--accent), #fbbf24);
}
.quiz-progress-text {
font-size: 0.75rem; color: var(--text-secondary); margin-bottom: 28px; text-align: right;
}
.quiz-question {
font-size: 1.2rem; font-weight: 700; color: var(--text-primary);
margin-bottom: 24px; text-align: center; line-height: 1.4;
}
.quiz-options { display: flex; flex-direction: column; gap: 10px; }
.quiz-option {
padding: 16px 20px; border-radius: 12px;
background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.08);
font-size: 0.95rem; color: var(--text-secondary);
display: flex; align-items: center; gap: 14px;
transition: border-color 0.2s, background 0.2s;
cursor: default;
}
.quiz-option:hover {
border-color: rgba(245,158,11,0.4);
background: rgba(245,158,11,0.05);
}
.quiz-option.selected {
border-color: var(--accent);
background: rgba(245,158,11,0.08);
color: var(--text-primary);
}
.quiz-option .letter {
width: 28px; height: 28px; border-radius: 8px;
background: rgba(255,255,255,0.06); display: flex; align-items: center; justify-content: center;
font-size: 0.8rem; font-weight: 700; flex-shrink: 0;
}
.quiz-option.selected .letter {
background: var(--accent); color: #000;
}
.quiz-next {
margin-top: 20px; width: 100%; padding: 14px; border-radius: 10px;
background: linear-gradient(135deg, var(--accent), var(--accent-dark));
color: #000; font-weight: 700; font-size: 0.95rem; text-align: center;
border: none;
}
.quiz-branding {
margin-top: 20px; text-align: center;
font-size: 0.7rem; color: var(--text-secondary); opacity: 0.5;
}
.cta { text-align: center; padding: 80px 0; animation: fadeInUp 0.6s ease-out both; animation-delay: 0.3s; }
.cta h2 { font-size: 2rem; font-weight: 700; margin-bottom: 12px; letter-spacing: -0.02em; }
.cta p { color: var(--text-secondary); margin-bottom: 28px; font-size: 1.05rem; }
.cta-btn {
display: inline-flex; align-items: center; gap: 8px;
padding: 14px 32px; border-radius: 12px;
background: linear-gradient(135deg, var(--accent), var(--accent-dark));
color: #000; font-weight: 700; font-size: 1rem;
text-decoration: none; transition: transform 0.2s, box-shadow 0.2s;
}
.cta-btn:hover { transform: translateY(-2px); box-shadow: 0 8px 30px rgba(245,158,11,0.3); }
.footer { text-align: center; padding: 40px 0; border-top: 1px solid var(--border-color); }
.footer .badge {
display: inline-flex; align-items: center; gap: 6px;
padding: 6px 14px; border-radius: 8px;
background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06);
font-size: 12px; color: var(--text-secondary);
}
@keyframes fadeInUp { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: translateY(0); } }
@media (max-width: 768px) {
.hero { padding: 40px 0 50px; }
.flow { grid-template-columns: 1fr; gap: 8px; }
.flow-step:not(:last-child)::after { content: '↓'; right: auto; left: 50%; top: auto; bottom: -14px; transform: translateX(-50%); }
.results-grid { grid-template-columns: repeat(2, 1fr); }
.section h2 { font-size: 1.4rem; }
}
@media (max-width: 480px) { .results-grid { grid-template-columns: 1fr; } }
</style>
</head>
<body>
<div class="container">
<a href="index.html" class="back">← Back to Portfolio</a>
<section class="hero">
<div class="hero-label">🧠 Full SaaS Build</div>
<h1>TheNicheQuiz.com — <span>AI Quiz Platform</span></h1>
<p class="hook">"Full SaaS product from idea to live in one session"</p>
</section>
<section class="section">
<div class="section-label">The Challenge</div>
<h2>Lead Gen Quizzes Are Expensive to Build</h2>
<div class="glass">
<p>Businesses want interactive quizzes to engage audiences and capture leads, but building custom quiz apps requires <strong style="color:var(--text-primary)">weeks of development</strong> and multiple tools. Off-the-shelf quiz builders lack the flexibility and branding control businesses need to stand out.</p>
</div>
</section>
<section class="section">
<div class="section-label">The Solution</div>
<h2>Idea → Live SaaS in One Day</h2>
<p>Built a complete SaaS platform that generates AI-powered niche quizzes with everything included:</p>
<ul class="solution-list">
<li><span class="check"></span> AI generates quiz questions for any niche — fitness, finance, cooking, tech, anything</li>
<li><span class="check"></span> Full authentication system with Clerk — users sign up, log in, manage quizzes</li>
<li><span class="check"></span> Stripe payment processing for premium features and subscriptions</li>
<li><span class="check"></span> Custom branding — colors, logos, domains per quiz</li>
<li><span class="check"></span> Lead capture and analytics dashboard for quiz creators</li>
</ul>
</section>
<section class="section">
<div class="section-label">How It Works</div>
<h2>5 Steps to Live Quiz</h2>
<div class="flow">
<div class="flow-step">
<div class="num">1</div>
<div class="icon">🎯</div>
<div class="label">Choose Niche</div>
<div class="sublabel">Any topic</div>
</div>
<div class="flow-step">
<div class="num">2</div>
<div class="icon">🤖</div>
<div class="label">AI Generates</div>
<div class="sublabel">Questions + answers</div>
</div>
<div class="flow-step">
<div class="num">3</div>
<div class="icon">🎨</div>
<div class="label">Customize</div>
<div class="sublabel">Branding + style</div>
</div>
<div class="flow-step">
<div class="num">4</div>
<div class="icon">🚀</div>
<div class="label">Deploy</div>
<div class="sublabel">Custom domain</div>
</div>
<div class="flow-step">
<div class="num">5</div>
<div class="icon">📊</div>
<div class="label">Collect Leads</div>
<div class="sublabel">Analytics dashboard</div>
</div>
</div>
</section>
<section class="section">
<div class="section-label">Tech Stack</div>
<h2>Built With</h2>
<div class="tech-grid">
<span class="tech-pill">Next.js</span>
<span class="tech-pill">PostgreSQL</span>
<span class="tech-pill">Auth (Clerk)</span>
<span class="tech-pill">Stripe</span>
<span class="tech-pill">Claude API</span>
<span class="tech-pill">Cloudflare</span>
<span class="tech-pill">Tailwind CSS</span>
</div>
</section>
<section class="section">
<div class="section-label">Results</div>
<h2>Impact at a Glance</h2>
<div class="results-grid">
<div class="result-card">
<div class="number">1 Day</div>
<div class="label">Idea to Live Product</div>
</div>
<div class="result-card">
<div class="number"></div>
<div class="label">Niches Supported</div>
</div>
<div class="result-card">
<div class="number">Full</div>
<div class="label">Auth + Payments</div>
</div>
<div class="result-card">
<div class="number">Custom</div>
<div class="label">Domain Support</div>
</div>
</div>
</section>
<section class="section">
<div class="section-label">Product Preview</div>
<h2>The Quiz Interface</h2>
<div class="mockup-container">
<div class="mockup-titlebar">
<span class="mockup-dot r"></span>
<span class="mockup-dot y"></span>
<span class="mockup-dot g"></span>
<div class="mockup-url-bar">thenichequiz.com/quiz/fitness-iq</div>
</div>
<div class="quiz-mock">
<div class="quiz-progress-bar"><div class="quiz-progress-fill"></div></div>
<div class="quiz-progress-text">Question 6 of 10</div>
<div class="quiz-question">What's the most effective rep range for building muscle hypertrophy?</div>
<div class="quiz-options">
<div class="quiz-option">
<span class="letter">A</span>
<span>13 reps (strength focus)</span>
</div>
<div class="quiz-option selected">
<span class="letter">B</span>
<span>812 reps (hypertrophy range)</span>
</div>
<div class="quiz-option">
<span class="letter">C</span>
<span>1520 reps (endurance focus)</span>
</div>
<div class="quiz-option">
<span class="letter">D</span>
<span>25+ reps (cardio territory)</span>
</div>
</div>
<div class="quiz-next">Next Question →</div>
<div class="quiz-branding">Powered by TheNicheQuiz.com</div>
</div>
</div>
</section>
<section class="cta">
<h2>Want something like this?</h2>
<p>Let's build your SaaS product at record speed.</p>
<a href="mailto:hello@example.com" class="cta-btn">Get in Touch →</a>
</section>
<footer class="footer">
<div class="badge">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
Built with Claude Code
</div>
</footer>
</div>
</body>
</html>