Fazekit

Code

"use client";
import * as React from "react";
import { MotionConfig, useReducedMotion } from "motion/react";
import { cn } from "@/lib/utils";
import { defaultFluxData, type FluxData, type Piece } from "./data";
import { Contact, Footer, Manifesto, type FluxInquiry } from "./sections/closing";
import type { GenParams } from "./sections/gen";
import { Hero } from "./sections/hero";
import { Maker, type MakerPreset } from "./sections/maker";
import { Navbar } from "./sections/navbar";
import { scrollToId } from "./sections/ui";
import { Gallery, Studio } from "./sections/work";

export type { FluxData, FluxInquiry, GenParams };
export { defaultFluxData };

export interface GenerativeStudioTemplateProps {
  /** Override any content group (hero, gallery pieces, palettes…). Missing groups use the demo content. */
  data?: Partial<FluxData>;
  /** Size of the square PNG exported by the generator. Default 2048. */
  exportSize?: number;
  /** Called with the parameters and PNG blob whenever someone downloads a piece. */
  onDownload?: (params: GenParams, blob: Blob) => void;
  /** Called when the contact form is submitted. */
  onInquiry?: (v: FluxInquiry) => Promise<void> | void;
  className?: string;
}

export function GenerativeStudioTemplate({ data, exportSize, onDownload, onInquiry, className }: GenerativeStudioTemplateProps) {
  const d = React.useMemo(() => ({ ...defaultFluxData, ...data }), [data]);
  const reduce = useReducedMotion();
  const [preset, setPreset] = React.useState<MakerPreset | null>(null);
  const openInMaker = React.useCallback(
    (p: Piece) => {
      setPreset((cur) => ({ style: p.style, seed: p.seed, palette: p.palette, density: p.density, turbulence: p.turbulence, nonce: (cur?.nonce ?? 0) + 1 }));
      scrollToId("make", reduce);
    },
    [reduce],
  );

  return (
    <MotionConfig reducedMotion="user">
      <div className={cn("relative w-full overflow-x-clip bg-background text-foreground antialiased selection:bg-orange-600 selection:text-white", className)}>
        <Navbar brand={d.brand} links={d.nav} />
        <main>
          <Hero data={d} onCta={() => scrollToId("contact", reduce)} onWork={() => scrollToId("work", reduce)} />
          <Studio data={d} />
          <Gallery data={d} onOpenInMaker={openInMaker} />
          <Maker data={d} preset={preset} exportSize={exportSize} onDownload={onDownload} />
          <Manifesto data={d} />
          <Contact data={d} onSubmit={onInquiry} />
        </main>
        <Footer data={d} />
      </div>
    </MotionConfig>
  );
}

More in Landing Pages

View all →