feat(landing): redesign default template + brand palette engine (Phase 1)#201
Merged
Conversation
…e 1) The link landing page was hardcoded dark with a single swapped accent, so every tenant got the same "dev-tool dark" canvas; the one piece of real visual content (social_preview.image_url) was never rendered, and expires_at was never surfaced. Phase 1 of brandable landing pages (no persistence yet): - services/landing: LandingTheme brand config with a Default impl (Rift defaults) — the renderer's sole branding input. Knobs are enums/constrained strings (template, color_scheme, font, corner_style, …) so a page can't render trash. Derives both REST (ToSchema) and MCP (JsonSchema) per CLAUDE.md. - api/links/palette: derivation engine turning one theme_color into a full, contrast-correct palette. Clamps saturation/lightness into a tasteful band, picks on-accent text by WCAG luminance, falls back to the default accent on garbage input. Dark/Light/Auto (Auto emits a prefers-color-scheme override). - landing.rs: Default template redesign — palette expressed as CSS custom properties, preview image rendered as a hero, expiry surfaced, bigger icon/type, button depth; agent panel restyled to the shared tokens and gated on show_agent_panel. Platform-detection JS and JSON-LD unchanged. - routes.rs: stop consuming App branding (unused); render from LandingTheme::default(). Branding returns in Phase 2 via tenant config. Tests: palette unit tests (clamping, contrast, fallback, scheme selection); resolve integration assertions for the hero image, expiry, and CSS variables. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The full cargo test run is slow; pushing the branch/opening the PR first lets remote CI run the suite in parallel with the local run instead of serializing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Adds a manual trigger so any branch can be deployed to sandbox from the Actions UI or `gh workflow run server-ci.yml --ref <branch>`. deploy-sandbox now also runs for workflow_dispatch events; deploy-prod stays gated to pushes on main, so a manual dispatch never touches prod. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
The link landing page was hardcoded dark (
#0a0a0a) with a single swapped accent, so every tenant got the same "dev-tool dark" canvas. The one piece of real visual content —social_preview.image_url— was never rendered (only emitted as an OG meta tag), andexpires_atwas never surfaced.This is Phase 1 of brandable landing pages. End-state: a small library of first-party templates customers select (never author), fed by a
LandingThemeconfig that cascadesLink override → LandingTheme → Rift default. Phase 1 builds the foundation and the visual win, with no persistence yet.Changes
services/landing—LandingThemebrand config + aDefaultimpl (Rift defaults), the renderer's sole branding input. Every knob is an enum or constrained string (template,color_scheme,font,corner_style, …) so a page can't render trash. Derives bothToSchema(REST) andJsonSchema(MCP) per CLAUDE.md.api/links/palette— derivation engine turning onetheme_colorinto a full, contrast-correct palette. Clamps saturation/lightness into a tasteful band, picks on-accent text color by WCAG luminance, falls back to the default accent on garbage input.Dark/Light/Auto(Auto emits aprefers-color-schemeoverride).landing.rs—Defaulttemplate redesign: palette expressed as CSS custom properties, preview image rendered as a hero, expiry surfaced, bigger icon/type, button depth; agent panel restyled to the shared tokens and gated onshow_agent_panel. Platform-detection JS and JSON-LD unchanged.routes.rs— stop consuming App branding (unused); render fromLandingTheme::default(). Branding returns in Phase 2 via tenant config.Tests
:root/--accentCSS variables present.Decisions / follow-ups
App.{app_name, icon_url, theme_color}) are now orphaned — candidate for a cleanup issue.LandingThemeonTenantDoc+ settings route + cascade + per-link content overrides; additional templates.🤖 Generated with Claude Code