Skip to content

feat: add legal page with privacy policy and transparency info#3825

Merged
MarkusNeusinger merged 5 commits intomainfrom
feat/legal-page-3818
Jan 13, 2026
Merged

feat: add legal page with privacy policy and transparency info#3825
MarkusNeusinger merged 5 commits intomainfrom
feat/legal-page-3818

Conversation

@MarkusNeusinger
Copy link
Copy Markdown
Owner

Summary

  • Add new /legal page with Legal Notice, Privacy Policy, and Transparency sections
  • Add footer link to legal page
  • Update sitemap to include legal page

Legal Notice

  • Operator info (Markus Neusinger, Visp, Switzerland)
  • Disclaimer for AI-powered visualization examples
  • MIT License reference

Privacy Policy

  • Accurate Plausible Analytics tracking disclosure (page views, navigation, code copies, etc.)
  • Public analytics dashboard link
  • Server logs info (IP addresses, 30 days retention via Google Cloud Logging)
  • Clear "What We Do NOT Collect" section (no cookies, no AI training)
  • GDPR/Swiss DSG rights info

Transparency

  • Full technology stack with links (PyCharm, React, Vite, MUI, Python, FastAPI, PostgreSQL 18, etc.)
  • Accurate monthly hosting costs (~$34/month)
  • Source code link

UX Improvements

  • Jump links (table of contents) at top
  • "Last updated" date at bottom
  • Consistent styling with MonoLisa font

Test plan

  • Visit http://localhost:3000/legal
  • Verify all external links open correctly
  • Test jump links scroll to sections
  • Check footer link works

🤖 Generated with Claude Code

- Implement LegalPage component with legal notice and privacy policy
- Add link to legal page in footer
- Update router to include legal route
- Implement bot-optimized legal page with appropriate og:tags
- Add legal page URL to sitemap
- Update documentation to include legal page in routes
- Adjust font sizes for headings and subheadings
- Modify breadcrumb margin for better spacing
- Add links for Legal Notice, Privacy Policy, and Transparency sections
- Enhance disclaimer and analytics descriptions
- Update monthly costs section with accurate figures
- Improve overall layout and styling for better readability
Copilot AI review requested due to automatic review settings January 13, 2026 21:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds a comprehensive legal page to the website containing legal notice, privacy policy, and transparency information. The implementation includes proper SEO support, navigation integration, and consistent styling with the rest of the application.

Changes:

  • New /legal route with detailed legal information (operator details, privacy policy, transparency about tech stack and costs)
  • Footer link to access the legal page
  • SEO enhancements including sitemap entry and bot-optimized page with Open Graph tags

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
app/src/pages/LegalPage.tsx New legal page component with three sections: Legal Notice, Privacy Policy, and Transparency
app/src/router.tsx Added route configuration for /legal path
app/src/components/Footer.tsx Added footer link to legal page with RouterLink
app/src/hooks/useUrlSync.ts Removed unused FilterCategory import (cleanup)
api/routers/seo.py Added /seo-proxy/legal endpoint and legal page URL to sitemap
docs/reference/seo.md Updated documentation to reflect legal page in SEO proxy endpoints and sitemap
docs/reference/plausible.md Added legal page to tracked pages documentation

<Link href="https://postgresql.org" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
PostgreSQL
</Link>{' '}
18
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PostgreSQL version listed as "18" appears to be incorrect. According to the project documentation in .github/copilot-instructions.md, the project uses PostgreSQL 15. Please update this to match the actual deployed version.

Suggested change
18
15

Copilot uses AI. Check for mistakes.
Comment thread api/routers/seo.py
Comment on lines +135 to +145
@router.get("/seo-proxy/legal")
async def seo_legal():
"""Bot-optimized legal page with correct og:tags."""
return HTMLResponse(
BOT_HTML_TEMPLATE.format(
title="Legal | pyplots.ai",
description="Legal notice, privacy policy, and transparency information for pyplots.ai",
image=DEFAULT_HOME_IMAGE,
url="https://pyplots.ai/legal",
)
)
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new seo_legal endpoint lacks test coverage. Based on the existing test patterns in tests/unit/api/test_routers.py (TestSeoProxyRouter class), this endpoint should have a unit test to verify it returns the correct HTML response with proper og:tags for the legal page.

