diff --git a/public/app.js b/public/app.js index 6a04382..6e99687 100644 --- a/public/app.js +++ b/public/app.js @@ -1,28 +1,26 @@ +function showState(state) { + ['signupInitial', 'signupLoading', 'signupResult'].forEach(function(id) { + document.getElementById(id).classList.remove('active'); + }); + document.getElementById(state).classList.add('active'); +} + function openSignup() { document.getElementById('signupModal').classList.add('active'); - document.getElementById('signupForm').style.display = 'block'; - document.getElementById('keyResult').style.display = 'none'; + showState('signupInitial'); document.getElementById('signupError').style.display = 'none'; - document.getElementById('signupBtn').textContent = 'Get API Key'; - document.getElementById('signupBtn').disabled = false; } function closeSignup() { document.getElementById('signupModal').classList.remove('active'); } -// Close on overlay click -document.getElementById('signupModal').addEventListener('click', function(e) { - if (e.target === this) closeSignup(); -}); - async function submitSignup() { var errEl = document.getElementById('signupError'); var btn = document.getElementById('signupBtn'); - - btn.textContent = 'Creating...'; - btn.disabled = true; errEl.style.display = 'none'; + btn.disabled = true; + showState('signupLoading'); try { var res = await fetch('/v1/signup/free', { @@ -30,43 +28,32 @@ async function submitSignup() { headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({}) }); - - if (res.status === 429) { - errEl.textContent = 'Too many requests. Please try again in a few minutes.'; - errEl.style.display = 'block'; - btn.textContent = 'Get API Key'; - btn.disabled = false; - return; - } - var data = await res.json(); if (!res.ok) { + showState('signupInitial'); errEl.textContent = data.error || 'Something went wrong. Please try again.'; errEl.style.display = 'block'; - btn.textContent = 'Get API Key'; btn.disabled = false; return; } - // Show key - document.getElementById('signupForm').style.display = 'none'; - document.getElementById('keyResult').style.display = 'block'; - document.getElementById('apiKeyDisplay').textContent = data.apiKey; + document.getElementById('apiKeyText').textContent = data.apiKey; + showState('signupResult'); } catch (err) { + showState('signupInitial'); errEl.textContent = 'Network error. Please try again.'; errEl.style.display = 'block'; - btn.textContent = 'Get API Key'; btn.disabled = false; } } function copyKey() { - var key = document.getElementById('apiKeyDisplay').textContent; - var hint = document.querySelector('.copy-hint'); + var key = document.getElementById('apiKeyText').textContent; + var btn = document.getElementById('copyBtn'); function showCopied() { - hint.textContent = '✓ Copied!'; - setTimeout(function() { hint.textContent = 'Click to copy'; }, 2000); + btn.textContent = '✓ Copied!'; + setTimeout(function() { btn.textContent = 'Copy'; }, 2000); } try { navigator.clipboard.writeText(key).then(showCopied).catch(function() { @@ -87,18 +74,28 @@ async function checkout() { var res = await fetch('/v1/billing/checkout', { method: 'POST' }); var data = await res.json(); if (data.url) window.location.href = data.url; - else alert('Something went wrong. Please try again.'); + else alert('Checkout is not available yet. Please try again later.'); } catch (err) { alert('Something went wrong. Please try again.'); } } -// BUG-005 fix: attach all click handlers via JS instead of inline onclick document.addEventListener('DOMContentLoaded', function() { document.getElementById('btn-signup').addEventListener('click', openSignup); document.getElementById('btn-signup-2').addEventListener('click', openSignup); document.getElementById('btn-checkout').addEventListener('click', checkout); document.getElementById('btn-close-signup').addEventListener('click', closeSignup); document.getElementById('signupBtn').addEventListener('click', submitSignup); - document.getElementById('apiKeyDisplay').addEventListener('click', copyKey); + document.getElementById('copyBtn').addEventListener('click', copyKey); + document.getElementById('signupModal').addEventListener('click', function(e) { + if (e.target === this) closeSignup(); + }); + // Smooth scroll for nav links + document.querySelectorAll('a[href^="#"]').forEach(function(a) { + a.addEventListener('click', function(e) { + e.preventDefault(); + var el = document.querySelector(this.getAttribute('href')); + if (el) el.scrollIntoView({ behavior: 'smooth' }); + }); + }); }); diff --git a/public/index.html b/public/index.html index bc3c9e3..81b72a2 100644 --- a/public/index.html +++ b/public/index.html @@ -5,207 +5,273 @@ DocFast — HTML & Markdown to PDF API + + + + + +
-

