Using Person Schema allows you to structure information about individuals, authors, team members, etc., so that AI models and search engines can better understand them.
Configure it as a global schema in nuxt.config.ts to automatically inject it into all pages:
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['nuxt-aeo'],
aeo: {
schemas: [
{
type: 'Person',
name: 'Yeonju Lee',
alternateName: 'Dewdew',
jobTitle: 'Software Engineer / CDO',
url: '/profile', // Relative URL - will be normalized to absolute
image: '/images/profile.jpg', // Relative URL - will be normalized to absolute
knowsAbout: ['Nuxt3', 'TypeScript', 'Supabase'],
sameAs: [
'https://github.com/dewdew', // Absolute URL - used as-is
'/social/twitter', // Relative URL - will be normalized to absolute
],
renderHtml: true, // Generate semantic HTML
visuallyHidden: true, // Visually hide
},
],
autoInject: true,
},
})
To add Person Schema only on specific pages, use the useSchema() composable:
Note:
useSchema()automatically normalizes URLs:
- Absolute URLs (starting with
http://orhttps://) are used as-is- Relative URLs are combined with the base URL (from
useRequestURL()orapp.baseURL)- URL normalization applies recursively to nested objects and arrays (e.g.,
sameAs[],worksFor.url)- Processes
url,image,logo, anditemproperties throughout the schema
<script setup lang="ts">
useSchema({
context: 'https://schema.org',
type: 'Person',
name: 'John Doe',
jobTitle: 'Software Engineer',
url: '/profile', // Relative URL - will be normalized to absolute
image: '/images/profile.jpg', // Relative URL - will be normalized to absolute
knowsAbout: ['JavaScript', 'TypeScript', 'Vue.js'],
sameAs: [
'https://github.com/johndoe', // Absolute URL - used as-is
'/social/twitter', // Relative URL - will be normalized to absolute
],
renderHtml: true, // Generate semantic HTML
visuallyHidden: true, // Visually hide
})
</script>
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['nuxt-aeo'],
aeo: {
schemas: [
{
type: 'Person',
name: 'Yeonju Lee',
alternateName: 'Dewdew',
jobTitle: 'Software Engineer / CDO',
url: '/profile', // Relative URL - will be normalized to absolute
image: '/images/profile.jpg', // Relative URL - will be normalized to absolute
description: 'Full-stack developer specializing in Nuxt and Vue.js',
knowsAbout: ['Nuxt3', 'TypeScript', 'Supabase', 'Vue.js'],
sameAs: [
'https://github.com/dewdew', // Absolute URL - used as-is
'/social/twitter', // Relative URL - will be normalized to absolute
'https://linkedin.com/in/dewdew', // Absolute URL - used as-is
],
worksFor: {
type: 'Organization',
name: 'Example Company',
},
renderHtml: true,
visuallyHidden: true,
},
],
autoInject: true,
},
})
<script setup lang="ts">
// Person data with mixed absolute and relative URLs
const person = {
name: 'John Doe',
alternateName: 'johndoe',
jobTitle: 'Software Engineer',
url: '/profile', // Relative URL - will be normalized to absolute
image: '/images/profile.jpg', // Relative URL - will be normalized to absolute
description: 'Full-stack developer with expertise in web application development.',
knowsAbout: ['JavaScript', 'TypeScript', 'Vue.js', 'Nuxt', 'Node.js'],
sameAs: [
'https://github.com/johndoe', // Absolute URL - used as-is
'/social/twitter', // Relative URL - will be normalized to absolute
'https://linkedin.com/in/johndoe', // Absolute URL - used as-is
],
worksFor: {
name: 'Example Company',
},
}
// Add Person Schema
useSchema({
context: 'https://schema.org',
type: 'Person',
name: person.name,
alternateName: person.alternateName,
jobTitle: person.jobTitle,
url: person.url,
image: person.image,
description: person.description,
knowsAbout: person.knowsAbout,
sameAs: person.sameAs,
worksFor: {
type: 'Organization',
name: person.worksFor.name,
},
renderHtml: true,
visuallyHidden: true,
})
</script>
The above example automatically adds the following JSON-LD script to the page <head>:
{
"@context": "https://schema.org",
"@type": "Person",
"name": "John Doe",
"alternateName": "johndoe",
"jobTitle": "Software Engineer",
"url": "https://example.com",
"image": "https://example.com/profile.jpg",
"description": "Full-stack developer with expertise in web application development.",
"knowsAbout": [
"JavaScript",
"TypeScript",
"Vue.js",
"Nuxt",
"Node.js"
],
"sameAs": [
"https://github.com/johndoe",
"https://twitter.com/johndoe",
"https://linkedin.com/in/johndoe"
],
"worksFor": {
"@type": "Organization",
"name": "Example Company"
}
}
When using the renderHtml: true option, the following semantic HTML is automatically generated and injected into the page:
<div class="nuxt-aeo-semantic-person nuxt-aeo-visually-hidden" aria-hidden="true">
<div itemscope itemtype="https://schema.org/Person">
<span itemprop="name">John Doe</span>
<span itemprop="alternateName">johndoe</span>
<span itemprop="jobTitle">Software Engineer</span>
<a itemprop="url" href="https://example.com">https://example.com</a>
<span itemprop="knowsAbout">JavaScript</span>
<span itemprop="knowsAbout">TypeScript</span>
<span itemprop="knowsAbout">Vue.js</span>
<!-- More skills... -->
</div>
</div>
name: Person's namealternateName: Alias, username, etc.jobTitle: Job titleurl: Personal website URLimage: Profile image URLdescription: Description of the personknowsAbout: Array of expertise areas or technical skillssameAs: Array of social media profile linksworksFor: Organization informationPerson Schema supports many more properties. For details, refer to the Schema.org Person documentation.
<script type="application/ld+json"> tag in the Elements tabnuxt-aeo-semantic-person class is injected inside the body tagOr you can run the following command in the Developer Tools console:
// Check semantic HTML
document.querySelectorAll('.nuxt-aeo-semantic-person').forEach(el => {
console.log('✅ Person semantic HTML:', el.innerHTML)
})
// Check JSON-LD schema
document.querySelectorAll('script[type="application/ld+json"]').forEach(script => {
const schema = JSON.parse(script.innerHTML)
if (schema['@type'] === 'Person') {
console.log('✅ Person JSON-LD:', schema)
}
})
context and type are automatically converted to @context and @type internallyrenderHtml: true option provides both JSON-LD and semantic HTML together to further optimize LLM crawlingknowsAbout property is useful for representing a person's areas of expertise or technical skillsThis page includes FAQPage Schema to help AI models and search engines understand common questions about this topic.
<script setup lang="ts">
useSchemaFaq({
mainEntity: [
{
name: 'When should I use Person Schema?',
acceptedAnswer: {
text: 'Person Schema is used to structure information about individuals, authors, team members, etc. It can be used on blog author information, team introduction pages, profile pages, contact pages, and more. It helps AI models and search engines better understand personal information.',
},
},
{
name: 'What is the difference between global and page-specific configuration?',
acceptedAnswer: {
text: 'Global configuration (nuxt.config.ts) automatically injects Person Schema into all pages. This is useful when displaying the same personal information across the entire site. Page-specific configuration (useSchema()) is used when you want to add Person Schema only on specific pages, allowing you to display different personal information on each page.',
},
},
{
name: 'What is the knowsAbout property?',
acceptedAnswer: {
text: 'The knowsAbout property represents the areas of expertise or technical skills that a person knows as an array. For example, you can list technical skills or areas of expertise like ["Nuxt3", "TypeScript", "Vue.js"]. This helps AI models understand the person\'s expertise.',
},
},
{
name: 'What are the renderHtml and visuallyHidden options?',
acceptedAnswer: {
text: 'Setting renderHtml to true automatically generates semantic HTML in Schema.org microdata format in addition to JSON-LD. Setting visuallyHidden to true hides the generated HTML visually so it is not visible to users, but AI models and search engines can read it. Using both options together further optimizes LLM crawling.',
},
},
],
})
</script>