一键导入
seo
Reference and checklist for SEO metadata on gallery pages. Use when writing, reviewing, or debugging useHead() and useSeoMeta() on any page.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Reference and checklist for SEO metadata on gallery pages. Use when writing, reviewing, or debugging useHead() and useSeoMeta() on any page.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Create a new painting or ceramic gallery page end-to-end: i18n translations, Vue page component, Menu.vue link update, and navigation. Use when asked to add a new gallery page to the site.
Reference pattern for creating gallery pages (painting and ceramic). Use this skill when building a new gallery page to ensure all SEO, i18n, and component conventions are followed.
Full SEO implementation pattern for gallery pages: useHead, useSeoMeta, canonical URL, hreflang, Open Graph, Twitter cards, and article tags. Use this skill when writing or reviewing SEO metadata on any page.
Manage translation entries in fr-FR.json and en-US.json. Use when adding, modifying, or reviewing i18n keys for gallery pages or shared labels.
i18n management for Atelier Libr'Émotions: key structure, naming conventions, both-locale rule, and translation quality guidelines. Use this skill when adding or modifying translation entries.
Vue 3 + Nuxt 4 conventions for this project: SFC structure, auto-imports, TypeScript, SCSS, components, and performance patterns. Use when writing or reviewing any .vue file.
| name | seo |
| description | Reference and checklist for SEO metadata on gallery pages. Use when writing, reviewing, or debugging useHead() and useSeoMeta() on any page. |
| disable-model-invocation | true |
| argument-hint | <page path to review or write SEO for> |
You are writing or reviewing SEO metadata for: $ARGUMENTS
The project uses @nuxtjs/seo v3. Every gallery page needs both useHead() and useSeoMeta().
const runtimeConfig = useRuntimeConfig()
const route = useRoute()
const baseUrl = ref(runtimeConfig.public.i18n.baseUrl)
// Path segment without locale prefix and without leading slash
const urlEndPath = '{domain}/{technique-kebab}/{category-kebab}'
// Path to OG image inside public/ (no leading slash)
const ogImageEndPath = '{domain_plural}/{technique_snake}/{category}/{Image}.webp'
const canonicalUrl = computed(() => `${baseUrl.value}${route.path}`)
route.path includes the locale prefix (/fr/... or /en/...) so canonicalUrl is always locale-correct.
useHead({
title: computed(() => t('pages.{domain}.{technique}.{category}.tab_name')),
meta: [
{
name: 'description',
content: computed(() => t('pages.{domain}.{technique}.{category}.meta.content')),
},
{
name: 'keywords',
content: `${computed(() => t('miscellaneous.{kw1}')).value},
${computed(() => t('miscellaneous.{kw2}')).value},
${computed(() => t('miscellaneous.art')).value},
${computed(() => t('miscellaneous.artist')).value},
${computed(() => t('miscellaneous.emotions')).value},
${computed(() => t('about.author')).value},
${computed(() => t('app.name')).value},
`,
},
],
link: [
{ rel: 'canonical', href: canonicalUrl.value },
{
rel: 'alternate',
href: computed(() => `${baseUrl.value}/en/${urlEndPath}`),
hreflang: 'en-US',
},
{
rel: 'alternate',
href: computed(() => `${baseUrl.value}/fr/${urlEndPath}`),
hreflang: 'fr-FR',
},
{
rel: 'alternate',
href: computed(() => `${baseUrl.value}/fr/${urlEndPath}`),
hreflang: 'x-default',
},
// iOS home screen: overrides app.vue global apple-icon.jpg with this page's gallery artwork.
// `key` is required so Unhead deduplicates — page-level entry wins over app.vue.
{
rel: 'apple-touch-icon',
sizes: '180x180',
href: `/${ogImageEndPath}`,
key: 'apple-touch-icon',
},
],
})
en-US, fr-FR, x-defaultx-default always points to /fr/ — French is the default localeurlEndPath (no locale prefix) and prepend /en/ or /fr/ manuallyroute.path for hreflang alternates — it carries the current localeuseSeoMeta({
ogTitle: '%s %separator %siteName',
twitterTitle: '%s %separator %siteName',
appleMobileWebAppTitle: '%s %separator %siteName',
description: computed(() => t('pages.{domain}.{technique}.{category}.meta.content')),
ogDescription: computed(() => t('pages.{domain}.{technique}.{category}.meta.content')),
twitterDescription: computed(() => t('pages.{domain}.{technique}.{category}.meta.content')),
ogImage: `${baseUrl.value}/${ogImageEndPath}`,
ogImageSecureUrl: `${baseUrl.value}/${ogImageEndPath}`,
ogImageAlt: computed(() => t('pages.{domain}.{technique}.{category}.meta.content')),
ogImageType: 'image/jpeg',
ogImageWidth: '1200',
ogImageHeight: '600',
twitterImage: `${baseUrl.value}/${ogImageEndPath}`,
twitterImageAlt: computed(() => t('pages.{domain}.{technique}.{category}.meta.content')),
twitterImageType: 'image/jpeg',
ogUrl: canonicalUrl.value,
ogType: 'article',
articleTag: [
computed(() => t('miscellaneous.{kw1}')).value,
computed(() => t('miscellaneous.art')).value,
computed(() => t('miscellaneous.artist')).value,
computed(() => t('miscellaneous.emotions')).value,
computed(() => t('about.author')).value,
computed(() => t('app.name')).value,
],
msapplicationTileImage: `${baseUrl.value}/${ogImageEndPath}`,
})
articleTag values use .value directly (resolved strings, not reactive). All other i18n values must be computed(() => t(...)).
// defineOgImageComponent('NuxtSeo', {
// theme: '#4A7C59',
// colorMode: 'dark',
// title: computed(() => t('pages.{domain}.{technique}.{category}.tab_name')),
// description: computed(() => t('pages.{domain}.{technique}.{category}.meta.content')),
// })
Do not remove this block from any page — it is kept for future activation.
Base keywords (every gallery page):
art, artist, emotions, about.author, app.name
| Domain | Additional keywords |
|---|---|
| Any painting page | painting, painter |
| Acrylic | + acrylic, abstracts, automatic_painting, abstract_art, mish_mash |
| Inks | + inks, indian_inks, landscape, roots, trees, water, water_jet |
| Oil | + oil_painting |
| Any ceramic page | ceramic, ceramicist |
| Electric kiln | + electric_kiln, nature, flowers |
| Porcelain | + porcelain, nature, flowers |
| Raku/smouldering | + raku_and_smouldering |
Keywords must match identically between meta[name=keywords] and articleTag.
"Galerie de…", "Collection de…", or "Découvrez…""Gallery of…", "Collection of…", or "Discover…"Correct FR example (137 chars):
"Collection de fleurs en porcelaine de Véronique Berthier : pièces délicates pour décoration murale ou sur meuble, seules ou associées à un élément naturel."
Choose a visually striking image from the gallery — not necessarily the first: