Files
anwar-pi-website/web/src/app/llms-full.txt/route.ts
T
AHMED 0161924088 Free early-access launch: LAUNCH_MODE policy, CRO, pipeline hardening, AI-SEO, ops
- launch.ts policy: LAUNCH_MODE=free_early_access default; effective access =
  published && (free || early); intended tier (access) never rewritten
- Billing off server-side: /api/subscribe 503 honest copy; subscribe CTAs
  render disabled 'قريباً' from first paint; /subscription early-access panel
  + /api/notify (LaunchNotifications) with honest 503 when mail transport off
- Signup trust: verification email at signup (Users afterChange), no
  confirm-password, 429 message fidelity, typo suggestion, live password hint
- Agent pipeline: pickFields strips access/readingMinutes, sourceId dedup,
  secret-scan 422 (pattern names only), string-content rejected (was silently
  replaced), publish stays explicit opt-in
- lexical.ts: root unwrap fix — lexicalToText/countLexicalWords returned 0
  for real serialized trees (secret scan + readingMinutes were inert)
- llms-full.txt: fetchIndexDocs(true) — bodies were never selected
- Content honesty: contentType/authorName/sourceId fields + migration,
  readingMinutes computed at write (160 wpm) + backfill script, byline,
  'حُدّث' freshness
- SEO/AI-SEO: metadata rewrite (published-only, og:image 1200x630), Article +
  BreadcrumbList + FAQPage + Organization JSON-LD, isAccessibleForFree honest,
  table renderer, robots AI-crawler policy (10 named bots), llms.txt +
  llms-full.txt, /topics/* hubs + sitemap, noindex auth pages, www 301
- Ops: backup-db.sh (restore rehearsed on VPS), docs copies (launch
  readiness + marketing audit + owner-inputs for L-03), GLOSSARY.md entries

Verified: tsc --noEmit 0, npm run build 0, local smoke (ghost VIP read,
subscribe/notify/agent APIs, signup token, 429 on 6th, llms/topics/sitemap,
og:image/JSON-LD)
2026-10-10 18:03:45 +03:00

46 lines
1.6 KiB
TypeScript

import { SITE_INTRO, SITE_TITLE, fetchIndexDocs, renderIndexSections, type IndexDoc } from '@/lib/llms'
import { freeEarlyAccess } from '@/lib/launch'
import { formatDate } from '@/lib/format'
import { lexicalToPlain } from '@/lib/lexical'
export const dynamic = 'force-dynamic'
export async function GET(): Promise<Response> {
const early = freeEarlyAccess()
// Public read path: the content field's read ACL already decides body
// availability — with early access every published body passes; with billing
// on, VIP bodies come back undefined and are listed members-only.
const docs = await fetchIndexDocs(true) as (IndexDoc & { content?: unknown })[]
const parts: string[] = [
`# ${SITE_TITLE}`,
'',
`> ${SITE_INTRO}`,
'',
renderIndexSections(docs, !early),
'---',
'',
'# الأدلة الكاملة',
'',
]
for (const doc of docs) {
const vipOnly = !early && doc.access === 'vip'
const suffix = vipOnly ? ' (دليل للأعضاء)' : ''
parts.push(`## ${doc.title}${suffix}`, '')
parts.push(`URL: /posts/${doc.slug}`, '')
if (doc.dek) parts.push(doc.dek, '')
if (doc.updatedAt && doc.publishedAt && doc.updatedAt !== doc.publishedAt) {
parts.push(`حُدّث: ${formatDate(doc.updatedAt)}`, '')
}
if (vipOnly) {
parts.push('هذا الدليل متاح للأعضاء فقط. العضوية: /subscription', '')
} else if (typeof doc.content === 'object' && doc.content !== null) {
parts.push(lexicalToPlain(doc.content), '')
}
parts.push('---', '')
}
return new Response(parts.join('\n'), { headers: { 'content-type': 'text/plain; charset=utf-8' } })
}