feat(landing): new landing page, /learn directory, and SEO/analytics repairs - #56
Conversation
Syncs src/components/ui/ to claude.ai/design as the "Flemoji Design System"
project: 17 visual primitives, each with an authored, render-verified preview.
What's here:
- assets/ds-entry.ts scoped bundle entry (primitives only, no next/navigation
or react-image-crop; also re-exports SelectItem, without
which FSelect is unusable)
- assets/ds.css + tailwind.ds.js + build-css.sh
compiles the DS stylesheet. Defines the three
--font-* custom properties next/font injects at runtime,
and safelists the documented brand palette, which Tailwind
would otherwise purge (bg-primary-700, bg-secondary-600,
shadow-glow et al were all missing).
- assets/fonts.css + woff2s
Inter / Poppins / JetBrains Mono harvested from the
next/font build, so designs render in brand type.
- previews/*.tsx 17 authored preview cards, all graded good
- conventions.md the header inlined into the design agent's prompt;
every component and class name in it was verified
against the built bundle
- NOTES.md re-sync instructions, gotchas, risks
Note for the team: docs/design-system.md is stale — it documents the
pre-efc251c purple-primary tokens. conventions.md reflects what actually
ships (primary blue, secondary purple) and the doc is deliberately not
uploaded so it can't mislead the design agent.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Implements the Claude Design handoff ("Landing page redesign: three
directions" → Flemoji Landing Page.dc.html) and restructures public routes
around it.
Routes:
/ marketing landing page (was the Learn hub)
/learn Learn directory — cluster hub
/learn?view=grid paginated article grid with cluster filters
/:slug individual guide (was /learn/:slug)
/topic/:slug topic hub (was /learn/topic/:slug)
/stream AI chat + streaming app (was /)
Old /learn/:slug and /learn/topic/:slug URLs are kept alive by rewrites in
next.config.mjs rather than redirects, so existing links keep working while
each page's canonical points at the new root URL — search engines consolidate
without anything 404ing. /articles/:slug now uses permanentRedirect (308) so
ranking signals actually transfer.
The landing page is built from real data: guides from article-service, tools
from the registry, and the five most-played public tracks via a new
MusicService.getFeaturedTracks(). Sections live in src/components/home/ with
shared values in tokens.ts. The equaliser is pure CSS (with a
prefers-reduced-motion guard) so the whole page stays a Server Component.
Two deliberate deviations from the mock: the stream play button links to
/stream instead of toggling a decorative playing state, and every section has
dark-mode variants since the header exposes a live theme toggle.
Also replaces public/main_logo.png with the transparent-background version.
The old file was opaque RGB with a baked-in white background, which rendered
as a solid white block on every dark surface — including the purple gradient
heroes. Because it is now transparent the dark wordmark is invisible on dark
backgrounds unless inverted, so every usage that lacked dark handling gained
`dark:brightness-0 dark:invert`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…uilding Findings from a Search Console / analytics audit, all verified against the running app. SITE_URL was not whitespace-safe. NEXT_PUBLIC_SITE_URL is set in Vercel with a trailing newline (the usual `echo … | vercel env add`), and resolveSiteUrl only stripped a trailing slash, so production shipped: sitemap.xml <loc>https://flemoji.com\n/learn</loc> robots.txt Sitemap: https://flemoji.com\n/sitemap.xml Every sitemap URL was malformed and robots.txt sitemap auto-discovery was dead. Metadata canonicals hid it because Next normalises those through new URL(); the raw interpolations did not. normalizeBaseUrl() now trims, covering both env sources, with regression tests. Sitemap submitted 8 unindexable URLs: six /genres/* entries whose route was never built (all 404), and /timeline + /league, which set robots noindex. Removed both groups, added /topic/:slug (clusters with published articles only) plus /privacy and /terms. Guides now live at the root, so an article slugged `tools` or `learn` is shadowed by that static route — unreachable, yet still submitted, and emitted twice. Next always prefers a static segment, so this is blocked at write time via RESERVED_ROOT_SLUGS in createArticle/updateArticle, with the sitemap filtering defensively for rows written before the guard. Structured data claimed two URLs that 404: Organization.logo pointed at /logo.png (the asset is main_logo.png) and WebSite.potentialAction declared a sitelinks searchbox at /search, which does not exist. Fixed the first, removed the second. GA4 fired on localhost and on every preview deploy into the production property. It is now gated on NEXT_PUBLIC_VERCEL_ENV === 'production' and the measurement id is overridable. The property also only ever received automatic pageviews, so sign_up, login and track_play events are now emitted through a typed helper that no-ops when the tag is absent. Artist profiles are Client Components and could not export metadata, so every one inherited the site title with no description or canonical while being submitted via sitemap. Added a segment layout with generateMetadata that uses its own read-only query — ArtistService.getArtistBySlug increments profileViews as a side effect and would have double-counted every crawl. Also: /ai-test and /unauthorized were fully indexable and are now noindex (deliberately not robots.txt Disallow, which would stop Google reading the noindex); added canonicals to /privacy and /terms; added a drift guard between the tool registry and ToolRenderer's import map, since registering a tool without wiring the renderer publishes a 200 page with an empty body; and documented the SEO/analytics env vars, which .env.example never mentioned. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The Claude Design sync inputs are generated bundles — compiled CSS, subset woff2 fonts, preview HTML — not hand-authored source. `prettier --check .` flagged three CSS files and failed the "Type-check, lint, format" CI job, blocking the branch. Same treatment `.claude/` and `.cursor/` already get. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Summary
Three things, in three commits:
chore(design-sync)— Claude Design sync inputs (pre-existing on this branch, not mine).feat(landing)— the landing-page revamp and public route restructure.fix(seo)— Search Console / analytics audit repairs.Happy to split 2 and 3 into their own PRs if that reviews better.
Route changes
//learn/learn?view=grid/:slug/learn/:slug)/topic/:slug/learn/topic/:slug)/stream/)Old
/learn/*URLs are kept alive by rewrites, not redirects, with canonicals pointing at the new root URLs — nothing 404s and search engines consolidate./articles/:slugupgraded 307 → 308.Production bug this fixes
NEXT_PUBLIC_SITE_URLin Vercel has a trailing newline, andresolveSiteUrlonly stripped a trailing slash. Live production is currently serving:Every sitemap URL is malformed and robots.txt sitemap auto-discovery is dead.
normalizeBaseUrl()now trims, so merging this fixes it without touching Vercel — though the env var is still worth cleaning up.Other SEO/analytics fixes
/genres/*404s;/timeline+/leaguearenoindex). Removed; added/topic/:slug,/privacy,/terms.toolswould be shadowed by the static route, unreachable but still submitted.Organization.logopointed at a 404;WebSite.potentialActiondeclared a/searchpage that doesn't exist.sign_up,login,track_play./ai-testand/unauthorizedwere fully indexable — nownoindex.Verification
tsc0 errors · lint 0 errors · jest 337/337 across 28 suites (11 new tests: reserved slugs, SITE_URL whitespace, tool registry drift).Verified against the running app at 1440px and 390px, light and dark.
Known gaps
/:slugand/artist/:slugwere exercised via 404/metadata paths, not with real content.🤖 Generated with Claude Code