# Getting Started

Get up and running with Fluid Primitives in just a few steps. This guide covers installation, basic setup, and creating your first component.

## Prerequisites

- TYPO3 13+
- PHP 8.3+
- Basic familiarity with [Fluid Components](https://docs.typo3.org/other/typo3fluid/fluid/main/en-us/Usage/Components.html)
- A modern JavaScript build setup like Vite, Webpack, etc. (Recommended)

## Installation

Install both the PHP and JavaScript packages:

```bash
composer require jramke/fluid-primitives
npm install fluid-primitives
```

<div class="relative w-full rounded-lg border px-4 py-3 text-sm grid has-[&gt;svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[&gt;svg]:gap-x-3 gap-y-0.5 items-start [&amp;&gt;svg]:size-4 [&amp;&gt;svg]:translate-y-0.5 [&amp;&gt;svg]:text-current text-warning bg-warning/5 border-warning/30 [&amp;&gt;svg]:text-warning *:[&amp;[data-scope=alert][data-part=content]]:text-warning/90 not-prose" role="alert" id="alert:«fqafmVhgz2»" data-scope="alert" data-part="root" >

<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-5"> <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"></path> <path d="M12 9v4"></path> <path d="M12 17h.01"></path> </svg>

<div class="col-start-2 min-h-4 font-medium tracking-tight" id="alert:«fqafmVhgz2»:title" data-scope="alert" data-part="title" >

<h3>Version Match</h3>

</div>

<div class="text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&amp;_p]:leading-relaxed" id="alert:«fqafmVhgz2»:content" data-scope="alert" data-part="content" >

<p>Keep the Composer and npm package versions in sync to avoid compatibility issues.</p>

</div>

</div>

### Canary Builds

Need a fix before the next release? Use the canary builds:

```bash
composer require jramke/fluid-primitives:"dev-main"
npm install fluid-primitives@next
```

## Setup

### 1. Create a Component Collection

Create a `ComponentCollection` class in your sitepackage to register your component paths and contexts:

```php
<?php

declare(strict_types=1);

namespace MyVendor\MySitepackage\Components;

use Jramke\FluidPrimitives\Component\AbstractComponentCollection;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3Fluid\Fluid\View\TemplatePaths;

final class ComponentCollection extends AbstractComponentCollection
{
    public function getTemplatePaths(): TemplatePaths
    {
        $templatePaths = new TemplatePaths();
        $templatePaths->setTemplateRootPaths([
            ExtensionManagementUtility::extPath('my_sitepackage', 'Resources/Private/Components/ui'),
            ExtensionManagementUtility::extPath('my_sitepackage', 'Resources/Private/Components'),
        ]);
        return $templatePaths;
    }

    public function getContextNamespaces(): array
    {
        return [
            'MyVendor\\MySitepackage\\Components\\Contexts',
        ];
    }
}
```

**Important:** Use `AbstractComponentCollection` from Fluid Primitives, not Fluid core.

Why two template paths? This lets you use `<ui:button>` instead of `<ui:ui.button>`. See [File Structure](/docs/core-concepts/file-structure.md) for details.

### 2. Register the Namespace

Add the `ui` namespace to your `ext_localconf.php`:

```php
$GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['namespaces']['ui'][] =
    'MyVendor\\MySitepackage\\Components\\ComponentCollection';
```

<div class="relative w-full rounded-lg border px-4 py-3 text-sm grid has-[&gt;svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[&gt;svg]:gap-x-3 gap-y-0.5 items-start [&amp;&gt;svg]:size-4 [&amp;&gt;svg]:translate-y-0.5 [&amp;&gt;svg]:text-current text-warning bg-warning/5 border-warning/30 [&amp;&gt;svg]:text-warning *:[&amp;[data-scope=alert][data-part=content]]:text-warning/90 not-prose" role="alert" id="alert:«fqafmVhgz4»" data-scope="alert" data-part="root" >

<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-5"> <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"></path> <path d="M12 9v4"></path> <path d="M12 17h.01"></path> </svg>

<div class="col-start-2 min-h-4 font-medium tracking-tight" id="alert:«fqafmVhgz4»:title" data-scope="alert" data-part="title" >

<h3>Namespace Array</h3>

</div>

<div class="text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&amp;_p]:leading-relaxed" id="alert:«fqafmVhgz4»:content" data-scope="alert" data-part="content" >

<p>Fluid Primitives already registers ViewHelpers under <code>ui</code>. Append to the array instead of overwriting it.</p>

</div>

</div>

### 3. Include the Site Set (or TypoScript manually)

```yaml
name: vendor/myext
label: 'MyExt'
dependencies:
    - jramke/fluid-primitives
```

### 4. Optional: Component Settings

Expose custom settings to component templates:

```typoscript
plugin.tx_fluidprimitives {
    settings {
        # Your custom settings here
    }
}
```

These merge with `lib.contentElement.settings` and are available as `{settings}` in component templates.

## Your First Component

Create a simple button at `Resources/Private/Components/ui/Button/Button.html`:

```html
<ui:prop name="variant" type="string" optional="{true}" default="primary" />
<ui:prop name="type" type="string" optional="{true}" default="button" />

<button type="{type}" class="{ui:cn(value: 'btn btn--{variant} {class}')}" {ui:attributes()}>
    <f:slot />
</button>
```

Use it anywhere in your templates:

```html
<ui:button variant="secondary" data-analytics="cta"> Get Started </ui:button>
```

**What's happening:**

- [ui:prop](/docs/viewhelpers/ui-prop.md) defines the components arguments (props) with types and defaults
- [ui:attributes](/docs/viewhelpers/ui-attributes.md) forwards any extra attributes (like `data-*`)
- [ui:cn](/docs/viewhelpers/ui-cn.md) is a helper for conditional class names
- `{class}` is automatically available for additional classes
- `<f:slot />` renders child content

## Adding Interactive Components

For components with client-side behavior (accordion, dialog, tabs, etc.), you'll also need to initialize them in JavaScript.

Example with a collapsible:

```html
<ui:collapsible.root>
    <ui:collapsible.trigger>Toggle content</ui:collapsible.trigger>
    <ui:collapsible.content> Hidden content that expands/collapses </ui:collapsible.content>
</ui:collapsible.root>
```

```typescript
import { mountAll } from 'fluid-primitives';
import { Collapsible } from 'fluid-primitives/collapsible';

mountAll('collapsible', ({ props }) => {
    const collapsible = new Collapsible(props);
    collapsible.init();
    return collapsible;
});
```

See [Hydration](/docs/core-concepts/hydration.md) for the full picture on client-side setup.

## Next Steps

- [Core Concepts](/docs/core-concepts.md) - Understand composition, context, and hydration
- [Components](/docs/components.md) - Browse available primitives
- [ViewHelpers](/docs/viewhelpers.md) - Reference for `ui:prop`, `ui:ref`, and more
