Skip to content
This repository was archived by the owner on Apr 21, 2026. It is now read-only.

feat: Add brand identity import to theme system#146

Closed
LucasSantana-Dev wants to merge 5 commits intomainfrom
feat/brand-identity-import
Closed

feat: Add brand identity import to theme system#146
LucasSantana-Dev wants to merge 5 commits intomainfrom
feat/brand-identity-import

Conversation

@LucasSantana-Dev
Copy link
Copy Markdown
Member

@LucasSantana-Dev LucasSantana-Dev commented Feb 28, 2026

Summary

  • Brand identity import: Connect branding-mcp output to the siza webapp generation pipeline
  • Smart detection: Auto-detect BrandIdentity JSON by checking for colors.primary.hex, falls back to standard theme format
  • Full mapping: Brand colors, typography, spacing, and border radius mapped to SizaTheme values
  • BrandMeta storage: Extra metadata (font names, semantic colors, neutrals) stored for richer AI prompt context
  • UI integration: Brand themes show a "brand" badge in ThemeSelector, font info in DesignContext panel
  • API extension: Pass brandHeadingFont, brandBodyFont, brandSemanticColors to generation API

Test plan

  • 13 new unit tests for parseBrandIdentity() and importBrand() (33 total in theme-store)
  • Verify lint, type check, build pass in CI
  • Verify full test suite passes (487+ tests)

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes - Version 0.15.0

  • New Features
    • Brand identity management: Import and create themes with custom typography (heading and body fonts) and semantic color palettes
    • Unified import flow: Support for both traditional theme JSON and brand identity JSON formats
    • Brand metadata display: Themes now showcase brand information including fonts and colors in the theme selector
    • Design context enhancement: Generated designs incorporate brand typography and color specifications

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 28, 2026

Warning

Rate limit exceeded

@LucasSantana-Dev has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 20 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 66014de and 2024019.

📒 Files selected for processing (4)
  • apps/web/src/__tests__/stores/theme-store.test.ts
  • apps/web/src/components/generator/DesignContext.tsx
  • apps/web/src/components/generator/ThemeSelector.tsx
  • apps/web/src/stores/theme-store.ts

Walkthrough

This PR introduces brand identity import functionality and metadata support throughout the application. It adds a new parseBrandIdentity function to convert brand JSON into theme objects, extends the generate API to accept brand-related fields, and updates UI components to display and handle brand metadata alongside themes. Version bumped to 0.15.0.

Changes

Cohort / File(s) Summary
Version Updates
package.json, apps/web/package.json
Bumped version from 0.14.0 to 0.15.0 across manifest files.
Theme Store Extension
apps/web/src/stores/theme-store.ts
Added new BrandMeta interface with brandName, typography, semantic colors, and neutrals. Extended SizaTheme with optional brandMeta field. Introduced parseBrandIdentity function to convert brand JSON into theme-compatible objects. Added importBrand method to create themes from brand data. Enhanced duplicateTheme to preserve brand metadata.
Theme Store Tests
apps/web/src/__tests__/stores/theme-store.test.ts
Added comprehensive tests for parseBrandIdentity covering JSON validation, field population, typography/spacing/borderRadius mappings, and fallback defaults. Extended tests for importBrand behavior including success and error handling.
Generate API Route
apps/web/src/app/api/generate/route.ts
Added three optional schema fields: brandHeadingFont, brandBodyFont, and brandSemanticColors (with hex color regex validation). Extended POST handler to extract and propagate these fields through design context construction and SSE events.
Generation Options Interface
apps/web/src/lib/api/generation.ts
Extended GenerationOptions interface with optional brand customization properties: brandHeadingFont, brandBodyFont, and brandSemanticColors object structure.
UI Components
apps/web/src/components/generator/DesignContext.tsx, apps/web/src/components/generator/GeneratorForm.tsx, apps/web/src/components/generator/ThemeSelector.tsx
Added BrandInfo component to display brand metadata when available. Enhanced GeneratorForm to inject brand metadata into design context conditionally. Extended ThemeSelector with importBrand functionality, brand-aware UI labels ("Import Theme / Brand"), visual brand indicators in theme list, and prioritized brand import path in JSON import flow.

Sequence Diagram

sequenceDiagram
    participant User
    participant ThemeSelector
    participant ThemeStore
    participant DesignContext
    participant API as Generate API

    User->>ThemeSelector: Paste brand JSON
    ThemeSelector->>ThemeStore: importBrand(json)
    ThemeStore->>ThemeStore: parseBrandIdentity(json)
    ThemeStore->>ThemeStore: createTheme(brandTheme)
    ThemeStore-->>ThemeSelector: Return theme ID
    ThemeSelector->>ThemeSelector: Set as active theme
    DesignContext->>ThemeStore: useThemeStore(projectId)
    ThemeStore-->>DesignContext: Return activeTheme.brandMeta
    DesignContext->>DesignContext: Render BrandInfo
    User->>API: Generate with design context
    API->>API: Include brandHeadingFont, brandBodyFont, brandSemanticColors
    API-->>User: Design generated with brand styling
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature: adding brand identity import capability to the theme system, which is the central change across multiple files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/brand-identity-import

Comment @coderabbitai help to get the list of available commands and usage tips.

Connect branding-mcp output to the siza webapp generation pipeline.
Users can now paste BrandIdentity JSON into the existing Import Theme
flow — auto-detected by checking for colors.primary.hex. Maps brand
colors, typography, spacing, and border radius to SizaTheme values,
stores extra BrandMeta (font names, semantic colors, neutrals) for
richer AI prompt context. Brand themes show a "brand" badge in the
selector and display font info in the design panel.

- Add BrandMeta interface and brandMeta field to SizaTheme
- Add parseBrandIdentity() with font/spacing/radius mapping
- Add importBrand() store action
- Smart import: try brand first, fall back to theme format
- Pass brandHeadingFont, brandBodyFont, brandSemanticColors to API
- Extend Zod schema and design context block in route.ts
- 13 new tests for parseBrandIdentity and importBrand (33 total)
@LucasSantana-Dev LucasSantana-Dev force-pushed the feat/brand-identity-import branch from de473f0 to 4b0d686 Compare February 28, 2026 05:07
Add brand identity CHANGELOG entry and bump version to 0.15.0.
else if (spacingUnit >= 12) spacing = 'spacious';

const radiusMd = data.borders?.radii?.md ?? 8;
let borderRadius: SizaTheme['borderRadius'] = 'medium';

Check warning

Code scanning / CodeQL

Useless assignment to local variable Warning

The initial value of borderRadius is unused, since it is always overwritten.
Comment thread apps/web/src/components/generator/ThemeSelector.tsx Fixed
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
apps/web/src/components/generator/DesignContext.tsx (1)

82-91: Consider memoizing the selector to avoid potential re-renders.

The current pattern useThemeStore((s) => s.getActiveTheme)(projectId) invokes the action on every render. While functionally correct, this creates a new function reference each time. Consider using useMemo or restructuring if performance becomes a concern.

