Some checks failed
Deploy to Production / Deploy to Server (push) Has been cancelled
- Created build-time templating system using existing build-html.cjs - Extracted index.html into source template with partials: _styles_index.html, _nav_index.html, _modals.html - All 4 templated pages (index, impressum, privacy, terms) use partials - docs.html excluded (Swagger UI, completely different structure) - Added HTML build step to Dockerfile - Built output is byte-identical to original files
255 lines
13 KiB
HTML
255 lines
13 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>DocFast — HTML & Markdown to PDF API</title>
|
|
<meta name="description" content="Convert HTML and Markdown to beautiful PDFs with a simple API call. Built-in invoice templates. Fast, reliable, developer-friendly.">
|
|
<meta property="og:title" content="DocFast — HTML & Markdown to PDF API">
|
|
<meta property="og:description" content="Convert HTML and Markdown to beautiful PDFs with a simple API call. Fast, reliable, developer-friendly.">
|
|
<meta property="og:type" content="website">
|
|
<meta property="og:url" content="https://docfast.dev">
|
|
<meta property="og:image" content="https://docfast.dev/og-image.png">
|
|
<meta name="twitter:card" content="summary_large_image">
|
|
<meta name="twitter:title" content="DocFast — HTML & Markdown to PDF API">
|
|
<meta name="twitter:description" content="Convert HTML and Markdown to beautiful PDFs with a simple API call.">
|
|
<link rel="canonical" href="https://docfast.dev">
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<script type="application/ld+json">
|
|
{"@context":"https://schema.org","@type":"SoftwareApplication","name":"DocFast","url":"https://docfast.dev","applicationCategory":"DeveloperApplication","operatingSystem":"Web","description":"Convert HTML and Markdown to beautiful PDFs with a simple API call. Fast, reliable, developer-friendly.","offers":[{"@type":"Offer","price":"0","priceCurrency":"EUR","name":"Free","description":"100 PDFs/month"},{"@type":"Offer","price":"9","priceCurrency":"EUR","name":"Pro","description":"5,000 PDFs per month","billingIncrement":"P1M"}]}
|
|
</script>
|
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>⚡</text></svg>">
|
|
{{> styles_index}}
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
|
</head>
|
|
<body>
|
|
|
|
{{> nav_index}}
|
|
|
|
<main class="hero" role="main">
|
|
<div class="container">
|
|
<div class="badge">🚀 Simple PDF API for Developers</div>
|
|
<h1>HTML to <span class="gradient">PDF</span><br>in one API call</h1>
|
|
<p>Convert HTML, Markdown, or URLs to pixel-perfect PDFs. Built-in templates for invoices & receipts. No headless browser headaches.</p>
|
|
<div class="hero-actions">
|
|
<button class="btn btn-primary" id="btn-signup">Get Free API Key →</button>
|
|
<a href="/docs" class="btn btn-secondary">Read the Docs</a>
|
|
</div>
|
|
<p style="margin-top:16px;color:var(--muted);font-size:0.9rem;">Already have an account? <a href="#" class="open-recover" style="color:var(--accent);">Lost your API key? Recover it →</a></p>
|
|
|
|
<div class="code-section">
|
|
<div class="code-header">
|
|
<div class="code-dots" aria-hidden="true"><span></span><span></span><span></span></div>
|
|
<span class="code-label">terminal</span>
|
|
</div>
|
|
<div class="code-block">
|
|
<span class="c"># Convert HTML to PDF — it's that simple</span>
|
|
<span class="k">curl</span> <span class="f">-X POST</span> https://docfast.dev/v1/convert/html \
|
|
-H <span class="s">"Authorization: Bearer YOUR_KEY"</span> \
|
|
-H <span class="s">"Content-Type: application/json"</span> \
|
|
-d <span class="s">'{"html": "<h1>Hello World</h1><p>Your first PDF</p>"}'</span> \
|
|
-o <span class="f">output.pdf</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<section class="trust">
|
|
<div class="container">
|
|
<div class="trust-grid">
|
|
<div class="trust-item">
|
|
<div class="trust-num"><1s</div>
|
|
<div class="trust-label">Avg. generation time</div>
|
|
</div>
|
|
<div class="trust-item">
|
|
<div class="trust-num">99.5%</div>
|
|
<div class="trust-label">Uptime SLA</div>
|
|
</div>
|
|
<div class="trust-item">
|
|
<div class="trust-num">HTTPS</div>
|
|
<div class="trust-label">Encrypted & secure</div>
|
|
</div>
|
|
<div class="trust-item">
|
|
<div class="trust-num">0 bytes</div>
|
|
<div class="trust-label">Data stored on disk</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="eu-hosting">
|
|
<div class="container">
|
|
<div class="eu-badge">
|
|
<div class="eu-icon">🇪🇺</div>
|
|
<div class="eu-content">
|
|
<h3>Hosted in the EU</h3>
|
|
<p>Your data never leaves the EU • GDPR Compliant • Hetzner Germany (Nuremberg)</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="features" id="features">
|
|
<div class="container">
|
|
<h2 class="section-title">Everything you need</h2>
|
|
<p class="section-sub">A complete PDF generation API. No SDKs, no dependencies, no setup.</p>
|
|
<div class="features-grid">
|
|
<div class="feature-card">
|
|
<div class="feature-icon" aria-hidden="true">⚡</div>
|
|
<h3>Sub-second Speed</h3>
|
|
<p>Persistent browser pool — no cold starts. Your PDFs are ready before your spinner shows.</p>
|
|
</div>
|
|
<div class="feature-card">
|
|
<div class="feature-icon" aria-hidden="true">🎨</div>
|
|
<h3>Pixel-perfect Output</h3>
|
|
<p>Full CSS support including flexbox, grid, and custom fonts. Your brand, your PDFs.</p>
|
|
</div>
|
|
<div class="feature-card">
|
|
<div class="feature-icon" aria-hidden="true">📄</div>
|
|
<h3>Built-in Templates</h3>
|
|
<p>Invoice and receipt templates out of the box. Pass JSON data, get beautiful PDFs.</p>
|
|
</div>
|
|
<div class="feature-card">
|
|
<div class="feature-icon" aria-hidden="true">🔧</div>
|
|
<h3>Dead-simple API</h3>
|
|
<p>REST API. JSON in, PDF out. Works with curl, Python, Node, Go — anything with HTTP.</p>
|
|
</div>
|
|
<div class="feature-card">
|
|
<div class="feature-icon" aria-hidden="true">📐</div>
|
|
<h3>Fully Configurable</h3>
|
|
<p>A4, Letter, custom sizes. Portrait or landscape. Headers, footers, and margins.</p>
|
|
</div>
|
|
<div class="feature-card">
|
|
<div class="feature-icon" aria-hidden="true">🔒</div>
|
|
<h3>Secure by Default</h3>
|
|
<p>HTTPS only. Rate limiting. No data stored. PDFs stream directly — nothing touches disk.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="pricing" id="pricing">
|
|
<div class="container">
|
|
<h2 class="section-title">Simple, transparent pricing</h2>
|
|
<p class="section-sub">Start free. Upgrade when you're ready. No surprise charges.</p>
|
|
<div class="pricing-grid">
|
|
<div class="price-card">
|
|
<div class="price-name">Free</div>
|
|
<div class="price-amount">€0<span> /mo</span></div>
|
|
<div class="price-desc">Perfect for side projects and testing</div>
|
|
<ul class="price-features">
|
|
<li>100 PDFs per month</li>
|
|
<li>All conversion endpoints</li>
|
|
<li>All templates included</li>
|
|
<li>Rate limiting: 10 req/min</li>
|
|
</ul>
|
|
<button class="btn btn-secondary" style="width:100%" id="btn-signup-2">Get Free API Key</button>
|
|
</div>
|
|
<div class="price-card featured">
|
|
<div class="price-name">Pro</div>
|
|
<div class="price-amount">€9<span> /mo</span></div>
|
|
<div class="price-desc">For production apps and businesses</div>
|
|
<ul class="price-features">
|
|
<li>5,000 PDFs per month</li>
|
|
<li>All conversion endpoints</li>
|
|
<li>All templates included</li>
|
|
<li>Priority support</li>
|
|
</ul>
|
|
<button class="btn btn-primary" style="width:100%" id="btn-checkout">Get Started →</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{{> footer}}
|
|
|
|
{{> modals}}
|
|
|
|
|
|
<!-- Recovery Modal -->
|
|
<div class="modal-overlay" id="recoverModal" role="dialog" aria-label="Recover API key">
|
|
<div class="modal">
|
|
<button class="close" id="btn-close-recover">×</button>
|
|
|
|
<div id="recoverInitial" class="active">
|
|
<h2>Recover your API key</h2>
|
|
<p>Enter the email you signed up with. We'll send a verification code.</p>
|
|
<div class="signup-error" id="recoverError"></div>
|
|
<input type="email" id="recoverEmailInput" placeholder="your.email@example.com" style="width:100%;padding:12px;border:1px solid var(--border);background:var(--bg);color:var(--fg);border-radius:8px;font-size:0.9rem;margin-bottom:16px;" required>
|
|
<button class="btn btn-primary" style="width:100%" id="recoverBtn">Send Verification Code →</button>
|
|
<p style="margin-top:16px;color:var(--muted);font-size:0.8rem;text-align:center;">Your key will be shown here after verification — never sent via email</p>
|
|
</div>
|
|
|
|
<div id="recoverLoading">
|
|
<div class="spinner"></div>
|
|
<p style="color:var(--muted);margin:0">Sending verification code…</p>
|
|
</div>
|
|
|
|
<div id="recoverVerify">
|
|
<h2>Enter verification code</h2>
|
|
<p>We sent a 6-digit code to <strong id="recoverEmailDisplay"></strong></p>
|
|
<div class="signup-error" id="recoverVerifyError"></div>
|
|
<input type="text" id="recoverCode" placeholder="123456" maxlength="6" pattern="[0-9]{6}" inputmode="numeric" style="width:100%;padding:14px;border:1px solid var(--border);background:var(--bg);color:var(--fg);border-radius:8px;font-size:1.4rem;letter-spacing:0.3em;text-align:center;margin-bottom:16px;font-family:monospace;" required>
|
|
<button class="btn btn-primary" style="width:100%" id="recoverVerifyBtn">Verify →</button>
|
|
<p style="margin-top:16px;color:var(--muted);font-size:0.8rem;text-align:center;">Code expires in 15 minutes</p>
|
|
</div>
|
|
|
|
<div id="recoverResult" aria-live="polite">
|
|
<h2>🔑 Your API key</h2>
|
|
<div class="warning-box">
|
|
<span class="icon">⚠️</span>
|
|
<span>Save your API key securely. This is the only time it will be shown.</span>
|
|
</div>
|
|
<div style="background:var(--bg);border:1px solid var(--accent);border-radius:8px;padding:14px;font-family:monospace;font-size:0.82rem;word-break:break-all;margin:16px 0;position:relative;">
|
|
<span id="recoveredKeyText"></span>
|
|
<button onclick="copyRecoveredKey()" id="copyRecoveredBtn" style="position:absolute;top:8px;right:8px;background:var(--accent);color:var(--bg);border:none;border-radius:4px;padding:4px 12px;cursor:pointer;font-size:0.8rem;">Copy</button>
|
|
</div>
|
|
<p style="margin-top:20px;color:var(--muted);font-size:0.9rem;"><a href="/docs">Read the docs →</a></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- Email Change Modal -->
|
|
<div class="modal-overlay" id="emailChangeModal" role="dialog" aria-label="Change email">
|
|
<div class="modal">
|
|
<button class="close" id="btn-close-email-change">×</button>
|
|
|
|
<div id="emailChangeInitial" class="active">
|
|
<h2>Change your email</h2>
|
|
<p>Enter your API key and new email address.</p>
|
|
<div class="signup-error" id="emailChangeError"></div>
|
|
<input type="text" id="emailChangeApiKey" placeholder="Your API key (df_free_... or df_pro_...)" style="width:100%;padding:12px;border:1px solid var(--border);background:var(--bg);color:var(--fg);border-radius:8px;font-size:0.9rem;margin-bottom:12px;font-family:monospace;" required>
|
|
<input type="email" id="emailChangeNewEmail" placeholder="new.email@example.com" style="width:100%;padding:12px;border:1px solid var(--border);background:var(--bg);color:var(--fg);border-radius:8px;font-size:0.9rem;margin-bottom:16px;" required>
|
|
<button class="btn btn-primary" style="width:100%" id="emailChangeBtn">Send Verification Code →</button>
|
|
<p style="margin-top:16px;color:var(--muted);font-size:0.8rem;text-align:center;">A verification code will be sent to your new email</p>
|
|
</div>
|
|
|
|
<div id="emailChangeLoading">
|
|
<div class="spinner"></div>
|
|
<p style="color:var(--muted);margin:0">Sending verification code…</p>
|
|
</div>
|
|
|
|
<div id="emailChangeVerify">
|
|
<h2>Enter verification code</h2>
|
|
<p>We sent a 6-digit code to <strong id="emailChangeEmailDisplay"></strong></p>
|
|
<div class="signup-error" id="emailChangeVerifyError"></div>
|
|
<input type="text" id="emailChangeCode" placeholder="123456" maxlength="6" pattern="[0-9]{6}" inputmode="numeric" style="width:100%;padding:14px;border:1px solid var(--border);background:var(--bg);color:var(--fg);border-radius:8px;font-size:1.4rem;letter-spacing:0.3em;text-align:center;margin-bottom:16px;font-family:monospace;" required>
|
|
<button class="btn btn-primary" style="width:100%" id="emailChangeVerifyBtn">Verify →</button>
|
|
<p style="margin-top:16px;color:var(--muted);font-size:0.8rem;text-align:center;">Code expires in 15 minutes</p>
|
|
</div>
|
|
|
|
<div id="emailChangeResult">
|
|
<h2>✅ Email updated!</h2>
|
|
<p>Your account email has been changed to <strong id="emailChangeNewDisplay"></strong></p>
|
|
<p style="margin-top:20px;color:var(--muted);font-size:0.9rem;"><a href="/docs">Read the docs →</a></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/app.js"></script>
|
|
</body>
|
|
</html>
|