Project Brief Builder
ComponentsProject Brief Builder
SectionsNew

Project Brief Builder

Turn a first hello into a useful enquiry. An editorial, three-step project brief with service choices, budget, contact details, and a final review.

USE IT FORAgency enquiriesFreelance project briefsStudio contact pages
React + CSS
Explore the full-width experienceOpen preview
northlineOpen for brand & web work

01 / 03 — THE POSSIBILITIES

What are we making?

One thing or a few. Choose what you have in mind.

The project
I’m looking for (choose one or more)
A few details. About 2 minutes.
A LITTLE CONTEXT. A LOT OF POSSIBILITY.northline / LET’S MAKE IT MATTER

NORTHLINE IS A FICTIONAL INDEPENDENT STUDIO.INTERACTIVE PREVIEW · NOTHING IS SENT OR SAVED.

Live component. Go ahead, interact.
01

Installation

Run this in your shadcn-configured React project. The component and stylesheet are added together.

TERMINAL
npx shadcn@latest add http://localhost:5173/r/project-brief-builder.json

This command uses the current site address. For localhost, keep this preview running on the same computer. Files follow your configured components alias.

02

Usage

Import the component and make the details your own.

TypeScript
'use client';

import { useState } from 'react';
import { ProjectBriefBuilder } from '@/components/anticraft/ProjectBriefBuilder';
import type { ProjectBrief } from '@/components/anticraft/ProjectBriefBuilder';

export function Example() {
  const [, setPreview] = useState<ProjectBrief | null>(null);
  // This runnable example stays in memory. For a live site, replace this
  // callback with your endpoint and reject when its response is unsuccessful.
  async function previewBrief(brief: ProjectBrief) {
    setPreview(brief);
  }

  return (
    <ProjectBriefBuilder
      studioName="northline"
      title="Your next project."
      description="A new identity, a website, or a shift in direction. Tell us where you’re headed."
      availability="Open for new collaborations"
      services={[
        { id: 'brand', label: 'Brand identity', description: 'A clear point of view' },
        { id: 'website', label: 'Digital experience', description: 'A place that feels like you' },
        { id: 'strategy', label: 'Creative strategy', description: 'The thinking before the making' },
        { id: 'other', label: 'Something else', description: 'Let’s find out together' },
      ]}
      budgets={[
        { id: '5-10k', label: '$5,000 – $10,000' },
        { id: '10-25k', label: '$10,000 – $25,000' },
        { id: '25k-plus', label: '$25,000+' },
        { id: 'discuss', label: 'Let’s discuss' },
      ]}
      timelines={[
        { id: 'soon', label: 'As soon as possible' },
        { id: '1-3-months', label: 'In the next 1–3 months' },
        { id: 'exploring', label: 'Just exploring' },
      ]}
      submitLabel="Preview the brief"
      successTitle="Your brief, assembled."
      successMessage="Your preview is ready. This example does not send or save your details."
      onSubmit={previewBrief}
    />
  );
}
03

Props

PropTypeDefaultDescription
servicesProjectBriefOption[]RequiredService choices with unique nonempty id and label values. Optional description appears below a service name. Visitors must choose at least one. Keep the options stable throughout a brief when possible. Removed selections are excluded from the review and delivery; if none remain, submission returns to the service choices.
budgets / timelinesProjectBriefOption[]RequiredNative select choices with unique nonempty id and label values. Both selections are required. Description is unused for select choices. If a selected option is removed, its select shows the placeholder and validation requires a new choice. An empty services, budgets, or timelines list displays a setup message instead of an unusable form.
onSubmit(brief: ProjectBrief) => void | Promise<void>RequiredReceives services ids, description, budget id, timeline id, name, email, and optional company text. Strings are trimmed for delivery. Resolve only after your own submission succeeds; throw or reject to show an error and retain every field for retry. The component has no endpoint or storage. A synchronous ref prevents rapid duplicate submissions; controls stay disabled while the promise is pending. Callbacks must be supplied from a client component in Next.js.
studioNamestring'Your studio'The studio wordmark in the masthead and colophon.
eyebrow / title / descriptionstringBuilt-in introductory copyThe introduction beside the form. Title names the section; keep it concise for an editorial composition.
availabilitystring'Open for new collaborations'A brief availability statement in the masthead.
submitLabelstring'Send your brief'The final submit button. Earlier steps use Continue; the pending state reads Submitting… .
successTitle / successMessagestringBuilt-in confirmation copyThe confirmation shown only after onSubmit resolves. A visible receipt repeats the project, contact details, budget, timeline, and description. Start another brief clears the in-memory state and returns to the first step. The library demo explicitly labels its local preview: nothing is sent or saved.
classNamestring''Additional root classes. Customize --ac-brief-paper, --ac-brief-ink, --ac-brief-muted, --ac-brief-line, --ac-brief-accent and --ac-brief-radius. Container queries adapt the two-column layout to a stacked phone form below 580px. Content uses natural page scrolling on short desktops; no viewport-fixed stage or clipped fields.
04

Motion & accessibility

Considered by default.

Three steps retain the entered brief when going back or editing the review. Continue validates required choices and a project description of at least 20 characters; the next step validates budget, timeline, name and email. Errors focus the first invalid field. Step changes and successful submission focus the new heading. Enter advances or submits from single-line fields; a textarea keeps normal newline behavior. Native checkboxes and selects support keyboard and touch. Choice and button color transitions respect reduced motion. No automatic advance, scroll capture, storage, email sending, or external dependency is included.

Use semantic content and meaningful labels in your composition. Check contrast and keyboard behavior with your own styles and content.

05

Inspiration

Guided, manageable steps inspired this practical enquiry flow. Anticraft’s original studio composition uses warm paper, restrained typography, real validation, an editable review, and an application-owned submission callback.

Visit Cult UI — Onboarding

The component source and demo artwork are original to Anticraft UI. The linked site is the design or content reference.