Files
Visigine/server/lib/autofix/json-ld.js
Ihor_Zhekov e344f1b7e7 Initial commit: Visigine (Vite client + Express/SQLite backend)
Container-ready via docker/ compose (frontend nginx + backend Node). Compose adjusted for Coolify on the prod server: frontend uses expose:80 (no host binding — host 8080 is taken by the Coolify proxy; Traefik routes visigine.de), backend ALLOWED_ORIGINS=https://visigine.de. Secrets stay in server/.env (git-ignored); see server/.env.example.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 10:15:06 +02:00

80 lines
2.4 KiB
JavaScript

// Generates a JSON-LD skeleton: Organization (or LocalBusiness if address/phone),
// WebSite, and FAQPage — three highest-impact AI signals.
const ph = (s) => `[Bitte ergänzen: ${s}]`
function buildOrganizationNode(siteData) {
const { name, url, description, email, phone, address, sameAs = [] } = siteData
const useLocalBusiness = Boolean(address || phone)
const node = {
'@type': useLocalBusiness ? 'LocalBusiness' : 'Organization',
'@id': `${(url || ph('https://deine-domain.de')).replace(/\/+$/, '')}/#organization`,
name: name || ph('Name deines Unternehmens'),
url: url || ph('https://deine-domain.de'),
description: description || ph('Ein-Satz-Beschreibung'),
}
if (email) node.email = email
if (phone) node.telephone = phone
node.address = {
'@type': 'PostalAddress',
addressCountry: address?.addressCountry || ph('DE/AT/CH'),
addressLocality: address?.addressLocality || ph('Stadt'),
postalCode: address?.postalCode || ph('PLZ'),
streetAddress: address?.streetAddress || ph('Straße + Nr.'),
}
node.sameAs = sameAs.length > 0 ? sameAs : [ph('https://www.linkedin.com/company/...')]
return node
}
function buildWebSiteNode(siteData) {
const { name, url, language = 'de' } = siteData
return {
'@type': 'WebSite',
'@id': `${(url || ph('https://deine-domain.de')).replace(/\/+$/, '')}/#website`,
url: url || ph('https://deine-domain.de'),
name: name || ph('Name deines Unternehmens'),
inLanguage: `${language}-DE`,
publisher: { '@id': `${(url || ph('https://deine-domain.de')).replace(/\/+$/, '')}/#organization` },
}
}
function buildFaqNode() {
return {
'@type': 'FAQPage',
mainEntity: [
{
'@type': 'Question',
name: ph('häufige Frage'),
acceptedAnswer: { '@type': 'Answer', text: ph('1-2 Sätze') },
},
{
'@type': 'Question',
name: ph('weitere Frage'),
acceptedAnswer: { '@type': 'Answer', text: ph('1-2 Sätze') },
},
],
}
}
export function generateJsonLd(siteData) {
const payload = {
'@context': 'https://schema.org',
'@graph': [
buildOrganizationNode(siteData),
buildWebSiteNode(siteData),
buildFaqNode(),
],
}
const pretty = JSON.stringify(payload, null, 2)
const content = `<script type="application/ld+json">\n${pretty}\n</script>\n`
return {
content,
mode: siteData.hasOrgJsonLd ? 'enhance' : 'new',
}
}