---
title: "Vue Components"
description: "Schema.org Vue components API (deprecated). Use composables like useSchemaOrg() instead for better TypeScript support."
canonical_url: "https://unhead.unjs.io/docs/nuxt/schema-org/guides/core-concepts/vue-components"
last_updated: "2026-07-29T15:06:51.773Z"
---

The component API is deprecated. Prefer `useSchemaOrg()` for stronger TypeScript support. Existing component code can pass node data through attributes or named slots.

## Headless Attributes

Component attributes are forwarded to the Schema.org node.

Omit the `@` prefix from fields such as `@type` and `@id`.

For example, to set a page name and type:

```vue
<template>
  <!-- About us page inline -->
  <SchemaOrgWebPage type="AboutPage" name="About Us" />
</template>
```

## Headless Slots

Named slots can provide the same data as attributes.

Only shallow text nodes are supported.

This FAQ question uses named slots:

```vue
<template>
  <SchemaOrgQuestion>
    <template #name>
      What is the capital of Australia?
    </template>
    <template #acceptedAnswer>
      Canberra
    </template>
  </SchemaOrgQuestion>
</template>
```

## Rendered Default Slot

To render markup with full customization, provide a default slot. Its slot props contain the resolved node.

```vue
<template>
  <SchemaOrgQuestion>
    <!-- Scoped slots won't render anything -->
    <template #name>
      {{ question }}
    </template>
    <template #acceptedAnswer>
      <div>{{ answer }}</div>
    </template>
    <!-- Default slot will render -->
    <h2>
      {{ question }}
    </h2>
    <div>{{ answer }}</div>
  </SchemaOrgQuestion>
</template>
```

Interpolation escapes HTML. If the answer must contain markup, sanitize it before using `v-html`; Vue's [security guidance](https://vuejs.org/guide/best-practices/security#html-injection) recommends rendering only trusted HTML.