HTML & Markdown to PDF

-

One API call. Beautiful PDFs. Built-in invoice templates. No headless browser setup, no dependencies, no hassle.

+
🚀 Simple PDF API for Developers
+

HTML to PDF
in one API call

+

Convert HTML, Markdown, or URLs to pixel-perfect PDFs. Built-in templates for invoices & receipts. No headless browser headaches.

- - View Docs + + Read the Docs
-
- // Convert markdown to PDF in one call
- curl -X POST https://docfast.dev/v1/convert/markdown \
-   -H "Authorization: Bearer YOUR_KEY" \
-   -H "Content-Type: application/json" \
-   -d '{"markdown": "# Invoice\\n\\nAmount: $500"}' \
-   -o invoice.pdf + +
+
+
+ terminal +
+
+# Convert HTML to PDF — it's that simple +curl -X POST https://docfast.dev/v1/convert/html \ + -H "Authorization: Bearer YOUR_KEY" \ + -H "Content-Type: application/json" \ + -d '{"html": "<h1>Hello World</h1><p>Your first PDF</p>"}' \ + -o output.pdf +
-
+
-

Why DocFast?

+
+
+
<1s
+
Avg. generation time
+
+
+
99.9%
+
Uptime SLA
+
+
+
HTTPS
+
Encrypted & secure
+
+
+
0 bytes
+
Data stored on disk
+
+
+
+
+ +
+
+

Everything you need

+

A complete PDF generation API. No SDKs, no dependencies, no setup.

-

Fast

-

Sub-second PDF generation. Persistent browser pool means no cold starts.

+

Sub-second Speed

+

Persistent browser pool — no cold starts. Your PDFs are ready before your spinner shows.

🎨
-

Beautiful Output

-

Full CSS support. Custom fonts, colors, layouts. Your PDFs, your brand.

+

Pixel-perfect Output

+

Full CSS support including flexbox, grid, and custom fonts. Your brand, your PDFs.

📄
-

Templates

-

Built-in invoice and receipt templates. Pass data, get PDF. No HTML needed.

+

Built-in Templates

+

Invoice and receipt templates out of the box. Pass JSON data, get beautiful PDFs.

🔧
-

Simple API

-

REST API with JSON in, PDF out. Works with any language. No SDKs required.

+

Dead-simple API

+

REST API. JSON in, PDF out. Works with curl, Python, Node, Go — anything with HTTP.

📐
-

Flexible

-

A4, Letter, custom sizes. Portrait or landscape. Configurable margins.

+

Fully Configurable

+

A4, Letter, custom sizes. Portrait or landscape. Headers, footers, and margins.

🔒
-

Secure

-

Your data is never stored. PDFs are generated and streamed — nothing hits disk.

+

Secure by Default

+

HTTPS only. Rate limiting. No data stored. PDFs stream directly — nothing touches disk.

-
-
-

API Endpoints

-
- POST - /v1/convert/html -
Convert raw HTML (with optional CSS) to PDF.
-
-
- POST - /v1/convert/markdown -
Convert Markdown to styled PDF with syntax highlighting.
-
-
- POST - /v1/convert/url -
Navigate to a URL and convert the page to PDF.
-
-
- GET - /v1/templates -
List available document templates with field definitions.
-
-
- POST - /v1/templates/:id/render -
Render a template (invoice, receipt) with your data to PDF.
-
-
- GET - /health -
Health check — verify the API is running.
-
-
-
-
-

Simple Pricing

-

No per-page fees. No hidden limits. Pay for what you use.

+

Simple, transparent pricing

+

Start free. Upgrade when you're ready. No surprise charges.

-

Free

-
$0/mo
+
Free
+
$0 /mo
+
Perfect for side projects and testing
    -
  • 100 PDFs / month
  • -
  • All endpoints
  • -
  • All templates
  • -
  • Community support
  • +
  • 100 PDFs per month
  • +
  • All conversion endpoints
  • +
  • All templates included
  • +
  • Rate limiting: 10 req/min
- +
@@ -213,27 +279,43 @@ footer { padding: 40px 0; text-align: center; color: var(--muted); font-size: 0.
-

DocFast © 2026 — Fast PDF generation for developers

+ +