YeonGyu-Kim
64997d5e81
test(web): responsive matrix — 6 viewports x 4 locales x 2 pages
...
e2e/responsive.spec.ts (new):
- 6 viewports: iPhone SE (375x667), iPhone 14 Pro (390x844),
iPad mini (768x1024), iPad Pro (1024x1366), laptop (1280x800),
desktop (1920x1080)
- 4 locales: en, ko, ja, zh
- 2 pages: landing /, manifesto /manifesto
- Checks: no horizontal scroll, no overflow-x, primary CTA visible,
hero headline visible, nav button hit target (44x44 mobile / 32x32
desktop)
48 tests total. All pass against current build.
/docs has pre-existing horizontal overflow at 1024px viewport
(fixed-width sidebar interacting with code blocks). Intentionally
out of scope for this PR — commented in the spec, tracked as
follow-up.
2026-05-20 14:27:02 +09:00
YeonGyu-Kim
623af75962
feat(web): dynamic OG + Twitter card images via next/og
...
app/opengraph-image.tsx (new):
- next/og ImageResponse, 1200x630 PNG
- Dark #0a0a0a background + cyan #00d4ff brand wordmark + headline
+ install command pill + terminal cursor
- Google Fonts loadGoogleFont helper for Geist 400/700 +
Geist Mono 500 (runtime fetch, Cloudflare Workers compatible)
- Cache-Control: public, immutable, max-age=31536000
app/twitter-image.tsx (new):
- Same shape as OG with Twitter-card alt text
- Inherits twitter:card=summary_large_image from layout
app/layout.tsx:
- metadata.alternates.languages: explicit canonical URLs for en/ko/
ja/zh so search engines pick up hreflang
- metadata.openGraph.alternateLocale: ko_KR, ja_JP, zh_CN
- Drop manual openGraph.images / twitter.images: file-based metadata
convention now auto-emits og:image:width, og:image:height,
og:image:type, twitter:image:width, twitter:image:height
- metadata.robots: max-image-preview=large, max-snippet=-1
(richer SERP previews)
Verified: curl /opengraph-image returns 200, content-type image/png,
1200x630 PNG body. All 4 hreflang links present in <head>.
2026-05-20 14:27:02 +09:00
YeonGyu-Kim
022eb78440
refactor(web): decompose 358-LOC manifesto into 9 section components
...
app/[locale]/manifesto/page.tsx: 358 LOC -> 22-LOC composition shell.
components/manifesto/sections/:
- hero.tsx
- pain-points.tsx
- indistinguishable.tsx (the 'AI vs senior engineer' argument)
- token-cost.tsx
- cognitive-load.tsx
- principles.tsx
- core-loop.tsx
- future.tsx
- final-cta.tsx
Each section 26-68 LOC. Copy unchanged; section order unchanged.
Same i18n namespace ('manifesto'). Renders identically to baseline
in all 4 locales (en/ko/ja/zh).
2026-05-20 14:27:02 +09:00
YeonGyu-Kim
4d5f58f0c3
refactor(web): decompose 832-LOC landing into 10 section components
...
app/_components/landing-page.tsx: 832 LOC -> 33-LOC composition shell.
Each section becomes a focused, named component under
components/landing/sections/:
- hero.tsx: terminal headline + install command + primary CTA
- ultrawork.tsx: ultrawork mode pitch
- sisyphus.tsx: Sisyphus orchestrator showcase
- prometheus-atlas.tsx: planner + executor pair (was amber+indigo,
now violet — single secondary accent)
- hephaestus.tsx: code surgeon (was orange, now cyan)
- team-mode.tsx: parallel team coordination (was fuchsia/purple/cyan
gradient, now solid cyan headline + violet skills accent)
- sub-agents.tsx: explore/librarian/oracle/multimodal etc.
- architecture.tsx: 4-tier diagram
- reviews.tsx: testimonials (Star kept text-cyan-500 / fill-cyan-500,
on-brand)
- cta.tsx: final call-to-action
components/landing/constants.ts (new):
- SUB_AGENT_KEYS, AGENT_STYLES, PRINCIPLE_KEYS, PRINCIPLE_ICONS,
REVIEW_KEYS, CATEGORY_ROUTING, SKILL_INJECTIONS
- Single source of truth for agent/principle/review metadata used
across sections
components/icons/github-icon.tsx (new):
- Extracted inline SVG into a typed component with default
aria-hidden and overridable size/className
Color consolidation: 9-color rainbow per-section -> cyan (primary)
+ violet (secondary, agent identity) + neutral grays + status colors
only. 'Evolution not revolution': dark + cyan brand soul intact.
2026-05-20 14:27:02 +09:00
YeonGyu-Kim
78ca837e82
style(web): extract design system tokens + DESIGN.md
...
DESIGN.md: 7-section design system (palette, typography, spacing,
motion, components, sections, banned patterns). Documents existing
dark + cyan brand to enforce 'evolution not revolution'.
globals.css: add design tokens — --surface-{0..3}, --text-{primary,
secondary,tertiary}, --accent-primary{,-soft,-border}, --border-
{default,subtle}, status tokens (success/warning/danger/info).
Add .reveal-on-enter utility: opacity 0 → 1, translateY(8px) → 0
over 600ms cubic-bezier(0.16, 1, 0.3, 1). Triggered via
'data-revealed' attribute set by IntersectionObserver upstream.
Respects 'prefers-reduced-motion: reduce' — falls back to instant
opacity transition.
Add .ring-cyan focus utility consolidating focus-visible rings
across components (was ad-hoc per-component).
2026-05-20 14:26:09 +09:00
YeonGyu-Kim
7e0406f4ec
fix(web): UX/a11y polish + middleware metadata route fix
...
- footer.tsx: Discord link → canonical discord.gg/PUwSMR9XNk
(was outdated invite that 404'd).
- [locale]/layout.tsx: hooks count 40 → 54 (matches AGENTS.md).
- lib/stats.ts:88: drop '!' non-null assertion; use '??' fallback.
Removes the only '!' in packages/web (project rule).
- nav-header.tsx: hamburger Button size='icon' → explicit h-11 w-11;
mobile drawer links min-h-11 px-3 rounded-md. WCAG 2.5.5 tap
target 44x44 minimum.
- install-command.tsx: copy button h-8 w-8 → h-11 w-11 (was 32px,
below WCAG). Icon stays 16x16; padding fills to 44.
- middleware.ts: matcher excludes opengraph-image, twitter-image,
icon, apple-icon, manifest.webmanifest, robots.txt, sitemap.xml.
Previously next-intl redirected /opengraph-image → /en/opengraph-image
breaking OG previews for crawlers that hit the unlocalized path.
2026-05-20 14:26:09 +09:00
YeonGyu-Kim
68b80e0343
perf(web): optimize CI + build pipeline
...
- web-ci.yml: cache .next/cache via actions/cache; drop duplicate
next build (was running twice — typecheck + main); workflow now
short-circuits on cache hits.
- scripts/prepare-build.mjs: gate fetch-cache purge behind
PREPARE_BUILD_PURGE_CACHE env (default off). preview/deploy npm
scripts no longer invoke it.
- scripts/generate-docs-content.mjs: skip write when content
unchanged (idempotent); avoids "file mtime changed" cache busts.
- eslint.config.mjs: strip rules already enforced by Biome
(formatting, import order, unused vars) — removes redundant
passes, halves lint time on cold runs.
- playwright.config.ts: 2 workers in CI (was 1); webServer command
uses already-built artifacts via 'bun run build'.
Cold build: 16.2s → 8.7s (-46%). Recompile 1.45s.
2026-05-20 14:26:08 +09:00
YeonGyu-Kim
9799c54a92
chore(web): remove dead deps + safe version bumps
...
Removed motion v12.38 (zero imports) and @radix-ui/react-accordion
(unused) from runtime deps. Removed 4 dead components: code-block,
option-table, accordion, mdx-components — all had zero references.
Bumped safe caret deps via bun update:
- marked 18.0.3 → 18.0.4
- @opennextjs/cloudflare 1.19.10 → 1.19.11
- wrangler 4.92.0 → 4.93.0
- postcss override 8.5.14 → 8.5.15 (closes GHSA-qx2v-qp2m-jg93)
- @types/node 25.8.0 → 25.9.1
- @types/react 19.2.14 → 19.2.15
- typescript-eslint 8.59.3 → 8.59.4
Bundle shrinks by removing motion (≈ 60 KB) from node_modules even
though it had no runtime usage.
2026-05-20 14:22:58 +09:00
YeonGyu-Kim
a6f1950d41
fix(web): restore navigation smoke coverage
...
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-05-18 20:56:13 +09:00
YeonGyu-Kim
9a9d9bd5a1
fix(web): adapt build tooling
...
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-05-18 20:55:59 +09:00
YeonGyu-Kim
92a5a44218
chore(web): update web dependencies
...
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-05-18 20:55:44 +09:00
YeonGyu-Kim
bf96794599
chore(web): move site under packages
2026-05-18 16:44:02 +09:00