---
title: Components
sort: 110
section-id: core-concepts
keywords: components, props, slots, lifecycle, tsx, velox components, islands
description: The Velox component model, including props, slots, lifecycle hooks, and the islands architecture
language: en
---
# Components
Velox components are TypeScript/TSX files that describe a piece of UI. They are the fundamental building blocks of a Velox application — reusable, composable, and by default rendered entirely on the server.
## Defining a Component
A basic Velox component is a TypeScript function that returns JSX:
```tsx
// components/Greeting.tsx
interface GreetingProps {
name: string;
formal?: boolean;
}
export default function Greeting({ name, formal = false }: GreetingProps) {
const salutation = formal ? 'Good day' : 'Hello';
return
{salutation}, {name}!
;
}
```
Use it in a route or another component:
```tsx
---
import Greeting from '../components/Greeting.tsx';
---
```
## Props
Props are typed using TypeScript interfaces or types. All props are validated at compile time — no runtime prop checking overhead.
```tsx
interface CardProps {
title: string;
description: string;
href?: string;
variant?: 'default' | 'featured' | 'compact';
children?: VeloxNode;
}
export default function Card({
title,
description,
href,
variant = 'default',
children,
}: CardProps) {
return (
);
}
```
### Default Props
Set default values directly in the destructuring parameter, as shown above. Velox does not use a separate `defaultProps` mechanism.
### Required vs Optional Props
By TypeScript convention, optional props are marked with `?`. Omitting a required prop is a compile-time error.
## Slots
The `children` prop is the default slot — content placed between the opening and closing tags of a component:
```tsx
This is the card body.
```
### Named Slots
For more complex component APIs, use named slot props:
```tsx
interface ModalProps {
title: VeloxNode;
footer?: VeloxNode;
children: VeloxNode;
}
export default function Modal({ title, footer, children }: ModalProps) {
return (
```
## Server vs Client Components
By default, all Velox components run on the server. They have no JavaScript bundle size on the client and cannot use browser APIs or client-side reactivity.
To make a component interactive on the client, use the `client:*` hydration directive when you include it in a route:
```tsx
---
import Counter from '../components/Counter.tsx';
import LazyChart from '../components/LazyChart.tsx';
---
```
### Writing Client Components
Client components can use signals, effects, and browser APIs:
```tsx
import { signal, effect, onMount, onCleanup } from 'velox/client';
export default function LiveClock() {
const time = signal(new Date().toLocaleTimeString());
onMount(() => {
const interval = setInterval(() => {
time.value = new Date().toLocaleTimeString();
}, 1000);
onCleanup(() => clearInterval(interval));
});
return
Current time: {time}
;
}
```
## Lifecycle Hooks
Client-side components can use the following lifecycle hooks:
| Hook | When it runs |
|------|-------------|
| `onMount(fn)` | After the component is first rendered and inserted into the DOM |
| `onUpdate(fn)` | After every re-render (reactive signal change) |
| `onCleanup(fn)` | Before the component unmounts or before the next `onUpdate` call |
| `onDestroy(fn)` | When the component is permanently unmounted |
```tsx
import { signal, onMount, onUpdate, onCleanup } from 'velox/client';
export default function DataComponent() {
const data = signal([]);
const loading = signal(true);
onMount(async () => {
const response = await fetch('/api/data');
data.value = await response.json();
loading.value = false;
});
onCleanup(() => {
// abort pending requests, clear timers, etc.
});
return (
{loading.value ?
Loading...
:
{data.value.map(d =>
{d.name}
)}
}
);
}
```
## Component Composition Patterns
### Higher-Order Components
```tsx
function withAuth(Component: VeloxComponent) {
return function AuthGated(props: T) {
const user = useUser();
if (!user) return ;
return ;
};
}
```
### Render Props / Function-as-Children
```tsx
interface FetcherProps {
url: string;
render: (data: T) => VeloxNode;
}
export function Fetcher({ url, render }: FetcherProps) {
// ... fetch logic
return render(data);
}
```
## Component Library
Velox ships an optional official component library `@velox/ui` with accessible, unstyled base components. Install it separately:
```bash
npm install @velox/ui
```
```tsx
import { Button, Input, Dialog } from '@velox/ui';
```
See the [Component API](api-components.md) reference for the full `defineComponent` API and advanced component patterns.