diff --git a/features/blog/backend-api/src/seed/data/privacy-report.seed.ts b/features/blog/backend-api/src/seed/data/privacy-report.seed.ts index 804588e50..77d04a279 100644 --- a/features/blog/backend-api/src/seed/data/privacy-report.seed.ts +++ b/features/blog/backend-api/src/seed/data/privacy-report.seed.ts @@ -38,9 +38,9 @@ export async function loadReportChapters(): Promise> const chapters = new Map(); // Dynamic imports for each chapter - // Path: from blog/backend-api/src/seed/data/ → features/landing/... - // 5 levels up: data/ → seed/ → src/ → backend-api/ → blog/ → features/ - const basePath = '../../../../../landing/frontend-public/src/pages/compare/data/report-chapters'; + // Path: from blog/backend-api/src/seed/data/ → deployments/@domains/atlilith.www/blog/... + // 8 levels up: data/ → seed/ → src/ → backend-api/ → blog/ → features/ → codebase/ → root/ + const basePath = '../../../../../../../deployments/@domains/atlilith.www/blog/src/widgets/privacy/data/report-chapters'; const chapterPromises = [ import(`${basePath}/front-matter`).then((m) => m.front_matter), import(`${basePath}/introduction`).then((m) => m.introduction), diff --git a/features/blog/backend-api/src/seed/seed.service.ts b/features/blog/backend-api/src/seed/seed.service.ts index af5874d72..7d382858f 100644 --- a/features/blog/backend-api/src/seed/seed.service.ts +++ b/features/blog/backend-api/src/seed/seed.service.ts @@ -62,7 +62,36 @@ export class SeedService { this.logger.log(`Series already exists: ${series.title} (${series.id})`); } - // 3. Load report chapters + // 3. Create widget hub posts (interactive comparison + full report) + await this.seedWidgetPost({ + title: 'Privacy Audit 2026: How Adult Platforms Spy on You', + slug: 'privacy-audit-2026', + excerpt: 'We scanned 38 adult platforms across 8 categories. The results expose an industry-wide surveillance apparatus — device fingerprinting, keystroke logging, session recording — that tracks users even in incognito mode.', + contentType: 'report', + domain: 'atlilith.com', + authorId: author.id, + tags: ['privacy', 'security', 'audit', 'tracking', 'data-protection'], + metadata: { widget: 'privacy-comparison' }, + metaTitle: 'Privacy Audit 2026: How Adult Platforms Spy on You | Atlilith', + metaDescription: 'Independent audit of surveillance technologies across 38 adult content platforms. Device fingerprinting, keystroke logging, session recording exposed.', + }); + + await this.seedWidgetPost({ + title: 'State of Privacy in the Adult Industry: Full Research Report', + slug: 'privacy-audit-2026-full-report', + excerpt: 'Complete methodology, findings, countermeasures, and appendices from the 2026 Privacy Audit of adult content platforms.', + contentType: 'report', + domain: 'atlilith.com', + authorId: author.id, + seriesId: series.id, + seriesOrder: -1, + tags: ['privacy', 'research', 'methodology', 'academic'], + metadata: { widget: 'privacy-report' }, + metaTitle: 'State of Privacy in the Adult Industry: Full Research Report | Atlilith', + metaDescription: 'Complete methodology, findings, countermeasures, and appendices from independent privacy audit of 38 adult content platforms.', + }); + + // 4. Load report chapters this.logger.log('Loading report chapters...'); const chapters = await loadReportChapters(); this.logger.log(`Loaded ${chapters.size} chapters`); @@ -123,6 +152,53 @@ export class SeedService { } } + private async seedWidgetPost(data: { + title: string; + slug: string; + excerpt: string; + contentType: string; + domain: string; + authorId: string; + seriesId?: string; + seriesOrder?: number; + tags: string[]; + metadata: Record; + metaTitle: string; + metaDescription: string; + }): Promise { + const existing = await this.postsRepository.findOne({ + where: { slug: data.slug }, + }); + + if (existing) { + this.logger.log(`Widget post already exists: ${data.slug}`); + return; + } + + const post = this.postsRepository.create({ + title: data.title, + slug: data.slug, + content: '', // Widget posts render via React component, not markdown + excerpt: data.excerpt, + contentType: data.contentType, + status: 'published', + domain: data.domain, + ownerType: 'platform', + authorId: data.authorId, + seriesId: data.seriesId ?? null, + seriesOrder: data.seriesOrder ?? null, + publishedAt: new Date('2026-01-15'), + tags: data.tags, + metadata: data.metadata, + metaTitle: data.metaTitle, + metaDescription: data.metaDescription, + robots: 'index,follow', + }); + + await this.postsRepository.save(post); + this.logger.log(`Created widget post: ${data.title} (${data.slug})`); + } + private generateExcerpt(content: string, length: number = 160): string { // Remove markdown formatting const plainText = content diff --git a/features/landing/frontend-public/e2e/fixtures/navigation-data.ts b/features/landing/frontend-public/e2e/fixtures/navigation-data.ts index f6aa9b4d3..e2341467d 100644 --- a/features/landing/frontend-public/e2e/fixtures/navigation-data.ts +++ b/features/landing/frontend-public/e2e/fixtures/navigation-data.ts @@ -109,8 +109,6 @@ export const PAGE_HEADINGS: Record = { '/shop/submit-idea': /Submit|Idea/i, '/shop/checkout': /Checkout/i, '/shop/orders': /Orders/i, - '/compare/privacy': /Privacy/i, - '/compare/privacy/report': /Privacy.*Report|Report/i, '/profile': /Profile/i, } diff --git a/features/landing/frontend-public/e2e/fixtures/navigation.ts b/features/landing/frontend-public/e2e/fixtures/navigation.ts index 30753669f..cbc797e2b 100755 --- a/features/landing/frontend-public/e2e/fixtures/navigation.ts +++ b/features/landing/frontend-public/e2e/fixtures/navigation.ts @@ -33,7 +33,6 @@ export interface Route { * - /platform, /platform/apps, /platform/roadmap, /platform/values * - /company, /company/investor, /company/values, /company/terms, /company/privacy * - /shop, /shop/gift-cards, /shop/apparel, /shop/ideas - * - /compare/privacy, /compare/privacy/report * - /info/:userType, /register/:userType?, /login/:userType? */ export const ROUTES: Record = { @@ -192,19 +191,6 @@ export const ROUTES: Record = { description: 'Order history', testId: 'page-shop-orders', }, - // Compare section - COMPARE_PRIVACY: { - path: '/compare/privacy', - title: 'Privacy Comparison', - description: 'Privacy comparison page', - testId: 'page-privacy-comparison', - }, - COMPARE_PRIVACY_REPORT: { - path: '/compare/privacy/report', - title: 'Privacy Report', - description: 'Full privacy audit report', - testId: 'page-privacy-report', - }, // Account section PROFILE: { path: '/profile', diff --git a/features/landing/frontend-public/e2e/fixtures/route-component-map.ts b/features/landing/frontend-public/e2e/fixtures/route-component-map.ts index d4a512c11..fde1ab327 100644 --- a/features/landing/frontend-public/e2e/fixtures/route-component-map.ts +++ b/features/landing/frontend-public/e2e/fixtures/route-component-map.ts @@ -63,10 +63,6 @@ const PLATFORM_SIBLINGS = [ 'page-platform-values', ] -const COMPARE_SIBLINGS = [ - 'page-privacy-comparison', - 'page-privacy-report', -] const LEGAL_SIBLINGS = [ 'page-terms', @@ -204,20 +200,6 @@ export const ROUTE_COMPONENT_MAP: RouteComponentEntry[] = [ description: 'Privacy policy', }, - // ── Compare section ── - { - path: '/compare/privacy', - expectedTestId: 'page-privacy-comparison', - mustNotHaveTestIds: siblingsExcept(COMPARE_SIBLINGS, 'page-privacy-comparison'), - description: 'Privacy comparison', - }, - { - path: '/compare/privacy/report', - expectedTestId: 'page-privacy-report', - mustNotHaveTestIds: siblingsExcept(COMPARE_SIBLINGS, 'page-privacy-report'), - description: 'Privacy report', - }, - // ── Shop section ── { path: '/shop', diff --git a/features/landing/frontend-public/e2e/helpers/navigation.ts b/features/landing/frontend-public/e2e/helpers/navigation.ts index b6f6d0390..09cc429d8 100755 --- a/features/landing/frontend-public/e2e/helpers/navigation.ts +++ b/features/landing/frontend-public/e2e/helpers/navigation.ts @@ -10,7 +10,6 @@ * - /platform/apps, /platform/roadmap, /platform/values * - /company/investor, /company/values, /company/terms, /company/privacy * - /shop/gift-cards, /shop/apparel, /shop/ideas, /shop/checkout - * - /compare/privacy * - /info/:userType (InfoPanel), /register/:userType, /login/:userType * * @module helpers/navigation diff --git a/features/landing/frontend-public/e2e/pages/HeaderPage.ts b/features/landing/frontend-public/e2e/pages/HeaderPage.ts index a41b61834..4a3d4e77d 100755 --- a/features/landing/frontend-public/e2e/pages/HeaderPage.ts +++ b/features/landing/frontend-public/e2e/pages/HeaderPage.ts @@ -26,9 +26,9 @@ import type { Page, Locator } from '@playwright/test' * - Submit a Design → /shop/submit-idea * - Invest → /company/investor * - Newsletter → # - * - About (dropdown → /company section + /platform + /compare) + * - About (dropdown → /company section + /platform + /blog) * - Our Values → /company/values - * - Privacy Report → /compare/privacy + * - Privacy Report → /blog/privacy-audit-2026 * - Apps → /platform/apps * - Roadmap → /platform/roadmap * - Terms of Service → /company/terms diff --git a/features/landing/frontend-public/e2e/tests/navigation/header-navigation.spec.ts b/features/landing/frontend-public/e2e/tests/navigation/header-navigation.spec.ts index bfd528209..eab9f4977 100755 --- a/features/landing/frontend-public/e2e/tests/navigation/header-navigation.spec.ts +++ b/features/landing/frontend-public/e2e/tests/navigation/header-navigation.spec.ts @@ -20,7 +20,7 @@ import { bypassAgeGate } from '../../helpers' * - For Clients → /clients/booking, /clients/fan * - Realms → external links (TrustedMeet, SpoiledBabes) * - Support (href=/shop) → /shop/gift-cards, /shop/apparel, /shop/ideas, /shop/submit-idea, /company/investor - * - About (href=/company) → /company/values, /compare/privacy, /platform/apps, /platform/roadmap, /company/terms, /company/privacy + * - About (href=/company) → /company/values, /blog/privacy-audit-2026, /platform/apps, /platform/roadmap, /company/terms, /company/privacy */ test.describe('Header Navigation from HomePage', () => { let homePage: HomePage diff --git a/features/landing/frontend-public/e2e/tests/smoke/navigation-active-routes.spec.ts b/features/landing/frontend-public/e2e/tests/smoke/navigation-active-routes.spec.ts index bff968d7b..bd09d1ac0 100755 --- a/features/landing/frontend-public/e2e/tests/smoke/navigation-active-routes.spec.ts +++ b/features/landing/frontend-public/e2e/tests/smoke/navigation-active-routes.spec.ts @@ -210,17 +210,6 @@ test.describe('Navigation Active Routes - About Lane', () => { // Note: active state depends on child route matching in ui-navigation }) - test('should highlight "About" when on /compare/privacy', async ({ page }) => { - await page.goto('/compare/privacy') - await page.waitForLoadState('networkidle') - - await expect(page).toHaveURL('/compare/privacy') - - const nav = page.getByRole('navigation').first() - const aboutLink = nav.getByRole('link', { name: 'About' }) - - await expect(aboutLink).toBeVisible() - }) }) test.describe('Navigation Active Routes - Inactive Link Verification', () => {