feat: add 3 SEO use case pages with clean URLs, sitemap, and index section
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 10m32s

This commit is contained in:
OpenClaw 2026-03-02 09:07:57 +01:00
parent 195a656a7d
commit e9ee3a6c2c
8 changed files with 729 additions and 2 deletions

View file

@ -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 }));

View file

@ -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>.+<\/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}`)
}
})
})