Skip to content

Brand Mark (Lantern Flame) Audit โ€‹

Last updated: 2026-06-22

This doc tracks the Lantern flame across the codebase. As of this change there are zero lucide-react Flame icons left: every flame is the custom Lantern silhouette, and a lint rule blocks the lucide Flame from coming back.

The decision โ€‹

We replaced the stock lucide-react Flame icon (a generic open, stroked flame thousands of apps use) with a custom solid-silhouette flame everywhere the flame appears: brand logos, app icons, splash, the beacon, the nav hub, hero badges, AND the small inline glyphs (offer badges, map markers, count pills, step icons, the venue-category lantern icon).

  • Shape only. The sacred brand amber #f59e0b is unchanged. We swapped the silhouette, not the color. Small glyphs still take their color from their context (a Tailwind text-* class).
  • One flame everywhere. Earlier we kept lucide for small glyphs; that was reversed in favor of a single consistent mark at every size, enforced by lint.

What to use (single source of truth) โ€‹

The flame geometry lives in one place. Never hand-draw the flame or import the lucide Flame.

NeedUseNotes
The amber brand logo (auth, loading, headers, app-icon tiles)<LanternLogo size glow /> (@lantern/ui/LanternLogo)Amber fill + optional glow, role="img".
An inline flame glyph in UI (badges, markers, buttons, list icons, icon={...} props)<FlameMark size className /> (@lantern/ui/FlameMark)Color comes from currentColor (set a text-* class). Drop-in for the old <Flame>; works as icon={FlameMark}. Accepts a fill override.
A custom treatment (gradient, specific color, nested in another SVG)LANTERN_FLAME_PATH + LANTERN_FLAME_VIEWBOX (@lantern/ui/lanternFlame)The raw path + viewBox. Used by LanternLogo, FlameMark, the beacon, the hub, email/SVG assets.
A static asset (favicon, splash, HTML email)inline copy of the pathCannot import; each carries the path with a comment pointing to lanternFlame.js. Keep in sync.

Enforcement (the proactive guardrail) โ€‹

.eslintrc.json bans the lucide Flame via no-restricted-imports:

import { Flame } from 'lucide-react'   // ESLint error

The error message points to LanternLogo / FlameMark / lanternFlame. This is what keeps future integrations from quietly reintroducing the stock flame; it runs as part of npm run lint (and therefore npm run validate / pre-push). Adding a new flame to the UI means reaching for FlameMark or LanternLogo.

Where the mark appears โ€‹

Grouped for orientation; all of these now render the silhouette.

GroupLocations
Brand logo componentpackages/ui/LanternLogo.jsx (auth, loading, headers, app-icon tiles app-wide)
Inline glyph componentpackages/ui/FlameMark.jsx (the drop-in used by the swaps below)
Canonical geometrypackages/ui/lanternFlame.js (LANTERN_FLAME_PATH, LANTERN_FLAME_VIEWBOX)
Favicons / PWA / splashapps/web/public/icons/*, apps/admin/public/icons/*, docs/public/icons/*, apps/site/public/lantern-flame.svg, apps/web/index.html (splash)
App chromeHomeView header, DashboardNavigation hub (resting/armed/lit), LanternBeacon, AccessGate (loading/sign-in/maintenance via LanternLogo; denied dimmed gray), LightLanternModal, LandingPage masthead + steps, InfoSupport hero + steps
Inline glyphs (FlameMark)venue map markers (VenuesMap), lantern-count badges (VenuePicker, HomeView, VenueView, offer cards), "Meet"/wave (Chat, WaveManager), light/schedule forms, profile name labels, frens tab/banners, admin metric + tab icons (SystemHealth, Billing, BillingReports, VenueActivityDashboard, merchant Overview), RecentActivityView event icon
Offer-card flamespackages/ui/offers/FlamePulse.jsx, LivingFlame.jsx, BurningHotCard.jsx, StorefrontShell.jsx, ClassicHeroCard.jsx, OfferCards.jsx
Icon vocabulary (SSOT)packages/ui/icons.js (lantern mood category, unknown-category fallback). The GCP provider uses CloudCog, not the flame.
Composite illustrationapps/admin/src/admin/chat/LanternChat.jsx (flame fitted inside the old-lantern frame)
Emailservices/api/auth/src/lib/email.js, services/functions/firebase/lib/email.js, email-preview.html
Marketing siteapps/site/index.html, apps/site/src/shared/chrome.js
Storybook specimensCallToAction.stories.jsx, StickyBottomCTA.stories.jsx, Primitives.stories.jsx, FlameMark.stories.jsx, Brand.stories.jsx

Known follow-ups / oddities โ€‹

  • LivingFlame / LanternChat: the animated "dying" flame and the flame-in-a-lantern illustration were tuned around the old 24-unit viewBox; the silhouette is fitted via its own viewBox, so ember/shimmer offsets may want a small visual touch-up if they look off.

How to audit again โ€‹

Run from the repo root. Match <Flame without a trailing-character class (to catch multi-line tags), and filter out the <FlamePulse> component:

bash
# Any lucide flame left as a component or icon value (should be empty):
grep -rn "<Flame" --include="*.jsx" . | grep -v node_modules | grep -v "FlamePulse"
grep -rnE "from ['\"]lucide-react['\"]" --include="*.jsx" --include="*.js" . | grep -v node_modules | grep "\bFlame\b"

# Inline path literal (old lucide flame), should be empty:
grep -rn "M8.5 14.5" --include="*.jsx" --include="*.js" --include="*.svg" --include="*.html" . | grep -v node_modules

# Files carrying the silhouette path:
grep -rn "233.2,58.8" --include="*.svg" --include="*.html" --include="*.jsx" --include="*.js" . | grep -v node_modules

Built with VitePress