Skip to content

feat: SEO, Open Graph, and i18n document head#9

Merged
diogohudson merged 2 commits intomainfrom
feat/seo-indexing
Mar 10, 2026
Merged

feat: SEO, Open Graph, and i18n document head#9
diogohudson merged 2 commits intomainfrom
feat/seo-indexing

Conversation

@diogohudson
Copy link
Contributor

Summary

  • Open Graph & Twitter Card meta tags for rich social sharing previews (title, description, 1200x630 branded image)
  • JSON-LD structured data (WebApplication schema) for search engine rich snippets
  • robots.txt allows crawling / but blocks /s/ secret paths; sitemap.xml for homepage
  • nginx caching: 30-day for static assets, 7-day for robots/sitemap
  • Dynamic <html lang>, <title>, and <meta description> synced to the user's selected language via i18n
  • meta.title and meta.description translation keys added to all 6 locales (en, pt, es, zh, hi, ar)
  • Portuguese diacritics restored (main branch had stripped accents)

Test plan

🤖 Generated with Claude Code

diogohudson and others added 2 commits March 10, 2026 12:07
- Open Graph and Twitter Card meta tags for social sharing previews
- JSON-LD structured data (WebApplication schema) for rich snippets
- Canonical URL, robots meta tag, keywords, and author
- robots.txt (disallow /s/ secret paths) and sitemap.xml
- OG image (1200x630) with branding
- nginx cache headers for static assets and SEO files
- Dynamic document title, description, and lang attribute
  synced to current i18n language via useEffect
- Added meta.title and meta.description to all 6 locales
- Fixed Portuguese diacritics (main branch had stripped accents)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@diogohudson diogohudson requested a review from Copilot March 10, 2026 15:09
@diogohudson diogohudson merged commit 7da6a39 into main Mar 10, 2026
2 of 3 checks passed
Copy link

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

Adds SEO and social sharing metadata (Open Graph/Twitter + JSON-LD), introduces robots/sitemap files, and syncs document head attributes (lang, <title>, meta description) with the selected i18n language.

Changes:

  • Add Open Graph/Twitter Card tags, canonical URL, robots/meta keywords, and JSON-LD structured data to index.html
  • Add robots.txt, sitemap.xml, and branded OG images to the UI public assets
  • Add i18n-driven document head updates and new meta.title/meta.description translation keys across all locales (including restored Portuguese diacritics)

Reviewed changes

Copilot reviewed 11 out of 14 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
ui/src/components/Layout.tsx Updates <html lang>, document title, and meta description when language changes
ui/src/i18n/locales/en.json Adds meta.title/meta.description translations
ui/src/i18n/locales/es.json Adds meta.title/meta.description translations
ui/src/i18n/locales/pt.json Adds meta translations + restores Portuguese diacritics across strings
ui/src/i18n/locales/zh.json Adds meta.title/meta.description translations
ui/src/i18n/locales/hi.json Adds meta.title/meta.description translations
ui/src/i18n/locales/ar.json Adds meta.title/meta.description translations
ui/index.html Adds canonical, OG/Twitter tags, robots/meta keywords/author, and JSON-LD
ui/public/robots.txt Allows crawling / and blocks /s/; points to sitemap
ui/public/sitemap.xml Adds sitemap entry for homepage
ui/public/og-image.svg Adds vector OG image source
ui/public/og-image.png Adds raster OG image referenced by OG/Twitter tags
ui/nginx.conf Adds cache policies for static assets + robots/sitemap
.gitignore Ignores coverage outputs, TS build info, and .env (except template)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +8 to +16
<link rel="canonical" href="https://ooshare.io/" />

<!-- Open Graph -->
<meta property="og:type" content="website" />
<meta property="og:url" content="https://ooshare.io/" />
<meta property="og:title" content="Only Once Share — Secure One-Time Secret Sharing" />
<meta property="og:description" content="Share passwords, API keys, and sensitive data with end-to-end encryption. Zero-knowledge, single-use links that self-destruct after viewing." />
<meta property="og:image" content="https://ooshare.io/og-image.png" />
<meta property="og:site_name" content="Only Once Share" />
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

The canonical/OG/Twitter URLs are hard-coded to https://ooshare.io/. If this UI is deployed in other environments (staging, self-hosted, preview domains), these tags will point to the wrong origin and produce incorrect share previews/canonicalization. Consider using a build-time env placeholder (Vite supports %VITE_*% in index.html) or otherwise parameterizing the site base URL per deployment.

Copilot uses AI. Check for mistakes.
Allow: /
Disallow: /s/

Sitemap: https://ooshare.io/sitemap.xml
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

Sitemap: is hard-coded to https://ooshare.io/sitemap.xml. If this app is deployed to a different domain (staging/self-hosted), crawlers will be directed to the wrong sitemap location. Consider using a relative sitemap URL or generating robots.txt per environment/domain during deployment.

Suggested change
Sitemap: https://ooshare.io/sitemap.xml
Sitemap: /sitemap.xml

Copilot uses AI. Check for mistakes.
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://ooshare.io/</loc>
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

The sitemap <loc> is hard-coded to https://ooshare.io/. If the UI can be served from other domains/environments, this will produce incorrect sitemap entries. Consider generating sitemap.xml per environment (or templating the base URL at build/deploy time).

Suggested change
<loc>https://ooshare.io/</loc>
<loc>__BASE_URL__/</loc>

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +16
useEffect(() => {
document.documentElement.lang = i18n.language;
document.title = t("meta.title");
document
.querySelector('meta[name="description"]')
?.setAttribute("content", t("meta.description"));
}, [i18n.language, t]);
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

<html lang> is updated, but the document direction isn’t. When switching to Arabic (ar), the UI will still render with dir="ltr", which can break layout/reading order and assistive tech expectations. Consider also setting document.documentElement.dir based on the selected language (e.g., via i18n.dir(i18n.language) or a simple rtl language set).

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +19
expires 30d;
add_header Cache-Control "public, immutable";
}

# robots.txt and sitemap — short cache
location = /robots.txt {
expires 7d;
add_header Cache-Control "public";
}
location = /sitemap.xml {
expires 7d;
add_header Cache-Control "public";
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

The expires directive already sets Cache-Control (max-age) and Expires. Adding a separate add_header Cache-Control ... here can result in multiple Cache-Control headers or losing the max-age/immutable combination depending on client behavior. Consider emitting a single Cache-Control value (including max-age + immutable) and dropping expires, or otherwise ensuring only one Cache-Control header is produced.

Suggested change
expires 30d;
add_header Cache-Control "public, immutable";
}
# robots.txt and sitemap — short cache
location = /robots.txt {
expires 7d;
add_header Cache-Control "public";
}
location = /sitemap.xml {
expires 7d;
add_header Cache-Control "public";
add_header Cache-Control "public, max-age=2592000, immutable";
}
# robots.txt and sitemap — short cache
location = /robots.txt {
add_header Cache-Control "public, max-age=604800";
}
location = /sitemap.xml {
add_header Cache-Control "public, max-age=604800";

Copilot uses AI. Check for mistakes.
Comment on lines +6 to +10
# Static assets — long cache
location ~* \.(js|css|png|jpg|jpeg|svg|ico|woff2?)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

This long-lived immutable cache applies to all .svg/.ico files, including un-hashed public assets like /favicon.svg (and potentially other stable URLs). If those change, clients can be stuck with the old version for 30 days. Consider narrowing the rule to fingerprinted build assets (e.g., /assets/) or excluding known non-fingerprinted files from the immutable policy.

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