diff --git a/package-lock.json b/package-lock.json index b49d108..ace1722 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "snapapi", - "version": "0.1.0", + "version": "0.6.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "snapapi", - "version": "0.1.0", + "version": "0.6.0", "dependencies": { "compression": "^1.8.1", "express": "^4.21.0", diff --git a/public/index.html b/public/index.html index 05e8c11..4b53948 100644 --- a/public/index.html +++ b/public/index.html @@ -546,6 +546,31 @@ screenshot = snap.capture( +
+
+ +

Built for real-world workflows

+

See how developers use SnapAPI to automate screenshots across their stack.

+ +
+
+
diff --git a/public/sitemap.xml b/public/sitemap.xml index 5511f6d..b03a934 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -2,6 +2,9 @@ https://snapapi.eu/weekly1.0 https://snapapi.eu/docsmonthly0.8 + https://snapapi.eu/use-cases/social-media-previewsmonthly0.7 + https://snapapi.eu/use-cases/website-monitoringmonthly0.7 + https://snapapi.eu/use-cases/pdf-reportsmonthly0.7 https://snapapi.eu/statusalways0.3 https://snapapi.eu/impressum.htmlyearly0.2 https://snapapi.eu/privacy.htmlyearly0.2 diff --git a/public/use-cases/pdf-reports.html b/public/use-cases/pdf-reports.html new file mode 100644 index 0000000..163e347 --- /dev/null +++ b/public/use-cases/pdf-reports.html @@ -0,0 +1,205 @@ + + + + + +Generate Visual Reports & Thumbnails from Web Content | SnapAPI + + + + + + + + + + + + + + + + + + +
+
+

Generate Visual Reports & Thumbnails from Web Content

+ +

Building a link directory, content aggregator, or dashboard? You need thumbnail previews of web pages. Rather than relying on unreliable meta images or building your own headless browser infrastructure, use SnapAPI to generate accurate website thumbnails on demand.

+ +

Common Use Cases

+ +
    +
  • Link preview thumbnails β€” Show visual previews of URLs in chat apps, bookmarking tools, or CMS platforms.
  • +
  • Report generation β€” Capture web dashboards (Grafana, analytics) as images for PDF reports or email digests.
  • +
  • Content directories β€” Generate thumbnails for website listings, app stores, or portfolio showcases.
  • +
  • Email newsletters β€” Embed live website previews in newsletters instead of stale static images.
  • +
+ +

Code Example

+ +

Generate a Website Thumbnail

+
+
Node.js
+
async function getThumbnail(url) {
+  const res = await fetch('https://snapapi.eu/v1/screenshot', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+      'X-API-Key': process.env.SNAPAPI_KEY
+    },
+    body: JSON.stringify({
+      url,
+      width: 1280,
+      height: 800,
+      format: 'webp',    // Smaller file size
+      quality: 80
+    })
+  });
+
+  return Buffer.from(await res.arrayBuffer());
+}
+
+// Generate thumbnails for a list of URLs
+const urls = ['https://github.com', 'https://news.ycombinator.com'];
+for (const url of urls) {
+  const img = await getThumbnail(url);
+  // Store in database, upload to CDN, etc.
+}
+
+ +

Batch Processing with Caching

+

For high-volume use, cache thumbnails and refresh them periodically:

+ +
+
Bash
+
# Quick thumbnail via cURL
+curl -X POST https://snapapi.eu/v1/screenshot \
+  -H "Content-Type: application/json" \
+  -H "X-API-Key: $SNAPAPI_KEY" \
+  -d '{"url":"https://example.com","width":1280,"height":800,"format":"webp"}' \
+  --output thumbnail.webp
+
+# Resize locally for smaller thumbnails
+convert thumbnail.webp -resize 400x250 thumbnail-sm.webp
+
+ +

Why SnapAPI for Thumbnails?

+
    +
  • Accurate rendering β€” Real Chromium browser captures the page exactly as users see it, including JavaScript-rendered content.
  • +
  • Multiple formats β€” PNG for lossless quality, WebP for smaller file sizes, JPEG for maximum compatibility.
  • +
  • Custom viewport β€” Set any width/height to capture desktop, tablet, or mobile views.
  • +
  • EU-hosted β€” All screenshots rendered in Germany. GDPR compliant by default.
  • +
+ +
+

Start Generating Thumbnails

+

Try it free in the playground β€” no signup needed.

+ Get Your API Key β†’ +
+ + +
+
+ + + + diff --git a/public/use-cases/social-media-previews.html b/public/use-cases/social-media-previews.html new file mode 100644 index 0000000..6f1ccfe --- /dev/null +++ b/public/use-cases/social-media-previews.html @@ -0,0 +1,194 @@ + + + + + +Generate OG Images & Social Media Previews with a Screenshot API | SnapAPI + + + + + + + + + + + + + + + + + + +
+
+

Generate OG Images & Social Media Previews with a Screenshot API

+ +

