feat: JSON-LD graph, breadcrumbs and hreflang in the resolve answer (tracer)

- classes/schema builds one @graph per page (WebPage, article, profile,
  service, BreadcrumbList, VideoObject, WebSite, publisher) linked by @id
- breadcrumb trail through the primary parent chain, hreflang alternates
  with x-default, html_lang and og:locale in the resolve answer
- migration 202610280004 adds the publisher, local business, home crumb
  and pagination settings columns
This commit is contained in:
Jakub Zych
2026-11-04 14:06:57 +01:00
parent df93c86001
commit ea2ce24954
12 changed files with 1676 additions and 2 deletions

View File

@@ -0,0 +1,65 @@
package updates
import (
"github.com/go-gormigrate/gormigrate/v2"
"gorm.io/gorm"
)
// addPublisherPagination adds the settings columns of the structured data,
// breadcrumb and pagination plan (33-06): the home crumb name, the page
// address form and its per-locale segment and suffixes, the publisher
// (D-45) and its local business data (opening hours as a JSON list). The
// translatable text columns (breadcrumb_home, page_segment, the suffixes,
// publisher_name) hold the default locale; the others live with the
// translation writer, as site_name does. Empty texts mean the per-locale
// default copy.
var addPublisherPagination = []*gormigrate.Migration{
{
ID: "202610280004_add_golem15_seo_publisher_pagination",
Migrate: func(tx *gorm.DB) error {
return tx.Exec(`ALTER TABLE golem15_seo_settings
ADD COLUMN breadcrumb_home TEXT NOT NULL DEFAULT '',
ADD COLUMN page_form TEXT NOT NULL DEFAULT 'query',
ADD COLUMN page_segment TEXT NOT NULL DEFAULT '',
ADD COLUMN page_title_suffix TEXT NOT NULL DEFAULT '',
ADD COLUMN page_description_suffix TEXT NOT NULL DEFAULT '',
ADD COLUMN publisher_type TEXT NOT NULL DEFAULT 'organization',
ADD COLUMN publisher_name TEXT NOT NULL DEFAULT '',
ADD COLUMN publisher_logo TEXT NOT NULL DEFAULT '',
ADD COLUMN publisher_url TEXT NOT NULL DEFAULT '',
ADD COLUMN publisher_email TEXT NOT NULL DEFAULT '',
ADD COLUMN publisher_phone TEXT NOT NULL DEFAULT '',
ADD COLUMN publisher_same_as TEXT NOT NULL DEFAULT '',
ADD COLUMN local_enabled BOOLEAN NOT NULL DEFAULT FALSE,
ADD COLUMN local_type TEXT NOT NULL DEFAULT 'LocalBusiness',
ADD COLUMN local_price_range TEXT NOT NULL DEFAULT '',
ADD COLUMN local_street TEXT NOT NULL DEFAULT '',
ADD COLUMN local_postal_code TEXT NOT NULL DEFAULT '',
ADD COLUMN local_city TEXT NOT NULL DEFAULT '',
ADD COLUMN local_region TEXT NOT NULL DEFAULT '',
ADD COLUMN local_country TEXT NOT NULL DEFAULT '',
ADD COLUMN local_latitude TEXT NOT NULL DEFAULT '',
ADD COLUMN local_longitude TEXT NOT NULL DEFAULT '',
ADD COLUMN local_hours JSONB NULL`).Error
},
Rollback: func(tx *gorm.DB) error {
return tx.Exec(`ALTER TABLE golem15_seo_settings
DROP COLUMN IF EXISTS breadcrumb_home, DROP COLUMN IF EXISTS page_form,
DROP COLUMN IF EXISTS page_segment, DROP COLUMN IF EXISTS page_title_suffix,
DROP COLUMN IF EXISTS page_description_suffix, DROP COLUMN IF EXISTS publisher_type,
DROP COLUMN IF EXISTS publisher_name, DROP COLUMN IF EXISTS publisher_logo,
DROP COLUMN IF EXISTS publisher_url, DROP COLUMN IF EXISTS publisher_email,
DROP COLUMN IF EXISTS publisher_phone, DROP COLUMN IF EXISTS publisher_same_as,
DROP COLUMN IF EXISTS local_enabled, DROP COLUMN IF EXISTS local_type,
DROP COLUMN IF EXISTS local_price_range, DROP COLUMN IF EXISTS local_street,
DROP COLUMN IF EXISTS local_postal_code, DROP COLUMN IF EXISTS local_city,
DROP COLUMN IF EXISTS local_region, DROP COLUMN IF EXISTS local_country,
DROP COLUMN IF EXISTS local_latitude, DROP COLUMN IF EXISTS local_longitude,
DROP COLUMN IF EXISTS local_hours`).Error
},
},
}
func init() {
Register(addPublisherPagination...)
}