feat(site): prerender every locale and publish structured data, llms.txt and sitemaps
Some checks failed
ci / 정본·보안·린트·타입·테스트 (push) Successful in 53s
ci / 모바일 린트·타입·Jest (push) Successful in 45s
ci / Supabase Edge Functions + Cloudflare Worker (push) Successful in 21s
ci / .NET API 서버 테스트 (push) Successful in 13s
deploy-site / deploy (push) Failing after 27s
ci / 워크스페이스 빌드 검증 (push) Successful in 36s

Crawlers received an empty client-rendered shell (107 characters of text);
most AI crawlers do not run JavaScript, so the product was invisible to them.

- Build renders each locale to static HTML (/ for Korean, /en/ … /vi/) with
  src/entry-server.tsx + scripts/prerender.mjs; the browser hydrates the same
  locale. The language menu links to those pages instead of switching in place.
- Per-locale head: title, description, canonical, hreflang (+ x-default /en/),
  Open Graph and X cards with a per-locale 1200x630 image.
- JSON-LD graph: Organization, WebSite, WebPage, SoftwareApplication (KRW
  offers, version, release date, download URL from the canonical sources),
  HowTo and FAQPage. No invented ratings.
- robots.txt (search, ai-input and ai-train allowed; /app, /api, invites
  excluded), sitemap.xml with language alternates, llms.txt and llms-full.txt
  generated from the same translations and canonical values.
- IndexNow key and a post-deploy ping (Bing, Naver, Yandex).
- A factual "at a glance" section and two FAQ answers (recognised languages,
  where data is stored) in all 10 languages.
- Icons, apple-touch-icon and web manifest; asset base is now absolute so
  sub-path pages load the same bundle.

Verified: 3.6k-7.7k characters of text per page, no hydration warnings,
no overflow at 320/1440 in six locales, axe 0, Lighthouse mobile SEO,
accessibility and best practices 100.
This commit is contained in:
Yun Chan 2026-09-27 10:45:05 +09:00
parent 52e364e578
commit a0abda7a5c
45 changed files with 852 additions and 79 deletions

View file

@ -0,0 +1 @@
5d886cca4138946b8488203724b2f53d

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
site/public/og/de.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
site/public/og/en.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

BIN
site/public/og/es.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
site/public/og/fr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
site/public/og/ja.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
site/public/og/ko.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
site/public/og/pt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
site/public/og/ru.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
site/public/og/vi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
site/public/og/zh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View file

@ -0,0 +1,15 @@
{
"name": "D3RO Voice",
"short_name": "D3RO Voice",
"description": "Voice typing that runs on your PC — hold a key, speak, and the text is typed at your cursor.",
"start_url": "/",
"scope": "/",
"display": "browser",
"background_color": "#08090c",
"theme_color": "#08090c",
"icons": [
{ "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png" },
{ "src": "/icons/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
]
}