Brandedflow nextjs-component-builder

Build Next.js React components following BrandedFlow conventions. Use process.env (not import.meta.env), Tailwind CSS, TypeScript. Use when building UI components for the Hub or client portals.

install
source · Clone the upstream repo
git clone https://github.com/JenCW/brandedflow
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/JenCW/brandedflow "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.claude/skills-library/nextjs-component-builder" ~/.claude/skills/jencw-brandedflow-nextjs-component-builder && rm -rf "$T"
manifest: .claude/skills-library/nextjs-component-builder/SKILL.md
source content

Next.js Component Builder

When to Use

  • Building a new Hub component
  • Adding a UI feature to the company hub
  • Building client portal components
  • Refactoring existing components

BrandedFlow Next.js Rules

  • Env vars: Always
    process.env.VAR_NAME
    (never
    import.meta.env
    )
  • Styling: Tailwind CSS only (no inline styles unless dynamic)
  • Types: TypeScript preferred
  • npm install: Always
    --legacy-peer-deps
  • Data fetching: Use API routes (
    /api/
    ) — never call Airtable or external APIs directly from client components
  • Hub API:
    https://brandedflow-hub-api.onrender.com

Hub Design System

  • Background: dark glassmorphism (
    bg-black/40 backdrop-blur-md
    )
  • Cards:
    bg-white/5 border border-white/10 rounded-2xl
  • Text: white primary,
    text-white/60
    secondary
  • Accent: gold (
    #C9A84C
    )
  • Font: system default

Component Template

'use client';

import { useState, useEffect } from 'react';

interface Props {
  // define props
}

export default function ComponentName({ }: Props) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch(`${process.env.NEXT_PUBLIC_API_URL}/endpoint`)
      .then(r => r.json())
      .then(d => { setData(d); setLoading(false); })
      .catch(() => setLoading(false));
  }, []);

  if (loading) return <div className="animate-pulse bg-white/5 rounded-2xl h-32" />;

  return (
    <div className="bg-white/5 border border-white/10 rounded-2xl p-6">
      {/* content */}
    </div>
  );
}

API Route Template

// app/api/[route]/route.ts
import { NextResponse } from 'next/server';

export async function GET() {
  try {
    const res = await fetch(process.env.HUB_API_URL + '/endpoint');
    const data = await res.json();
    return NextResponse.json(data);
  } catch (err) {
    return NextResponse.json({ error: 'Failed' }, { status: 500 });
  }
}

End of Task

State: "END-OF-TASK: Directive [N/A]. Self-annealing [applied/N/A]."