docs / Language
Component Declarations
The component keyword, typed params, generics, async and island modifiers, and the two body modes.
`component` is the Vesk component keyword — the unit of markup, state and effects. The compiler transforms a component body into IR and generates both server (SSR) and client (hydration) code from it.
Syntax
component App {
<div>Hello World</div>
}
component Greeting(props: { name: string }) {
<div>Hello, {props.name}!</div>
}
export default async component Page(props: { id: string }) {
const res = await fetch(`/api/items/${props.id}`);
const item = await res.json();
<p>{item.title}</p>
}
- `component` is a reserved keyword — using it as an identifier raises a compiler error.
- Params are optional and fully TypeScript-typed; `component Name { }` is the same as `component Name() { }`.
- Generic type parameters are supported: `component List<T>(props: { items: T[] }) { ... }`.
- `async` may appear directly before `component` or after `export`: `export default async component X() { ... }`.
- `client` (the island modifier) may appear after the closing paren or after `component` — both parse to the same `client: true` flag.
Body modes
A component body is either expression mode — it ends with `return <jsx>;` — or statement mode — markup and control flow appear directly as statements (bare JSX, `if`, `for`, `switch`, `try`, guard-clause early returns). Both modes produce the same IR nodes, so every feature works in both.
component App {
<div>Hello World</div>
}
component Greeting(props: { name: string }) {
<div>Hello, {props.name}!</div>
}
export default async component Page(props: { id: string }) {
const res = await fetch(`/api/items/${props.id}`);
const item = await res.json();
<p>{item.title}</p>
}
The parser emits a `ComponentDeclaration` node with id, params, body, async, client and optional typeParameters fields — the AST shape the IR generator consumes.