Files
financial/app/site/next.config.js
zeekay 2196d6ee71 refactor(site): every brand-bearing string flows through @luxbank/brand; add LUX_BRAND_OVERRIDE/INLINE env passthrough + tenant examples
- @luxbank/brand: add productName, urls, contactEmails, copyright surfaces
  to BrandConfig; resolve tenant overrides from LUX_BRAND_INLINE (JSON
  string, optionally base64) and LUX_BRAND_OVERRIDE (path to JSON file);
  domain-driven URL/email derivation when only `domains.primary` is set.
- next.config.js: resolve LUX_BRAND_OVERRIDE at Node config time and
  pass through as LUX_BRAND_INLINE so the same JSON is visible to both
  server and client bundles (no fs in the browser).
- layout.tsx: metadata reads from LUX_BRAND.name + urls.site.
- Footer/Menu/NavDropdown/CommandPalette/ChatWidget/UserSteps: all
  brand-bearing URLs, emails, copyright, attribution, and product-name
  strings sourced from LUX_BRAND.
- ~40 product/technology/solutions/contact/press/security pages: hardcoded
  docs.lux.financial / app.lux.financial / status.lux.financial /
  cal.com/luxfi / mailto:*@lux.financial swapped for LUX_BRAND.urls.* and
  LUX_BRAND.contactEmails.*.
- examples/tenant-bank.example.json + tenant-psp.example.json: working
  fictitious tenant overrides demonstrating the full surface (name,
  legalName, productName, domains, urls, contactEmails, copyright, colors,
  social). Build the same code as a fully-rebranded site with
  LUX_BRAND_OVERRIDE=./examples/tenant-<x>.example.json pnpm build.
- pkg/brand 1.0.2 -> 1.0.3; root 0.1.2 -> 0.1.3.
2026-05-24 14:53:04 -07:00

80 lines
2.4 KiB
JavaScript

// White-label brand override resolution.
//
// We resolve the tenant override here (Node-only, build time), inline it
// as LUX_BRAND_INLINE (a JSON string), and then `@luxbank/brand` reads
// the same string from process.env in both server and client bundles.
// That way the client bundle does not need fs access.
const fs = require('fs');
const path = require('path');
function resolveBrandInline() {
if (process.env.LUX_BRAND_INLINE && process.env.LUX_BRAND_INLINE.length > 0) {
return process.env.LUX_BRAND_INLINE;
}
const overridePath = process.env.LUX_BRAND_OVERRIDE;
if (overridePath && overridePath.length > 0) {
const resolved = path.isAbsolute(overridePath)
? overridePath
: path.resolve(process.cwd(), overridePath);
const body = fs.readFileSync(resolved, 'utf8');
// Round-trip through JSON to strip comments and validate.
return JSON.stringify(JSON.parse(body));
}
return '';
}
const BRAND_INLINE = resolveBrandInline();
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: false,
eslint: {
ignoreDuringBuilds: true,
},
compiler: {
styledComponents: true,
},
// White-label brand override surface — picked up by @luxbank/brand at
// build time. PSPs, banks, and wallets rebuild this same site with
// their own brand by setting LUX_BRAND_OVERRIDE=./tenant.json or
// LUX_BRAND_INLINE='{"name":"Acme Pay",...}'.
// Both server and client bundles read LUX_BRAND_INLINE; LUX_BRAND_OVERRIDE
// is resolved into LUX_BRAND_INLINE above at build time.
env: {
LUX_BRAND_INLINE: BRAND_INLINE,
},
transpilePackages: ['@luxfi/logo', '@luxbank/brand', 'geist'],
images: {
unoptimized: true,
remotePatterns: [
{
protocol: "https",
hostname: "static.ghost.org",
port: "",
},
{
protocol: "http",
hostname: "localhost",
port: "",
},
{
protocol: "https",
hostname: "news.dev.lux.financial",
port: "",
},
{
protocol: "https",
hostname: "www.dev.lux.financial",
port: "",
},
],
},
// Use 'export' for static deployment (Cloudflare Pages, GitHub Pages)
// Set to 'standalone' for Node.js server deployment
output: process.env.STATIC_EXPORT ? "export" : "standalone",
// basePath removed - site deploys to root of custom domain (lux.financial)
compress: true,
};
module.exports = nextConfig;