Copilot uses AI. Check for mistakes.
Comment thread api/routers/seo.py
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
" <url><loc>https://pyplots.ai/</loc></url>",
" <url><loc>https://pyplots.ai/catalog</loc></url>",
" <url><loc>https://pyplots.ai/legal</loc></url>",
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The addition of the legal page URL to the sitemap lacks test coverage. The existing tests in tests/unit/api/test_routers.py (test_sitemap_structure and test_sitemap_with_db methods) should be updated to verify that the sitemap includes the legal page URL.

Copilot uses AI. Check for mistakes.
Comment on lines +68 to +78
<Link
component={RouterLink}
to="/legal"
sx={{
color: '#9ca3af',
textDecoration: 'none',
'&:hover': { color: '#6b7280' },
}}
>
legal
</Link>
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new legal link in the footer is missing an onClick handler for analytics tracking. The other footer links (linkedin, github, stats) all have onClick handlers that call onTrackEvent. For consistency and to track user navigation to the legal page from the footer, consider adding an onClick handler similar to the pattern used for external links.

Copilot uses AI. Check for mistakes.
@codecov
Copy link
Copy Markdown

codecov Bot commented Jan 13, 2026

Codecov Report

❌ Patch coverage is 66.66667% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
api/routers/seo.py 66.66% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

- Clarified rights under GDPR and Swiss DSG
- Improved wording for better readability
- Adjust legal page component in footer to include tracking event
- Update cloud SQL version in copilot instructions
Copilot AI review requested due to automatic review settings January 13, 2026 21:32
@MarkusNeusinger MarkusNeusinger merged commit b4bf549 into main Jan 13, 2026
13 checks passed
@MarkusNeusinger MarkusNeusinger deleted the feat/legal-page-3818 branch January 13, 2026 21:36
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment on lines +134 to +334
<Link href="https://plausible.io" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
Plausible Analytics
</Link>
, a privacy-focused analytics tool. It collects no personal data, uses no cookies, and does not track you
across websites. We track: page views, navigation patterns, code copies, image downloads, search queries,
filter usage, and UI interactions. When you share a link, we detect which platform requests the preview
(e.g., LinkedIn, WhatsApp). All data is aggregated and anonymous.
</Typography>
<Typography sx={textStyle}>
<strong>Public Dashboard</strong>: Our analytics are{' '}
<Link href="https://plausible.io/pyplots.ai" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
fully public
</Link>{' '}
– see exactly what we see.
</Typography>
<Typography sx={textStyle}>
<strong>Server Logs</strong>: Technical server logs including IP addresses, request URLs, and user agents
are retained for 30 days via{' '}
<Link href="https://cloud.google.com/logging" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
Google Cloud Logging
</Link>{' '}
for security and debugging purposes.
</Typography>

<Typography sx={subheadingStyle}>What We Do NOT Collect</Typography>
<Typography sx={textStyle}>
• No user accounts or personal profiles
<br />
• No personal data (names, emails, etc.)
<br />
• No cookies at all (we use localStorage for UI preferences only)
<br />• <strong>No AI training</strong>: Your interactions are not used to train AI models
</Typography>

<Typography sx={textStyle}>
<strong>Contributors</strong>: If you suggest a plot type via GitHub, your GitHub username may be credited
in the specification metadata. This is public information from your GitHub profile.
</Typography>

<Typography sx={subheadingStyle}>Hosting &amp; Third Parties</Typography>
<Typography sx={textStyle}>All services are hosted in the EU (Netherlands, europe-west4):</Typography>
<Table sx={tableStyle}>
<TableBody>
<TableRow>
<TableCell>Hosting</TableCell>
<TableCell>Google Cloud Run (Netherlands)</TableCell>
</TableRow>
<TableRow>
<TableCell>Database</TableCell>
<TableCell>Google Cloud SQL (Netherlands)</TableCell>
</TableRow>
<TableRow>
<TableCell>Storage</TableCell>
<TableCell>Google Cloud Storage (Netherlands)</TableCell>
</TableRow>
<TableRow>
<TableCell>Analytics</TableCell>
<TableCell>Plausible Analytics (EU, proxied)</TableCell>
</TableRow>
</TableBody>
</Table>

