mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-23 06:10:32 +00:00
## Summary - Adds programmatic SEO model pages at `/p/supported-models/[slug]` for **207 models** auto-generated from `workflow_templates` (180 local + 27 partner nodes) - 3-file architecture: `generated-models.json` (auto-generated, checked in) + `model-metadata.ts` (editorial overrides) + `models.ts` (65-line merger) - Full JSON-LD per page: `SoftwareApplication` + `BreadcrumbList` + `FAQPage` (targeting AI Overviews / People Also Ask) - Partner node support: `directory: 'partner_nodes'` hides Download button, shows VIEW TUTORIAL - `generate-models.ts`: walks `workflow_templates` for local models + `API_PROVIDER_MAP` for 30+ partner integrations (Kling, Meshy, Luma, Runway, Stability AI, ByteDance, Google, etc.) - Weekly GH Actions workflow opens issue when new models appear in `workflow_templates` but not in `generated-models.json` - `add-model-page` Claude skill for Slack-driven model page PRs ## Files changed | File | Purpose | |------|---------| | `apps/website/src/config/generated-models.json` | Auto-generated, 207 models (27 partner + 180 local) | | `apps/website/src/config/model-metadata.ts` | Editorial overrides: docsUrl, blogUrl, featured (9 entries) | | `apps/website/src/config/models.ts` | 65-line merger — imports JSON + overrides, exports `models` + `getModelBySlug` | | `apps/website/scripts/generate-models.ts` | Build-time parser; run with `pnpm generate:models` | | `apps/website/src/i18n/translations.ts` | ~30 UI keys added (no per-model keys — displayName is plain string) | | `apps/website/src/pages/p/supported-models/[slug].astro` | Dynamic route with 3x JSON-LD schemas | | `apps/website/src/pages/p/supported-models/index.astro` | Model grid index page | | `apps/website/src/components/models/ModelHeroSection.vue` | Hero component | | `.github/workflows/model-page-discovery.yaml` | Weekly auto-discovery workflow | | `.claude/skills/add-model-page/SKILL.md` | Claude skill for adding/updating model pages | ## Test plan - [ ] `pnpm build` passes in `apps/website` - [ ] `/p/supported-models` index renders 207 model cards - [ ] `/p/supported-models/kling-ai` shows Partner Node eyebrow, no Download button, VIEW TUTORIAL CTA - [ ] `/p/supported-models/flux-1-dev` shows Diffusion Model eyebrow, Download + Tutorial buttons - [ ] `/p/supported-models/umt5-xxl-fp8-e4m3fn-scaled` redirects 301 to `umt5-xxl-fp16` (canonicalSlug) - [ ] Structured data validator shows FAQPage + SoftwareApplication + BreadcrumbList valid Fixes FE-421 --------- Co-authored-by: GitHub Action <action@github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
138 lines
3.5 KiB
Vue
138 lines
3.5 KiB
Vue
<script setup lang="ts">
|
|
import { cn } from '@comfyorg/tailwind-utils'
|
|
import BrandButton from '../common/BrandButton.vue'
|
|
import { t } from '../../i18n/translations'
|
|
|
|
const {
|
|
displayName,
|
|
huggingFaceUrl,
|
|
docsUrl,
|
|
blogUrl,
|
|
hubSlug,
|
|
workflowCount,
|
|
directory
|
|
} = defineProps<{
|
|
displayName: string
|
|
huggingFaceUrl: string
|
|
docsUrl?: string
|
|
blogUrl?: string
|
|
hubSlug?: string
|
|
workflowCount: number
|
|
directory: string
|
|
}>()
|
|
|
|
const workflowsUrl = hubSlug
|
|
? `https://www.comfy.org/workflows/model/${hubSlug}`
|
|
: null
|
|
|
|
const dirDisplayMap: Record<string, string> = {
|
|
diffusion_models: 'Diffusion Model',
|
|
checkpoints: 'Checkpoint',
|
|
loras: 'LoRA',
|
|
controlnet: 'ControlNet',
|
|
clip_vision: 'CLIP Vision',
|
|
model_patches: 'Model Patch',
|
|
vae: 'VAE',
|
|
text_encoders: 'Text Encoder',
|
|
audio_encoders: 'Audio Encoder',
|
|
latent_upscale_models: 'Latent Upscale Model',
|
|
upscale_models: 'Upscale Model',
|
|
style_models: 'Style Model',
|
|
partner_nodes: 'Partner Node'
|
|
}
|
|
|
|
const eyebrow = dirDisplayMap[directory] ?? directory
|
|
const isPartnerNode = directory === 'partner_nodes'
|
|
</script>
|
|
|
|
<template>
|
|
<section
|
|
:class="
|
|
cn(
|
|
'mx-auto flex max-w-7xl flex-col gap-8 px-6 py-16',
|
|
'lg:flex-row lg:items-center lg:gap-16 lg:px-8 lg:py-24'
|
|
)
|
|
"
|
|
>
|
|
<div class="flex max-w-2xl flex-1 flex-col gap-6">
|
|
<p
|
|
class="text-sm font-medium uppercase tracking-widest text-primary-comfy-yellow"
|
|
>
|
|
{{ eyebrow }}
|
|
</p>
|
|
|
|
<h1 class="text-4xl font-bold text-primary-comfy-canvas lg:text-6xl">
|
|
{{ displayName }} in ComfyUI
|
|
</h1>
|
|
|
|
<p class="text-sm text-primary-comfy-canvas/60">
|
|
{{
|
|
t('models.hero.workflowCount').replace(
|
|
'{count}',
|
|
String(workflowCount)
|
|
)
|
|
}}
|
|
</p>
|
|
|
|
<div class="flex flex-col gap-3 sm:flex-row">
|
|
<BrandButton
|
|
v-if="workflowsUrl"
|
|
:href="workflowsUrl"
|
|
variant="solid"
|
|
size="lg"
|
|
class="w-full uppercase sm:w-auto sm:min-w-48"
|
|
>
|
|
{{ t('models.hero.primaryCta') }}
|
|
</BrandButton>
|
|
|
|
<BrandButton
|
|
v-if="!isPartnerNode && huggingFaceUrl"
|
|
:href="huggingFaceUrl"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
:variant="workflowsUrl ? 'outline' : 'solid'"
|
|
size="lg"
|
|
class="w-full uppercase sm:w-auto sm:min-w-48"
|
|
>
|
|
{{ t('models.hero.secondaryCta') }}
|
|
</BrandButton>
|
|
|
|
<BrandButton
|
|
v-if="!workflowsUrl"
|
|
href="https://www.comfy.org/cloud"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
:variant="huggingFaceUrl && !isPartnerNode ? 'outline' : 'solid'"
|
|
size="lg"
|
|
class="w-full uppercase sm:w-auto sm:min-w-48"
|
|
>
|
|
{{ t('models.hero.cloudCta') }}
|
|
</BrandButton>
|
|
|
|
<BrandButton
|
|
v-if="docsUrl"
|
|
:href="docsUrl"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
variant="outline"
|
|
size="lg"
|
|
class="w-full uppercase sm:w-auto sm:min-w-48"
|
|
>
|
|
{{ t('models.hero.tutorialCta') }}
|
|
</BrandButton>
|
|
</div>
|
|
|
|
<div v-if="blogUrl" class="text-sm text-primary-comfy-canvas/60">
|
|
<a
|
|
:href="blogUrl"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
class="hover:text-primary-comfy-canvas underline"
|
|
>
|
|
{{ t('models.hero.blogLink') }}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</template>
|