When you share a link on Twitter, LinkedIn, or Slack, the platform fetches an Open Graph image to display as a preview card. Static OG images are fine for homepages β€” but what about blog posts, user profiles, or product pages that need unique, dynamic preview images?

+ +

SnapAPI lets you render any HTML page as a PNG image via a simple API call. Build an HTML template with your title, author, and branding, host it on a URL, and let SnapAPI screenshot it into a pixel-perfect OG image.

+ +

How It Works

+ +

The workflow is straightforward:

+
    +
  1. Create an HTML template β€” Design your OG card layout (1200Γ—630px) with CSS. Use query parameters for dynamic content.
  2. +
  3. Call SnapAPI β€” Pass the template URL to the screenshot endpoint. SnapAPI renders it in a real Chromium browser.
  4. +
  5. Serve the image β€” Use the returned PNG as your og:image meta tag, or cache it on your CDN.
  6. +
+ +

Code Example

+ +

Screenshot an OG Template

+
+
Node.js
+
const response = await fetch('https://snapapi.eu/v1/screenshot', {
+  method: 'POST',
+  headers: {
+    'Content-Type': 'application/json',
+    'X-API-Key': process.env.SNAPAPI_KEY
+  },
+  body: JSON.stringify({
+    url: 'https://yoursite.com/og-template?title=My+Post&author=Jane',
+    width: 1200,
+    height: 630,
+    format: 'png'
+  })
+});
+
+const imageBuffer = await response.arrayBuffer();
+// Upload to S3, serve from CDN, or return directly
+
+ +

Dynamic Meta Tags

+

Point your og:image to a serverless function that calls SnapAPI on-the-fly:

+ +
+
HTML
+
<!-- In your page's <head> -->
+<meta property="og:image"
+      content="https://yoursite.com/api/og?title=My+Blog+Post" />
+<meta property="og:image:width" content="1200" />
+<meta property="og:image:height" content="630" />
+
+ +

Why Use SnapAPI for OG Images?

+
    +
  • Real browser rendering β€” Full CSS support, custom fonts, gradients, SVGs. No template language limitations.
  • +
  • EU-hosted, GDPR compliant β€” All rendering happens on servers in Germany. No data leaves the EU.
  • +
  • Fast β€” Typical render times under 2 seconds. Cache the result and serve instantly.
  • +
  • Simple API β€” One POST request, one image back. No SDKs required.
  • +
+ +
+

Start Generating OG Images

+

Try SnapAPI free in the playground β€” no signup needed.

+ Get Your API Key β†’ +
+ + +
+
+ + + + diff --git a/public/use-cases/website-monitoring.html b/public/use-cases/website-monitoring.html new file mode 100644 index 0000000..183d298 --- /dev/null +++ b/public/use-cases/website-monitoring.html @@ -0,0 +1,211 @@ + + + + + +Visual Website Monitoring & Regression Testing with a Screenshot API | SnapAPI + + + + + + + + + + + + + + + + + + +
+
+

Visual Website Monitoring & Regression Testing

+ +

CSS changes, dependency updates, or CMS edits can silently break your site's layout. Traditional uptime monitoring checks if a page returns 200 β€” but it won't tell you if your hero section is now overlapping your navigation bar.

+ +

Visual monitoring solves this by taking periodic screenshots and comparing them against a known-good baseline. SnapAPI provides the screenshot capture part β€” you bring the comparison logic or just review the images manually.

+ +

How It Works

+ +
    +
  1. Schedule screenshots β€” Use a cron job or CI pipeline to call SnapAPI at regular intervals (daily, hourly, per-deploy).
  2. +
  3. Store the results β€” Save screenshots to S3, a database, or your local filesystem with timestamps.
  4. +
  5. Compare β€” Use pixel-diff tools like pixelmatch or resemble.js to detect visual changes. Alert when the diff exceeds a threshold.
  6. +
+ +

Code Example

+ +

Daily Screenshot Cron Job

+
+
Node.js
+
import fs from 'fs';
+
+const PAGES = [
+  'https://yoursite.com',
+  'https://yoursite.com/pricing',
+  'https://yoursite.com/docs',
+];
+
+for (const url of PAGES) {
+  const res = await fetch('https://snapapi.eu/v1/screenshot', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+      'X-API-Key': process.env.SNAPAPI_KEY
+    },
+    body: JSON.stringify({
+      url,
+      width: 1440,
+      height: 900,
+      format: 'png',
+      fullPage: true
+    })
+  });
+
+  const slug = new URL(url).pathname.replace(/\//g, '_') || 'home';
+  const date = new Date().toISOString().slice(0, 10);
+  fs.writeFileSync(`screenshots/${slug}_${date}.png`,
+    Buffer.from(await res.arrayBuffer()));
+}
+
+// Run via: node monitor.mjs (cron: 0 6 * * *)
+
+ +

CI Pipeline Integration

+

Add visual regression checks to your deployment pipeline. Take a screenshot after each deploy and compare it to the previous version:

+ +
+
Bash
+
# In your CI pipeline (GitHub Actions, GitLab CI, etc.)
+curl -X POST https://snapapi.eu/v1/screenshot \
+  -H "Content-Type: application/json" \
+  -H "X-API-Key: $SNAPAPI_KEY" \
+  -d '{"url":"https://staging.yoursite.com","width":1440,"height":900,"format":"png"}' \
+  --output screenshot-after-deploy.png
+
+# Compare with baseline using pixelmatch, ImageMagick, etc.
+
+ +

Use Cases for Visual Monitoring

+
    +
  • Pre/post deploy checks β€” Catch CSS regressions before users see them.
  • +
  • Third-party widget monitoring β€” Detect when embedded widgets (chat, analytics banners) break your layout.
  • +
  • Competitor tracking β€” Screenshot competitor pages periodically to track pricing or feature changes.
  • +
  • Compliance archiving β€” Keep dated visual records of your pages for regulatory requirements.
  • +
+ +
+

Start Monitoring Visually

+

Try SnapAPI free in the playground. Set up your first visual monitor in minutes.

+ Get Your API Key β†’ +
+ + +
+
+ + + + diff --git a/src/index.ts b/src/index.ts index 738ad30..7986fb9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -130,6 +130,11 @@ for (const page of ["privacy", "terms", "impressum", "status", "usage"]) { app.get(`/${page}`, (_req, res) => res.redirect(301, `/${page}.html`)); } +// Clean URLs for use case pages +for (const page of ["social-media-previews", "website-monitoring", "pdf-reports"]) { + app.get(`/use-cases/${page}`, (_req, res) => res.redirect(301, `/use-cases/${page}.html`)); +} + // Static files (landing page) app.use(express.static(path.join(__dirname, "../public"), { etag: true })); diff --git a/src/routes/__tests__/use-cases.test.ts b/src/routes/__tests__/use-cases.test.ts new file mode 100644 index 0000000..92439e0 --- /dev/null +++ b/src/routes/__tests__/use-cases.test.ts @@ -0,0 +1,84 @@ +import { describe, it, expect, vi } from 'vitest' +import request from 'supertest' +import express from 'express' +import path from 'path' +import { fileURLToPath } from 'url' +import fs from 'fs' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) +const publicDir = path.join(__dirname, '../../../public') + +// Build a minimal app that mirrors index.ts routing +function createApp() { + const app = express() + + // Clean URLs for use-case pages + const useCasePages = ['social-media-previews', 'website-monitoring', 'pdf-reports'] + for (const page of useCasePages) { + app.get(`/use-cases/${page}`, (_req, res) => res.redirect(301, `/use-cases/${page}.html`)) + } + + app.use(express.static(publicDir, { etag: true })) + return app +} + +const useCases = [ + { slug: 'social-media-previews', title: 'OG Images', keywords: ['og image', 'social media preview'] }, + { slug: 'website-monitoring', title: 'Website Monitoring', keywords: ['website screenshot monitoring', 'visual regression'] }, + { slug: 'pdf-reports', title: 'Reports', keywords: ['thumbnail', 'web page preview'] }, +] + +describe('Use Case Pages', () => { + const app = createApp() + + for (const uc of useCases) { + describe(uc.slug, () => { + it(`GET /use-cases/${uc.slug}.html returns 200`, async () => { + const res = await request(app).get(`/use-cases/${uc.slug}.html`) + expect(res.status).toBe(200) + expect(res.headers['content-type']).toContain('text/html') + }) + + it(`GET /use-cases/${uc.slug} redirects 301 to .html`, async () => { + const res = await request(app).get(`/use-cases/${uc.slug}`) + expect(res.status).toBe(301) + expect(res.headers.location).toBe(`/use-cases/${uc.slug}.html`) + }) + + it('contains required SEO elements', async () => { + const res = await request(app).get(`/use-cases/${uc.slug}.html`) + const html = res.text + + // Title tag + expect(html).toMatch(/.+<\/title>/) + // Meta description + expect(html).toMatch(/<meta name="description" content=".+"/) + // OG tags + expect(html).toMatch(/<meta property="og:title"/) + expect(html).toMatch(/<meta property="og:description"/) + expect(html).toMatch(/<meta property="og:type" content="article"/) + // JSON-LD + expect(html).toContain('"@type":"Article"') + // H1 + expect(html).toMatch(/<h1[^>]*>.+<\/h1>/) + // Canonical + expect(html).toMatch(/<link rel="canonical"/) + }) + }) + } + + it('sitemap contains all use case URLs', () => { + const sitemap = fs.readFileSync(path.join(publicDir, 'sitemap.xml'), 'utf-8') + for (const uc of useCases) { + expect(sitemap).toContain(`https://snapapi.eu/use-cases/${uc.slug}`) + } + }) + + it('index.html contains use cases section', () => { + const index = fs.readFileSync(path.join(publicDir, 'index.html'), 'utf-8') + expect(index).toContain('id="use-cases"') + for (const uc of useCases) { + expect(index).toContain(`/use-cases/${uc.slug}`) + } + }) +})