♻️ Alternative pattern using useMemo
 function BrandInfo({ projectId }: { projectId: string }) {
-  const activeTheme = useThemeStore((s) => s.getActiveTheme)(projectId);
+  const getActiveTheme = useThemeStore((s) => s.getActiveTheme);
+  const activeTheme = useMemo(() => getActiveTheme(projectId), [getActiveTheme, projectId]);
   if (!activeTheme?.brandMeta) return null;

Note: This requires importing useMemo from React.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/components/generator/DesignContext.tsx` around lines 82 - 91,
The BrandInfo component creates a new selector function each render by calling
useThemeStore((s) => s.getActiveTheme)(projectId); change this to memoize the
selector so the selector reference is stable: import useMemo from React and
create const selectActiveTheme = useMemo(() => (s) =>
s.getActiveTheme(projectId), [projectId]); then call const activeTheme =
useThemeStore(selectActiveTheme); this keeps BrandInfo, useThemeStore and
getActiveTheme usage but prevents a new function reference on every render.
apps/web/src/components/generator/ThemeSelector.tsx (1)

137-154: Extract shared post-import success handling to avoid duplication.

Both brand and theme import branches repeat the same success steps. Pull that into a helper to reduce drift risk.

♻️ Suggested refactor
+  const applyImportedTheme = (themeId: string) => {
+    setImporting(false);
+    setImportJson('');
+    setActiveTheme(projectId, themeId);
+    const newTheme = getThemes().find((t) => t.id === themeId);
+    if (newTheme) onSelectTheme(themeToValues(newTheme));
+    setOpen(false);
+  };
+
   const handleImportSubmit = () => {
     setImportError('');
     const brandResult = importBrand(importJson);
     if (brandResult) {
-      setImporting(false);
-      setImportJson('');
-      setActiveTheme(projectId, brandResult);
-      const newTheme = getThemes().find((t) => t.id === brandResult);
-      if (newTheme) onSelectTheme(themeToValues(newTheme));
-      setOpen(false);
+      applyImportedTheme(brandResult);
       return;
     }
     const id = importTheme(importJson);
     if (id) {
-      setImporting(false);
-      setImportJson('');
-      setActiveTheme(projectId, id);
-      const newTheme = getThemes().find((t) => t.id === id);
-      if (newTheme) onSelectTheme(themeToValues(newTheme));
-      setOpen(false);
+      applyImportedTheme(id);
     } else {
       setImportError('Invalid theme or brand identity JSON');
     }
   };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/components/generator/ThemeSelector.tsx` around lines 137 - 154,
Both import branches repeat the same post-success steps; extract them into a
helper (e.g., handleImportSuccess) that accepts the theme/brand id and performs
setImporting(false), setImportJson(''), setActiveTheme(projectId, id), finds the
theme via getThemes().find(t => t.id === id) and calls
onSelectTheme(themeToValues(theme)) if found, then setOpen(false); replace the
duplicated blocks after importBrand(importJson) and importTheme(importJson) to
call this helper with the returned id.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/web/src/components/generator/DesignContext.tsx`:
- Around line 82-91: The BrandInfo component creates a new selector function
each render by calling useThemeStore((s) => s.getActiveTheme)(projectId); change
this to memoize the selector so the selector reference is stable: import useMemo
from React and create const selectActiveTheme = useMemo(() => (s) =>
s.getActiveTheme(projectId), [projectId]); then call const activeTheme =
useThemeStore(selectActiveTheme); this keeps BrandInfo, useThemeStore and
getActiveTheme usage but prevents a new function reference on every render.

In `@apps/web/src/components/generator/ThemeSelector.tsx`:
- Around line 137-154: Both import branches repeat the same post-success steps;
extract them into a helper (e.g., handleImportSuccess) that accepts the
theme/brand id and performs setImporting(false), setImportJson(''),
setActiveTheme(projectId, id), finds the theme via getThemes().find(t => t.id
=== id) and calls onSelectTheme(themeToValues(theme)) if found, then
setOpen(false); replace the duplicated blocks after importBrand(importJson) and
importTheme(importJson) to call this helper with the returned id.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e8b3b0b and 66014de.

⛔ Files ignored due to path filters (1)
  • CHANGELOG.md is excluded by !**/*.md
📒 Files selected for processing (9)
  • apps/web/package.json
  • apps/web/src/__tests__/stores/theme-store.test.ts
  • apps/web/src/app/api/generate/route.ts
  • apps/web/src/components/generator/DesignContext.tsx
  • apps/web/src/components/generator/GeneratorForm.tsx
  • apps/web/src/components/generator/ThemeSelector.tsx
  • apps/web/src/lib/api/generation.ts
  • apps/web/src/stores/theme-store.ts
  • package.json

@LucasSantana-Dev
Copy link
Copy Markdown
Member Author

Closing: the generate route brand fields were merged via #148 (v0.15.0). The theme store brand import and UI features need a fresh branch based on current main — the service layer refactoring makes this PR unrebaseable.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants