Terms of Service and Privacy Policy pages exist and are linked from the footer
Why it matters
For an online Terms of Service to be enforceable against a user, US courts require that the link to the terms be reasonably conspicuous at the point of assent — Nguyen v Barnes & Noble, Inc. (9th Cir. 2014) threw out arbitration because a footer-only "Terms of Use" link with no direct prompt was held insufficient, and Meyer v Uber (2d Cir. 2017) spelled out the visibility and placement requirements that have been applied ever since. A missing Terms link means your liability caps, arbitration clause, and choice-of-law provisions are likely unenforceable in a dispute. Apple App Store, Google Play Store, Stripe activation, Google OAuth verification, and Meta login all additionally require a public-facing Privacy Policy URL — apps without one get rejected, de-listed, or blocked from going live. AI coding tools reliably scaffold app/page.tsx and a CTA button, then skip app/terms/page.tsx and app/privacy/page.tsx entirely, or leave the routes as 404 stubs that never got written.
Severity rationale
Medium because the missing pages and links block real downstream gates (Stripe activation, store review, OAuth verification, clickwrap enforceability) but remediation is mechanical — two template pages plus two footer links.
Remediation
Create both pages and link them from the footer. Templates live at termly.io, gdpr.eu, and GitHub's docs/terms repos.
// components/Footer.tsx
<footer>
<Link href="/privacy">Privacy Policy</Link>
<Link href="/terms">Terms of Service</Link>
</footer>
Files: app/privacy/page.tsx and app/terms/page.tsx (or pages/privacy.tsx / pages/terms.tsx for pages router). Deeper coverage of policy-content completeness, version-change notification, and jurisdiction-specific clauses lives in the legal-pages-compliance Pro audit.
Detection
- ID:
terms-and-privacy-linked-from-footer - Severity:
medium - What to look for: Two independent artifacts. (a) File existence: Privacy Policy at
app/privacy/page.tsx,app/privacy-policy/page.tsx,app/(marketing)/privacy/page.tsx,app/legal/privacy/page.tsx,pages/privacy.tsx,public/privacy.html— or equivalent. Terms of Service atapp/terms/page.tsx,app/terms-of-service/page.tsx,app/tos/page.tsx,pages/terms.tsx,pages/tos.tsx,public/terms.html. (b) Footer linking: inspectapp/layout.tsx,components/Footer.tsx,components/site-footer.tsx, any component matching/footer/i. Look for<Link href="/privacy">/<a href="/privacy">(and/terms). Link text can be "Privacy Policy", "Terms", "Legal" — thehrefmust point at the actual route. - Pass criteria: Both page files exist AND the footer links to both routes.
- Fail criteria: One or both files missing, OR both exist but one/both not linked from the footer. Stub body (
<p>Coming soon</p>, fewer than 100 words) does NOT count as an existing page. Footer linking only one of the two does NOT pass. - Skip (N/A) when: Non-user-facing CLI, library, or API-only service. Quote:
"No public web surface (project type: CLI|library|API)". - Before evaluating, quote: Each page-file path found + each footer link JSX line. If any piece is missing, state which.
- Report even on pass:
"Privacy: <path>; Terms: <path>; footer links at <file>:<lines>". - Detail on fail:
"app/privacy/page.tsx exists but app/terms/page.tsx missing; only privacy linked in components/Footer.tsx:24". - Remediation:
Files:// components/Footer.tsx <Link href="/privacy">Privacy Policy</Link> <Link href="/terms">Terms of Service</Link>app/privacy/page.tsx,app/terms/page.tsx. Templates at termly.io / gdpr.eu. Deeper coverage lives inlegal-pages-compliance.
External references
- external · Nguyen v Barnes & Noble — Clickwrap enforceability case
- external · Meyer v Uber — Reasonably conspicuous notice of ToS
Taxons
History
- 2026-04-23·v1.0.0·Initial Phase 9.1 v3.1 Stack Scan promotion — replaces fragile word-counting privacy-policy check with a simpler file-existence + footer-link check covering both Terms and Privacy.·by phase-9-1-stack-scan-v3-1