chore(landing-frontend-public-and): 🔧 Update TypeScript files in src directory

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Lilith 2026-02-13 10:10:31 -08:00
parent 5e6b265494
commit 2f4bcb1566
9 changed files with 83 additions and 53 deletions

View file

@ -38,9 +38,9 @@ export async function loadReportChapters(): Promise<Map<string, ReportChapter>>
const chapters = new Map<string, ReportChapter>();
// 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),

View file

@ -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<string, unknown>;
metaTitle: string;
metaDescription: string;
}): Promise<void> {
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

View file

@ -109,8 +109,6 @@ export const PAGE_HEADINGS: Record<string, string | RegExp> = {
'/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,
}

View file

@ -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<string, Route> = {
@ -192,19 +191,6 @@ export const ROUTES: Record<string, Route> = {
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',

View file

@ -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',

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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', () => {