Skip to content

Velocity Architecture

brand.json — The Single Source of Truth Schema Velocity X Ships With

One JSON File. Every Page. Every Tool. No Duplication.

📋 🔗

Your business info is scattered. Name in the footer, ABN in a comment, address in the contact form, social links in the header, phone in an env var, pricing in markdown. When you rebrand or move offices, you hunt 12 files. When Claude asks "what's your ABN?", you paste it instead of pointing to canonical source. When a junior dev asks "where's the company phone number?", nobody's sure. The fix: encode your entire business spec in brand.json and never duplicate again.

Velocity X treats brand.json as the single source of truth. Business name, ABN, contact details, social handles, colour tokens, voice rules, pricing tiers, SEO defaults, navigation, CTAs — all live in one JSON file. Pages read from it at build time. AI tools read it during conversation. Add a new social link once and it propagates everywhere. Port the template to a new business in 15 minutes. No code changes. No "did I update that too?" anxiety.

Why Scattered Config Kills Velocity

When business data lives across env vars, YAML, inline component values, and hardcoded strings, every update becomes a hunt. Rebrand your company and you're grep-ing for stale references for days. Hire a junior dev and they don't know which file holds the phone number. Update your ABN and hope you didn't miss a copy somewhere. The friction multiplies with every new site you scaffold from the template.

Env vars are worse. They're invisible. Nobody reads them because they're buried in .env files and deployment dashboards. New team members don't know what values to set. You can't see them in git history. When something breaks, you're hunting environment config instead of code. Env vars are for secrets (API keys, database passwords). They're not for business metadata.

brand.json inverts this. Build once, port anywhere. Edit brand.json, rebuild, and every page reads the new values automatically. No manual sync. No env-var guessing. No "did I miss one?" anxiety. One file, version-controlled, human-readable, machine-parseable. Every developer sees the same values. Every AI tool reads them first.

The Full Schema

Here's the annotated brand.json schema that ships with Velocity X:

{`{
  "business": {
    "name": "Rebuild Relief",              // Display name (page titles, meta)
    "shortName": "Relief",                 // Short form (logo alt text, breadcrumbs)
    "tagline": "Hail damage claims, simplified.",  // Homepage hook
    "description": "Insurance claims management...",  // Long description for schema.org
    "type": "ProfessionalService",         // schema.org type
    "abn": "12 345 678 901",               // Australian Business Number
    "url": "https://rebuildrelief.com.au", // Canonical domain
    "ogImage": "/opengraph.png",           // Social share image (1200×630px)
    "logos": {
      "primary": "/logo-purple.svg",       // Default logo
      "white": "/logo-white.svg",          // On dark backgrounds
      "black": "/logo-black.svg",          // On light backgrounds
      "favicon": "/favicon.ico",           // Browser tab icon
      "appleTouchIcon": "/apple-touch-icon.png"
    },
    "address": {
      "locality": "Gold Coast",
      "region": "QLD",
      "country": "AU",
      "areaServed": "Queensland, Australia"
    },
    "contact": {
      "email": "hello@rebuildrelief.com.au",
      "phone": "+61 7 5555 0000",
      "bookingUrl": "/book",               // Typeform / Calendly
      "enquireUrl": "/enquire",            // Contact form
      "contactUrl": "/contact"             // Contact page
    },
    "social": {
      "instagram": "https://instagram.com/rebuildrelief",
      "facebook": "https://facebook.com/rebuildrelief",
      "linkedin": "https://linkedin.com/company/rebuild-relief"
    },
    "twitterHandle": "@rebuildrelief",
    "googleAnalyticsId": "G-ABC123XYZ",
    "web3formsKey": "your-api-key-here"
  },

  "seo": {
    "defaultTitleSuffix": " · Rebuild Relief",
    "defaultDescription": "Fast, fair hail damage claims...",
    "ogLocale": "en_AU",
    "ogSiteName": "Rebuild Relief"
  },

  "theme": {
    "primaryHue": "blue",                  // Tailwind hue name
    "darkModeDefault": false,
    "accentColor": "#1e40af"               // Hex override for gradients
  },

  "navigation": {
    "primary": [
      { "label": "How It Works", "href": "/how-it-works" },
      { "label": "Pricing", "href": "/pricing" },
      { "label": "Blog", "href": "/blog" }
    ],
    "cta": { "label": "Get Started", "href": "/enquire" }
  },

  "cta": {
    "default": {
      "headline": "Ready to move fast on your claim?",
      "subtext": "Let's get your site online.",
      "submitLabel": "Submit"
    }
  },

  "pricing": {
    "currency": "AUD",
    "currencySymbol": "$",
    "tiers": [
      {
        "name": "Standard",
        "price": "$45/month",
        "description": "For solo assessors",
        "features": ["5 claims/month", "Mobile app", "Email support"],
        "highlighted": false
      },
      {
        "name": "Pro",
        "price": "$120/month",
        "description": "Most popular",
        "features": ["Unlimited claims", "Dashboard analytics", "Priority support"],
        "highlighted": true
      }
    ]
  },

  "voice": {
    "default": "Direct, warm, uncluttered. No corporate hedging.",
    "tone": "Confident without arrogance. Helpful without condescension.",
    "shiftConditions": [
      {
        "context": "Talking to homeowners (emotional moment)",
        "tone": "Warm, reassuring, less jargon. Emphasise speed and simplicity."
      },
      {
        "context": "Talking to insurance assessors (internal audience)",
        "tone": "Formal, technical, numbers-first. More jargon is OK."
      }
    ],
    "avoid": ["leverage", "synergy", "solutions provider", "premier", "best-in-class", "unlock potential"],
    "lean": ["we'll handle it", "takes one day", "here's the real cost", "no hidden fees"]
  },

  "footer": {
    "copyrightLine": "© 2026 Rebuild Relief. All rights reserved.",
    "legal": [
      { "label": "Privacy", "href": "/privacy" },
      { "label": "Terms", "href": "/terms" }
    ]
  }
}`}

