Skip to content

feat(web): add domain-based branding system#3514

Open
devin-ai-integration[bot] wants to merge 3 commits intomainfrom
devin/1769913717-domain-feature-flags
Open

feat(web): add domain-based branding system#3514
devin-ai-integration[bot] wants to merge 3 commits intomainfrom
devin/1769913717-domain-feature-flags

Conversation

@devin-ai-integration
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot commented Feb 1, 2026

Summary

Adds a domain-based branding system to apps/web that enables dynamic branding based on the current hostname. This supports the upcoming rebrand from hyprnote.com to char.com by allowing different logos and product names per domain.

Changes:

  • branding.ts: Core module with Brand type, BrandingConfig interface, and domain detection logic
  • BrandingProvider.tsx: React Context provider with single useBranding() hook returning stable primitive values
  • router.tsx: Wraps app with BrandingProvider
  • header.tsx: Updates Logo component to use branding hook instead of hardcoded values

The architecture is designed to be extended with PostHog flags later for A/B testing pricing changes.

Updates since last revision

  • Renamed feature-flags.ts to branding.ts
  • Simplified API to single useBranding() hook (removed useBrand(), useIsCharBrand())
  • Hook returns flat object with stable primitive values (brand, logo, productName, etc.) similar to TanStack Query pattern
  • SSR hydration fix: getCurrentHostname() now extracts hostname from VITE_APP_URL during SSR to avoid hydration mismatch

Review & Testing Checklist for Human

  • VITE_APP_URL configuration: The SSR fix relies on VITE_APP_URL matching the actual deployment domain. If deploying to char.com, ensure VITE_APP_URL=https://char.com is set in that environment. Mismatched config will cause hydration issues.
  • Char assets: The config references /api/images/char/logo.svg and /api/images/char/og-image.jpg - ensure these assets exist or will be added before deploying to char.com
  • Domain detection: Test that detectBrand() correctly identifies char.com vs hyprnote.com vs localhost
  • Single-deployment limitation: This approach assumes one domain per deployment. If the same deployment needs to serve both domains simultaneously, a different approach (server request headers) would be needed.

Recommended test plan:

  1. Run locally and verify hyprnote branding appears
  2. Modify detectBrand() temporarily to return "char" and verify char branding appears
  3. Check browser console for any React hydration warnings

Notes

Meta tags in __root.tsx (title, description, og:image) still use hardcoded "Hyprnote" values. These could be updated in a follow-up PR.

Link to Devin run: https://app.devin.ai/sessions/7a4241ebceed4b21b614c8999f3ca49a
Requested by: yujonglee (@yujonglee)

- Add feature-flags.ts with Brand type and BrandingConfig
- Add BrandingProvider context for domain detection
- Update router.tsx to wrap app with BrandingProvider
- Update header.tsx Logo component to use useBranding hook

This enables dynamic branding based on the current domain
(hyprnote.com vs char.com) for the upcoming rebrand.

Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
@devin-ai-integration
Copy link
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@netlify
Copy link

netlify bot commented Feb 1, 2026

Deploy Preview for hyprnote ready!

Name Link
🔨 Latest commit c0f2b96
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote/deploys/697ec53d2dcd1300089ee6b7
😎 Deploy Preview https://deploy-preview-3514--hyprnote.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link

netlify bot commented Feb 1, 2026

Deploy Preview for hyprnote-storybook canceled.

Name Link
🔨 Latest commit c0f2b96
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote-storybook/deploys/697ec53dda748400080dcef4

Copy link
Contributor Author

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

View issue and 5 additional flags in Devin Review.

Open in Devin Review

devin-ai-integration bot and others added 2 commits February 1, 2026 03:08
- Rename feature-flags.ts to branding.ts
- Consolidate to single useBranding hook with flat return object
- Return stable primitive values (brand, logo, productName, etc.)
- Similar to TanStack Query's render optimization pattern

Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
…mismatch

During SSR, window is undefined so getCurrentHostname() now extracts
the hostname from VITE_APP_URL environment variable. This ensures
consistent branding between server and client rendering.

Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
@devin-ai-integration devin-ai-integration bot changed the title feat(web): add domain-based feature flags for branding feat(web): add domain-based branding system Feb 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant