# Components

<ExperimentalFeatureAside feature="Canvas Headless" />

**Goal:** know how the [components](/start-here/glossary/#component) editors place on [Drupal Canvas](/start-here/glossary/#drupal-canvas) pages are created, identified, and kept in sync when your app is the renderer.

## What you'll have when you're done

- A working model of where components live in the app, what gives one its identity, and when the site learns about it.
- The rules that decide whether a component is offered for placement, and who is allowed to change what.

## Prerequisites

- An app registered with your site, from the [quickstart](/source-cms/get-content/quickstart/); its component directory already ships a working set (`Hero`, `Card`, `Accordion`, and more).

## Steps

1. **Know where components live.** `componentDir` in `canvas.config.json` at the project root is the single source: `components` in the Next.js template, `src/components` in Astro, `app/components` in Nuxt. Each component is a directory holding its `component.yml` (metadata), source file, and CSS file, the shape `npx canvas scaffold` writes in the quickstart's [component scaffold step](/source-cms/get-content/quickstart/#add-a-component-of-your-own). An app component you already have becomes a Canvas component by gaining a `component.yml` beside it.

2. **Give each component its identity.**

   <Tabs syncKey="method">
   <TabItem label="Yourself">

   `machineName` in `component.yml` is the component's identity in Canvas and the key your app's generated registry renders by. The scaffolder writes the placeholder `hello-world` into every new component, so the second scaffold collides with the first until you change it. `machineName` does not have to match the directory name, but a name that does is easier to live with. Change `machineName` later and Canvas treats it as a different component: the new name registers, and the old entry is deactivated.

   </TabItem>
   <TabItem label="With an AI agent">

   Hand your agent this page's Markdown export (the `View as Markdown` control at the top) for the identity and status rules, then the edit:

   ```text
   In components/<name>/component.yml set machineName to <name> and status: true.
   machineName is the component's identity; renaming it later registers a new
   component and deactivates the old one.
   ```

   </TabItem>
   </Tabs>

3. **Decide what editors can place.** `status: true` offers the component for placement; a component left at the scaffolder's `status: false` still synchronizes, and the site records it, but the library does not offer it. Nobody can rename an external component or flip its status from the editor: its identity belongs to the app that implements it, so both changes happen in `component.yml`.

4. **Let synchronization do the rest.** There is nothing to push. Canvas reads your app's component metadata endpoint when the editor loads and registers every component it finds, so a reload after a change is what publishes it to the library. The [props](/start-here/glossary/#prop) declared in a component's `component.yml` appear as editable fields in the editor's right-hand panel when that component is placed. Components that already exist on the site come the other way: `npx canvas pull` brings them into the app's codebase in the same format.

## When something goes wrong

**A component is missing from the library**: check its `component.yml`. `status` left at `false` registers without offering; `machineName` left at `hello-world` collides with the previous scaffold. Fix the file and reload the editor, since components synchronize when it loads.

## Next steps

- [Component development guide](/source-cms/canvas-components/guide/): the authoring model itself: props as JSON Schema, slots, styling, and composition.
- [Prop type declarations](/source-cms/reference/canvas-cli/#prop-type-declarations): the exact schema that declares each prop type the editor offers, single- and multi-value.
- [First fetch](/source-cms/content-api/first-fetch/): the advanced path, when a component's page is not enough and you need the content as data.