Four Patterns That Unlock brand.json

Pattern 1: Component Templating

Drop brand.json into any component and you have instant access to business data without prop-drilling. The header reads business.name and contact.email directly. The footer reads social links, copyright, and legal links. When you fork the template for a new client, zero component changes needed — just update brand.json and rebuild. The footer component doesn't know or care which business it's rendering; it reads the file and renders what's there. Same footer component works for Rebuild Relief, Aidxn Design, or any brand you port to.

Pattern 2: AI Context

Pin brand.json into your CLAUDE.md or drop it into a Claude conversation. When you ask "write a homepage headline", Claude reads the business tagline, voice rules, target audience, and ABN from one file. When you say "generate the footer copyright line", Claude knows the company name and founding year. No back-and-forth clarifications. One file, complete context. Same applies to Cursor, Aider, or any code tool. Your IDE becomes business-aware.

Pattern 3: Dynamic OpenGraph Tags

Every page's og:image, og:title, og:description is generated from brand.json at build time. Update the ogImage path once and every share card on Twitter, LinkedIn, and Discord uses the new image. Rename your business and all 50 pages get the new name in their social cards automatically. No stale metadata to hunt down. When someone shares a page, the rich preview comes straight from brand.json, not hardcoded in each template.

Pattern 4: SEO Metadata Pipeline

The default page titles and descriptions come from brand.json. Blog posts get defaultTitleSuffix appended automatically. Meta robots tags are set globally. Structured data (schema.org type, address, contact, ABN) is baked into the layout. Update brand.json and your entire site's SEO surface gets refreshed without touching a single Astro file. Search engines see consistent, up-to-date metadata across every page.

Migration Path: From Scattered Config to JSON

Step 1: Audit. Find every hardcoded string in your codebase: company name, phone, email, social links, colour values, ABN, address. Grep for them. List them all.

Step 2: Structure. Group them into the schema above. If you have voice rules, add a voice key. If you have multiple products or service categories, add a products array.

Step 3: Update components incrementally. Change one component at a time to read from brand.json instead of props or hardcoded values. Test each change locally. Don't try to refactor the whole site at once.

Step 4: Delete the old sources. Once every component reads from brand.json, remove env vars, inline constants, and hardcoded strings. Verify no stale references remain with grep.

Frequently Asked Questions

What if my business has multiple brands or product lines?

Create separate brand.json files (brand-product-a.json, brand-product-b.json) and pass the filename to loadBrand(). Or add a top-level "products" array to brand.json and have pages select which product's data to use. The schema scales to multi-product structures without friction.

Can I use brand.json with environment variables?

Yes. Use env vars for sensitive values (API keys, Stripe keys, database credentials) and brand.json for public data (company name, social links, tagline, ABN, address). They're complementary. Env vars stay hidden; brand.json stays visible.

Should brand.json be committed to git?

Absolutely. It's not a secret. It's brand infrastructure. Version-control it, review updates like any code change, and share it with team members and AI tools. The entire point is visibility and sync.

What if a field is blank? Do I delete it or use empty string?

Use empty string ("") for optional string fields, not null or undefined. The loaders expect a string; null can cause template errors. For optional arrays (social, legal links), you can omit the key entirely or pass an empty array ([]).

How do I test brand.json changes locally?

Edit brand.json, rebuild (npm run build), and inspect the output. Or run npm run dev and hard-refresh the page. Since brand.json is loaded at build time, you'll see changes instantly in the rendered HTML and head tags.

Can I add custom fields to brand.json?

Yes. The schema is a convention, not a restriction. If your site needs fields like "founderName" or "supportPhoneUrgent", add them. The loaders will pass them through. Just document them so future maintainers know what they're for.

The Bottom Line

brand.json is single-source-of-truth infrastructure. One file holds your company's entire public identity — name, ABN, contact, social, voice, pricing, colours, SEO defaults. Pages read from it at build time. AI tools read from it during conversation. Fork the template to a new brand by editing JSON, not code. Port your existing site by consolidating scattered config into one canonical file. No more hunting for stale references. No more "did I update that too?" anxiety. One file, version-controlled, human-readable, machine-parseable. Check out the pricing page to see how Velocity X scaffolds a new brand in 15 minutes, or read the brand voice rules post to see how voice rules live alongside business data in the same file.

Let us make some quick suggestions?

Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.