<Typography sx={subheadingStyle}>Your Rights</Typography>
<Typography sx={textStyle}>
You have the right to access, rectify, erase, and export your data. Since we do not store personal data,
there is typically nothing to delete or export. For questions, contact{' '}
<Link href="mailto:admin@pyplots.ai" sx={{ color: '#3776AB' }}>
admin@pyplots.ai
</Link>
.
</Typography>
</Paper>

{/* Transparency */}
<Paper component="section" id="transparency" sx={{ p: 3, mb: 2 }}>
<Typography variant="h2" sx={headingStyle}>
Transparency
</Typography>

<Typography sx={textStyle}>
This project is open source and committed to full transparency about how it works and what it costs.
</Typography>

<Typography sx={subheadingStyle}>Technology Stack</Typography>
<Table sx={tableStyle}>
<TableBody>
<TableRow>
<TableCell>Editor</TableCell>
<TableCell>
<Link href="https://www.jetbrains.com/pycharm/" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
JetBrains PyCharm
</Link>
</TableCell>
</TableRow>
<TableRow>
<TableCell>Frontend</TableCell>
<TableCell>
<Link href="https://react.dev" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
React
</Link>{' '}
19,{' '}
<Link href="https://vite.dev" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
Vite
</Link>
,{' '}
<Link href="https://mui.com" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
MUI
</Link>{' '}
7,{' '}
<Link href="https://typescriptlang.org" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
TypeScript
</Link>
</TableCell>
</TableRow>
<TableRow>
<TableCell>Backend</TableCell>
<TableCell>
<Link href="https://python.org" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
Python
</Link>{' '}
3.13,{' '}
<Link href="https://fastapi.tiangolo.com" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
FastAPI
</Link>
,{' '}
<Link href="https://sqlalchemy.org" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
SQLAlchemy
</Link>
</TableCell>
</TableRow>
<TableRow>
<TableCell>Database</TableCell>
<TableCell>
<Link href="https://postgresql.org" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
PostgreSQL
</Link>{' '}
18
</TableCell>
</TableRow>
<TableRow>
<TableCell>Hosting</TableCell>
<TableCell>
<Link href="https://cloud.google.com/run" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
Google Cloud Run
</Link>{' '}
(Netherlands)
</TableCell>
</TableRow>
<TableRow>
<TableCell>Storage</TableCell>
<TableCell>
<Link href="https://cloud.google.com/storage" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
Google Cloud Storage
</Link>
</TableCell>
</TableRow>
<TableRow>
<TableCell>Analytics</TableCell>
<TableCell>
<Link href="https://plausible.io" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
Plausible
</Link>{' '}
(privacy-friendly, no cookies,{' '}
<Link href="https://plausible.io/pyplots.ai" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
public dashboard
</Link>
)
</TableCell>
</TableRow>
<TableRow>
<TableCell>Code Generation</TableCell>
<TableCell>
<Link href="https://anthropic.com" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
Anthropic Claude
</Link>{' '}
(code generation &amp; review),{' '}
<Link href="https://github.com/features/copilot" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
GitHub Copilot
</Link>{' '}
(PR reviews)
</TableCell>
</TableRow>
<TableRow>
<TableCell>Typography</TableCell>
<TableCell>
<Link href="https://www.monolisa.dev/" target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
MonoLisa
</Link>{' '}
by Marcus Sterz
</TableCell>
</TableRow>
</TableBody>
</Table>

<Typography sx={subheadingStyle}>Source Code</Typography>
<Typography sx={textStyle}>
The entire codebase is publicly available under the MIT License:
<br />
<Link href={GITHUB_URL} target="_blank" rel="noopener" sx={{ color: '#3776AB' }}>
github.com/MarkusNeusinger/pyplots
</Link>
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

External links should include both noopener and noreferrer in the rel attribute for security and privacy best practices. The Footer component uses rel="noopener noreferrer" while this page uses only rel="noopener". Update all external links to use rel="noopener noreferrer" for consistency with the rest of the application.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants