Atelier UI®

DocsCatalogShader StudioPricingGithub
Docs 1.0.0

tools

  • Browse Catalog
  • Shader Studio
    pro
  • Collage
    new

Documentation

  • How it works
  • License
  • MCP

Page Transition (04)

  • Clip Transition
  • Stripe Transition
  • Pixel Transition
  • Band Transition

Components (36)

  • Orbit Gallery
  • Sphere Gallery
  • Spiral Gallery
  • Glowing Fog
  • Gradient Flow
  • Halftone Glow
  • Scattered Grid
  • Tag Cloud
  • Edge Bounce
  • Fluid Distortion
  • Image Trail
  • Lens Media
  • Liquid Media
  • Magnetic Dot Grid
  • Pixel Media
  • Pixel Trail
  • Dither Cursor
  • Hover Burst
  • Image Bloom
  • Curve Media
  • Infinite Gallery
  • Infinite Parallax
  • Infinite Zoom
  • Pixel Scroll
  • Scattered Scroll
  • Elastic Stick
  • Letter Swarm
  • Magnify Trail
  • Stacking Grid
  • Wavy Scroll
  • Pixelated Text
  • Text Bounce
  • Text Fluid
  • Text Scramble
  • Falling Text
  • Text Roll

Foundation Blocks (07)

  • Smooth Scroll
  • Text Split
  • WebGL Image
  • WebGL Provider
  • WebGL Scene
  • WebGL Text
  • WebGL Video
Atelier UI 1.0.0 ©2026
Star on githubBuy me a coffeellms.txt
  1. Docs
  2. /
  3. Getting Started
  4. /
  5. Contribution

How to contribute

Contribution guidelines for the project.

  • Project structure
  • Component format
  • Dependencies
  • Testing
  • Add a new component
  • Base component
  • Demo component
  • Exporting the demo
  • Adding to the registry
  • Write the documentation
  • Frontmatter
  • Guide and preview
  • Usage and API sections
  • Controls

Notes

This project uses pnpm as the package manager; you must have pnpm installed globally to run commands and tests locally.


Project structure

Here is where each type of file lives:

  • src/registry/base holds the components that ship to users.
  • src/registry/hooks and src/registry/lib hold code shared between components.
  • src/registry/demos holds demo components and their controls.
  • src/registry/index.ts declares every component and its dependencies.
  • src/content holds documentation.
Visual representation
(src/registry)
|-- base
|   |-+ your-component
|       |-+ your-component.tsx          # Your new component
|-- hooks
|   |-+ use-frame-loop.ts               # Shared hooks
|-- demos
|   |-+ your-component
|   |   |-+ your-component.tsx          # Your new demo component
|   |   |-+ controls.ts                 # Your demo controls
|   |
|   |-- index.ts                        # Exports the demo components

(src/content)
|-- en
    |-- components
        |-- _dir.yml
        |-+ your-component
            |-+ your-component.mdx      # Your new component documentation

Component format

Each component has a single responsibility and lives in a single file, so it stays self-contained and easy to reuse.

Every base component starts with "use client". Components run hooks and browser APIs, and users drop them into server components, which is the default in the Next.js app router.

Component structure
"use client"

const NAMED_X_CONSTANT = {...} as const
const NAMED_Y_CONSTANT = "value" as const

function helperFunction() {...}

type ComponentExampleProps = {...} & ComponentProps<'div'>

export function ComponentExample({}: ComponentExampleProps) {...}

When logic is shared across components, put it in src/registry/hooks or src/registry/lib and list the file in the component's shared field. The use-frame-loop hook is one example.


Dependencies

This project uses motion.dev for DOM-based animations, React Three Fiber for WebGL effects, and Tailwind CSS for styling.

Vanilla JS animations such as requestAnimationFrame and the Web Animations API can also be used where a library isn't needed.

Anything listed in a component's dependencies is installed on the user's machine, so the list has to be complete. A component that imports Three.js types declares @types/three next to three.


Testing

Tests run automatically on every pull request. They verify that every component has its files, demo, export, and documentation in sync. Unit tests per component are not required by default.


Add a new component

Use the pnpm scafold-new command. It creates the base component, the demo, a templated MDX doc, and patches the registry and demo index.

Terminal
pnpm scafold-new animated-text --category scroll
pnpm scafold-new sparkle --category background

If you prefer to do it manually, follow the steps below.

Base component

Create a folder in src/registry/base named after the component:

src/registry/base/component-name/component-name.tsx
"use client"

export function ComponentName() {
  return <></>;
}

Demo component

Create a demo in src/registry/demos and structure it how you want:

src/registry/demos/component-name/component-name.tsx
import { ComponentName } from "@/registry/base/component-name/component-name";

export default function ComponentNameDemo() {
  return <ComponentName />;
}

Exporting the demo

Export the demo in src/registry/demos/index.ts:

src/registry/demos/index.ts
export const demos: Record<
  string,
  React.LazyExoticComponent<React.ComponentType>
> = {
  "component-name": lazy(() => import("./component-name/component-name")),
};

Adding to the registry

Declare the component in src/registry/index.ts:

src/registry/index.ts
export const components: TRegistryComponent[] = [
  {
    name: "new-component",
    files: ["new-component.tsx"],
    description: "My new component",
    shared: ["hooks/use-my-hook.ts"],
    dependencies: ["motion"],
    registryDependencies: ["text-split"],
  },
];

shared takes full paths with their extension, relative to src/registry. registryDependencies names other registry components, which the CLI installs alongside this one.


Write the documentation

A component page opens on its preview, then folds the prose into collapsible sections. The order is frontmatter, install guide, Usage, API, and the components it builds on.

Frontmatter

Add the metadata for the component:

Frontmatter
---
title: "New Component"
description: "My new component"
icon: "Component"
---

Guide and preview

The preview is built by the doc page from the registry, so the document does not declare it.

Add the installation guide with the <InstallGuide /> component, using the exact name of the base component. It renders the agent prompt, with the CLI command and the file-by-file copy collapsed underneath it.

Install example
<InstallGuide name="component-name" />

Usage and API sections

Wrap the prose in <Collapsible /> so the page opens on the preview:

Section structure
<Collapsible title="Usage">

Import paths repeat the component name, because each file installs to
`components/<name>/<name>.tsx`:

```tsx
import { ComponentName } from "@/components/component-name/component-name";
```

</Collapsible>

---

<Collapsible title="API" defaultOpen>

| Name    | Type     | Default   | Description                              |
| ------- | -------- | --------- | ---------------------------------------- |
| `speed` | `number` | `1`       | Controls the animation speed multiplier. |
| `color` | `string` | `#ff5733` | Sets the primary color of the component. |

</Collapsible>

Close the page with <BuiltOn />, which links the component to the primitives it is built from:

Built on
<BuiltOn name="component-name" />

Controls

Controls let users change props on the live preview, and the values travel into the copyable agent prompt. Declare them in src/registry/demos/<component-name>/controls.ts and register the file in src/registry/demos/controls.ts.

The values have to match the default props of the base component:

src/registry/demos/component-name/controls.ts
import type { ControlDef } from "@/types/controls"

export const controls: Record<string, ControlDef> = {
    speed: { type: "slider", value: 1, min: 0, max: 10, step: 0.1 },
    color: { type: "color", value: "#ff5733" },
    palette: { type: "palette", value: ["#ff5733", "#33c1ff"], min: 2, max: 5 },
    variant: { type: "select", value: "solid", options: ["solid", "outline"] },
    enabled: { type: "boolean", value: true },
    glow: { type: "slider", value: 0.5, min: 0, max: 1, step: 0.01, showIf: "enabled" },
}
TypeFieldsRenders
slidervalue min max stepSlider
colorvalueColor picker
palettevalue min maxColor list
selectvalue optionsSelect
booleanvalueToggle switch

Any control takes an optional showIf, naming a boolean control that has to be on for it to render.

Export the base component's props type, then spread controls onto it:

Demo component
export default function ComponentNameDemo(
  controls: Partial<ComponentNameProps>,
) {
  return <ComponentName {...controls} />;
}
Star on githubBuy me a coffeellms.txt