seo best practices

SEO Best Practices Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "seo best practices" with this command: npx skills add traxito/vibe_coding_skills/traxito-vibe-coding-skills-seo-best-practices

SEO Best Practices Skill

Complete SEO implementation for SaaS applications and modern web apps.

When to Use This Skill

  • Creating any public page (landing, pricing, blog, about)

  • Improving Google search rankings

  • Implementing rich snippets and social cards

  • Optimizing Core Web Vitals

  • Setting up structured data markup

  • Configuring sitemaps and robots.txt

Required Meta Tags

Every public page MUST include these meta tags for optimal SEO:

SEO Head Component (React/TypeScript)

// src/components/common/SEOHead.tsx import { Helmet } from 'react-helmet-async';

interface SEOProps { title: string; description: string; canonical?: string; image?: string; type?: 'website' | 'article' | 'product'; publishedTime?: string; modifiedTime?: string; author?: string; keywords?: string[]; noindex?: boolean; }

export default function SEOHead({ title, description, canonical, image = '/og-image.jpg', type = 'website', publishedTime, modifiedTime, author, keywords = [], noindex = false }: SEOProps) { const siteName = 'YourApp'; const fullTitle = ${title} | ${siteName}; const url = canonical || (typeof window !== 'undefined' ? window.location.href : ''); const fullImageUrl = image.startsWith('http') ? image : ${typeof window !== 'undefined' ? window.location.origin : ''}${image};

return ( <Helmet> {/* Basic Meta Tags */} <title>{fullTitle}</title> <meta name="description" content={description} /> {keywords.length > 0 && ( <meta name="keywords" content={keywords.join(', ')} /> )} <link rel="canonical" href={url} />

  {/* Robots */}
  {noindex &#x26;&#x26; &#x3C;meta name="robots" content="noindex, nofollow" />}

  {/* Open Graph (Facebook, LinkedIn) */}
  &#x3C;meta property="og:type" content={type} />
  &#x3C;meta property="og:title" content={title} />
  &#x3C;meta property="og:description" content={description} />
  &#x3C;meta property="og:url" content={url} />
  &#x3C;meta property="og:image" content={fullImageUrl} />
  &#x3C;meta property="og:image:width" content="1200" />
  &#x3C;meta property="og:image:height" content="630" />
  &#x3C;meta property="og:locale" content="en_US" />
  &#x3C;meta property="og:site_name" content={siteName} />

  {/* Twitter Cards */}
  &#x3C;meta name="twitter:card" content="summary_large_image" />
  &#x3C;meta name="twitter:title" content={title} />
  &#x3C;meta name="twitter:description" content={description} />
  &#x3C;meta name="twitter:image" content={fullImageUrl} />
  &#x3C;meta name="twitter:site" content="@yourapp" />
  &#x3C;meta name="twitter:creator" content="@yourapp" />

  {/* Article Meta Tags (for blog posts) */}
  {type === 'article' &#x26;&#x26; publishedTime &#x26;&#x26; (
    &#x3C;>
      &#x3C;meta property="article:published_time" content={publishedTime} />
      {modifiedTime &#x26;&#x26; (
        &#x3C;meta property="article:modified_time" content={modifiedTime} />
      )}
      {author &#x26;&#x26; &#x3C;meta property="article:author" content={author} />}
    &#x3C;/>
  )}

  {/* Mobile Optimization */}
  &#x3C;meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5" />
  &#x3C;meta name="theme-color" content="#000000" />
&#x3C;/Helmet>

); }

Usage Example:

// In any public page component <SEOHead title="Pricing Plans" description="Choose the perfect plan for your needs. Starting at $19/month." canonical="https://yourapp.com/pricing" keywords={['pricing', 'plans', 'subscription', 'saas pricing']} />

Schema.org Structured Data

Structured data helps search engines understand your content and display rich results.

  1. Landing Page (Organization + Website Schema)

// src/pages/Home.tsx export default function Home() { const organizationSchema = { "@context": "https://schema.org", "@type": "Organization", "name": "YourApp", "url": "https://www.yourapp.com", "logo": "https://www.yourapp.com/logo.png", "description": "Brief description of your SaaS product", "foundingDate": "2024", "founders": [ { "@type": "Person", "name": "Founder Name" } ], "contactPoint": { "@type": "ContactPoint", "email": "contact@yourapp.com", "contactType": "Customer Service", "availableLanguage": ["English", "Spanish"] }, "sameAs": [ "https://twitter.com/yourapp", "https://www.linkedin.com/company/yourapp", "https://github.com/yourapp" ] };

const websiteSchema = { "@context": "https://schema.org", "@type": "WebSite", "name": "YourApp", "url": "https://www.yourapp.com", "potentialAction": { "@type": "SearchAction", "target": { "@type": "EntryPoint", "urlTemplate": "https://www.yourapp.com/search?q={search_term_string}" }, "query-input": "required name=search_term_string" } };

return ( <> <SEOHead title="Home" description="Your SEO-optimized description here. Keep it under 160 characters." keywords={['saas', 'productivity', 'automation']} />

  {/* JSON-LD Structured Data */}
  &#x3C;script
    type="application/ld+json"
    dangerouslySetInnerHTML={{ __html: JSON.stringify(organizationSchema) }}
  />
  &#x3C;script
    type="application/ld+json"
    dangerouslySetInnerHTML={{ __html: JSON.stringify(websiteSchema) }}
  />

  {/* Page content */}
&#x3C;/>

); }

  1. Blog Post (Article Schema)

// src/pages/BlogPost.tsx interface BlogPostProps { post: { title: string; excerpt: string; slug: string; featuredImage: string; publishedAt: string; updatedAt: string; author: { name: string; slug: string; image: string; }; content: string; readingTime: number; }; }

export default function BlogPost({ post }: BlogPostProps) { const articleSchema = { "@context": "https://schema.org", "@type": "BlogPosting", "headline": post.title, "description": post.excerpt, "image": post.featuredImage, "datePublished": post.publishedAt, "dateModified": post.updatedAt, "author": { "@type": "Person", "name": post.author.name, "url": https://www.yourapp.com/author/${post.author.slug}, "image": post.author.image }, "publisher": { "@type": "Organization", "name": "YourApp", "logo": { "@type": "ImageObject", "url": "https://www.yourapp.com/logo.png" } }, "mainEntityOfPage": { "@type": "WebPage", "@id": https://www.yourapp.com/blog/${post.slug} }, "wordCount": post.content.split(' ').length, "timeRequired": PT${post.readingTime}M };

const breadcrumbSchema = { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [ { "@type": "ListItem", "position": 1, "name": "Home", "item": "https://www.yourapp.com" }, { "@type": "ListItem", "position": 2, "name": "Blog", "item": "https://www.yourapp.com/blog" }, { "@type": "ListItem", "position": 3, "name": post.title, "item": https://www.yourapp.com/blog/${post.slug} } ] };

return ( <> <SEOHead title={post.title} description={post.excerpt} canonical={https://www.yourapp.com/blog/${post.slug}} image={post.featuredImage} type="article" publishedTime={post.publishedAt} modifiedTime={post.updatedAt} author={post.author.name} />

  &#x3C;script
    type="application/ld+json"
    dangerouslySetInnerHTML={{ __html: JSON.stringify(articleSchema) }}
  />
  &#x3C;script
    type="application/ld+json"
    dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbSchema) }}
  />

  {/* Article content */}
  &#x3C;article>
    &#x3C;h1>{post.title}&#x3C;/h1>
    &#x3C;div dangerouslySetInnerHTML={{ __html: post.content }} />
  &#x3C;/article>
&#x3C;/>

); }

  1. Pricing Page (Product/Offer Schema)

// src/pages/Pricing.tsx export default function Pricing() { const plans = [ { name: 'Starter', price: 9.99, currency: 'USD', description: 'Perfect for individuals getting started' }, { name: 'Pro', price: 29.99, currency: 'USD', description: 'For professionals and small teams' }, { name: 'Enterprise', price: 99.99, currency: 'USD', description: 'Advanced features for large organizations' } ];

const productSchema = plans.map(plan => ({ "@context": "https://schema.org", "@type": "Product", "name": YourApp ${plan.name}, "description": plan.description, "brand": { "@type": "Brand", "name": "YourApp" }, "offers": { "@type": "Offer", "url": "https://www.yourapp.com/pricing", "priceCurrency": plan.currency, "price": plan.price.toString(), "priceValidUntil": "2026-12-31", "itemCondition": "https://schema.org/NewCondition", "availability": "https://schema.org/InStock", "seller": { "@type": "Organization", "name": "YourApp" } } }));

const faqSchema = { "@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [ { "@type": "Question", "name": "Can I cancel my subscription anytime?", "acceptedAnswer": { "@type": "Answer", "text": "Yes, you can cancel your subscription at any time with no penalties." } }, { "@type": "Question", "name": "Do you offer a free trial?", "acceptedAnswer": { "@type": "Answer", "text": "Yes, we offer a 14-day free trial for all plans. No credit card required." } } ] };

return ( <> <SEOHead title="Pricing Plans" description="Choose the perfect plan for your needs. Starting at $9.99/month. 14-day free trial available." canonical="https://www.yourapp.com/pricing" keywords={['pricing', 'plans', 'subscription', 'cost', 'free trial']} />

  {productSchema.map((schema, index) => (
    &#x3C;script
      key={index}
      type="application/ld+json"
      dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
    />
  ))}

  &#x3C;script
    type="application/ld+json"
    dangerouslySetInnerHTML={{ __html: JSON.stringify(faqSchema) }}
  />

  {/* Pricing content */}
&#x3C;/>

); }

  1. SaaS Software Application Schema

// For your main landing page const softwareAppSchema = { "@context": "https://schema.org", "@type": "SoftwareApplication", "name": "YourApp", "applicationCategory": "BusinessApplication", "operatingSystem": "Web, iOS, Android", "offers": { "@type": "Offer", "price": "9.99", "priceCurrency": "USD" }, "aggregateRating": { "@type": "AggregateRating", "ratingValue": "4.8", "ratingCount": "256" }, "screenshot": "https://www.yourapp.com/screenshots/dashboard.png" };

Dynamic Sitemap Generation

Sitemap Utility (TypeScript)

// src/utils/generateSitemap.ts import { collection, getDocs, query, where } from 'firebase/firestore'; import { db } from '@/lib/firebase';

interface SitemapEntry { loc: string; lastmod?: string; changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'; priority?: number; }

export async function generateSitemap(): Promise<string> { const baseUrl = 'https://www.yourapp.com';

// Static pages const staticPages: SitemapEntry[] = [ { loc: '/', changefreq: 'weekly', priority: 1.0 }, { loc: '/pricing', changefreq: 'monthly', priority: 0.9 }, { loc: '/features', changefreq: 'monthly', priority: 0.8 }, { loc: '/blog', changefreq: 'daily', priority: 0.9 }, { loc: '/about', changefreq: 'monthly', priority: 0.6 }, { loc: '/contact', changefreq: 'monthly', priority: 0.6 }, { loc: '/privacy-policy', changefreq: 'yearly', priority: 0.3 }, { loc: '/terms-of-service', changefreq: 'yearly', priority: 0.3 } ];

// Dynamic blog posts const postsQuery = query( collection(db, 'blog-posts'), where('published', '==', true) ); const postsSnapshot = await getDocs(postsQuery);

const blogPosts: SitemapEntry[] = postsSnapshot.docs.map(doc => { const data = doc.data(); return { loc: /blog/${data.slug}, lastmod: data.updatedAt?.toDate().toISOString() || new Date().toISOString(), changefreq: 'monthly', priority: 0.7 }; });

// Dynamic category pages (if applicable) const categoriesSnapshot = await getDocs(collection(db, 'categories')); const categoryPages: SitemapEntry[] = categoriesSnapshot.docs.map(doc => ({ loc: /category/${doc.data().slug}, changefreq: 'weekly', priority: 0.6 }));

const allPages = [...staticPages, ...blogPosts, ...categoryPages];

// Generate XML const sitemap = &#x3C;?xml version="1.0" encoding="UTF-8"?> &#x3C;urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"> ${allPages.map(page => <url> <loc>${baseUrl}${page.loc}</loc> ${page.lastmod ? &#x3C;lastmod>${page.lastmod}&#x3C;/lastmod> : ''} ${page.changefreq ? &#x3C;changefreq>${page.changefreq}&#x3C;/changefreq> : ''} ${page.priority !== undefined ? &#x3C;priority>${page.priority.toFixed(1)}&#x3C;/priority> : ''} </url>).join('\n')} &#x3C;/urlset>;

return sitemap; }

Server-side Sitemap Endpoint (Express/Node.js)

// api/sitemap.ts (Vercel/Netlify Functions) import { generateSitemap } from '../utils/generateSitemap';

export default async function handler(req: any, res: any) { try { const xml = await generateSitemap();

res.setHeader('Content-Type', 'application/xml');
res.setHeader('Cache-Control', 'public, max-age=3600, s-maxage=3600');
res.status(200).send(xml);

} catch (error) { console.error('Error generating sitemap:', error); res.status(500).json({ error: 'Failed to generate sitemap' }); } }

Firebase Cloud Function Sitemap

// functions/src/sitemap.ts import * as functions from 'firebase-functions'; import { generateSitemap } from './utils/generateSitemap';

export const sitemap = functions.https.onRequest(async (req, res) => { try { const xml = await generateSitemap();

res.set('Content-Type', 'application/xml');
res.set('Cache-Control', 'public, max-age=3600');
res.status(200).send(xml);

} catch (error) { console.error('Error generating sitemap:', error); res.status(500).send('Error generating sitemap'); } });

robots.txt Configuration

public/robots.txt

Allow all crawlers

User-agent: * Allow: /

Block private pages

Disallow: /dashboard Disallow: /dashboard/* Disallow: /settings Disallow: /settings/* Disallow: /admin Disallow: /admin/* Disallow: /api/*

Block sensitive paths

Disallow: /auth/ Disallow: /checkout/ Disallow: /*.json$

Sitemap location

Sitemap: https://www.yourapp.com/sitemap.xml

Crawl delay (optional, use if server load is an issue)

Crawl-delay: 10

Core Web Vitals Optimization

  1. Image Optimization

// Always use optimized images with proper attributes

// ✅ CORRECT: Modern image with lazy loading <img src="/images/hero.webp" alt="Descriptive alt text for SEO" loading="lazy" width={1200} height={630} decoding="async" />

// ✅ BETTER: Responsive images with srcset <img srcSet="/images/hero-320w.webp 320w, /images/hero-640w.webp 640w, /images/hero-1280w.webp 1280w" sizes="(max-width: 640px) 320px, (max-width: 1280px) 640px, 1280px" src="/images/hero-1280w.webp" alt="Descriptive alt text" loading="lazy" width={1280} height={720} />

// ✅ BEST: Next.js Image component (automatic optimization) import Image from 'next/image';

<Image src="/images/hero.jpg" alt="Descriptive alt text" width={1200} height={630} priority={false} // true for above-the-fold images placeholder="blur" blurDataURL="data:image/jpeg;base64,..." />

  1. Code Splitting by Routes

// src/router.tsx import { lazy, Suspense } from 'react'; import { BrowserRouter, Routes, Route } from 'react-router-dom'; import LoadingSpinner from '@/components/common/LoadingSpinner';

// ✅ Lazy load routes for better initial load performance const Home = lazy(() => import('@/pages/public/Home')); const Pricing = lazy(() => import('@/pages/public/Pricing')); const Blog = lazy(() => import('@/pages/public/Blog')); const BlogPost = lazy(() => import('@/pages/public/BlogPost')); const Dashboard = lazy(() => import('@/pages/dashboard/Dashboard')); const Features = lazy(() => import('@/pages/public/Features'));

export default function Router() { return ( <BrowserRouter> <Suspense fallback={<LoadingSpinner />}> <Routes> <Route path="/" element={<Home />} /> <Route path="/pricing" element={<Pricing />} /> <Route path="/features" element={<Features />} /> <Route path="/blog" element={<Blog />} /> <Route path="/blog/:slug" element={<BlogPost />} /> <Route path="/dashboard/*" element={<Dashboard />} /> </Routes> </Suspense> </BrowserRouter> ); }

  1. Preload Critical Resources

// src/main.tsx or index.html import { createRoot } from 'react-dom/client';

// Preload critical fonts const preloadFont = (href: string) => { const link = document.createElement('link'); link.rel = 'preload'; link.as = 'font'; link.type = 'font/woff2'; link.href = href; link.crossOrigin = 'anonymous'; document.head.appendChild(link); };

preloadFont('/fonts/Inter-var.woff2'); preloadFont('/fonts/Inter-Bold.woff2');

// Preconnect to external domains const preconnect = (href: string) => { const link = document.createElement('link'); link.rel = 'preconnect'; link.href = href; document.head.appendChild(link); };

preconnect('https://fonts.googleapis.com'); preconnect('https://cdn.yourcdn.com');

createRoot(document.getElementById('root')!).render(<App />);

  1. Vite Build Optimization

// vite.config.ts import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import { visualizer } from 'rollup-plugin-visualizer';

export default defineConfig({ plugins: [ react(), visualizer({ open: true }) // Analyze bundle size ], build: { rollupOptions: { output: { // Manual chunk splitting for optimal caching manualChunks: { 'react-vendor': ['react', 'react-dom', 'react-router-dom'], 'firebase-vendor': ['firebase/app', 'firebase/auth', 'firebase/firestore', 'firebase/storage'], 'ui-vendor': ['lucide-react', 'sonner', '@radix-ui/react-dialog'], 'form-vendor': ['react-hook-form', 'zod', '@hookform/resolvers'] } } }, chunkSizeWarningLimit: 1000, minify: 'terser', terserOptions: { compress: { drop_console: true, // Remove console.log in production drop_debugger: true } } }, optimizeDeps: { include: ['react', 'react-dom', 'react-router-dom'] } });

  1. Next.js Configuration for Performance

// next.config.js /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, swcMinify: true,

// Image optimization images: { formats: ['image/webp', 'image/avif'], deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840], imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], },

// Compression compress: true,

// Headers for caching async headers() { return [ { source: '/:all*(svg|jpg|png|webp|avif)', headers: [ { key: 'Cache-Control', value: 'public, max-age=31536000, immutable', }, ], }, ]; }, };

module.exports = nextConfig;

  1. Performance Monitoring Component

// src/components/PerformanceMonitor.tsx import { useEffect } from 'react';

export default function PerformanceMonitor() { useEffect(() => { // Measure Core Web Vitals if (typeof window !== 'undefined' && 'web-vitals' in window) { import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { getCLS(console.log); getFID(console.log); getFCP(console.log); getLCP(console.log); getTTFB(console.log); }); }

// Log performance metrics
if (window.performance) {
  const perfData = window.performance.timing;
  const pageLoadTime = perfData.loadEventEnd - perfData.navigationStart;
  console.log(`Page load time: ${pageLoadTime}ms`);
}

}, []);

return null; }

// Add to your App component function App() { return ( <> <PerformanceMonitor /> {/* Rest of your app */} </> ); }

SEO Pre-Deploy Checklist

Meta Tags & Structured Data

  • All pages have unique <title> tags (50-60 characters)

  • All pages have unique meta descriptions (150-160 characters)

  • Canonical URLs set on all pages

  • Open Graph tags implemented (title, description, image, url)

  • Twitter Card tags implemented

  • Schema.org markup on homepage (Organization/WebSite)

  • Schema.org markup on blog posts (Article)

  • Schema.org markup on pricing (Product/Offer)

  • Breadcrumb schema on inner pages

  • FAQ schema where applicable

Technical SEO

  • sitemap.xml generated and accessible

  • robots.txt configured correctly

  • All images have descriptive alt text

  • Images optimized (WebP/AVIF format)

  • Lazy loading implemented for below-fold images

  • HTTPS enabled site-wide

  • 404 page exists and is helpful

  • Redirects (301) set up for changed URLs

  • No broken internal links

  • Mobile-responsive design verified

Performance

  • Lighthouse score > 90 on mobile

  • Lighthouse score > 95 on desktop

  • LCP (Largest Contentful Paint) < 2.5s

  • FID (First Input Delay) < 100ms

  • CLS (Cumulative Layout Shift) < 0.1

  • Code splitting implemented

  • Critical CSS inlined

  • Fonts preloaded

  • External resources preconnected

Analytics & Monitoring

  • Google Search Console configured

  • Google Analytics 4 installed

  • Core Web Vitals tracking enabled

  • Conversion tracking set up

  • Error tracking configured (Sentry, etc.)

Content

  • H1 tag on every page (only one per page)

  • Proper heading hierarchy (H1 → H2 → H3)

  • Internal linking strategy implemented

  • Blog content plan created

  • Target keywords researched

  • Content length adequate (1000+ words for pillar content)

Tools & Testing

Testing Your SEO Implementation

1. Test with Lighthouse (Chrome DevTools)

Open DevTools → Lighthouse → Run audit

2. Check structured data

Visit: https://search.google.com/test/rich-results

Enter your URL

3. Validate sitemap

Visit: https://www.xml-sitemaps.com/validate-xml-sitemap.html

4. Check mobile-friendliness

Visit: https://search.google.com/test/mobile-friendly

5. Analyze Core Web Vitals

Visit: https://pagespeed.web.dev/

Recommended Tools

SEO Analysis:

  • Ahrefs - Comprehensive SEO toolset

  • SEMrush - Keyword research & competitor analysis

  • Moz - Domain authority tracking

  • Screaming Frog - Technical SEO crawler

Performance:

  • Lighthouse - Built into Chrome DevTools

  • WebPageTest - Detailed performance analysis

  • GTmetrix - Performance & optimization recommendations

  • Google PageSpeed Insights - Core Web Vitals

Schema Testing:

  • Google Rich Results Test

  • Schema Markup Validator

  • JSON-LD Playground

Common SEO Mistakes to Avoid

❌ Don't Do This:

  • Duplicate title tags across multiple pages

  • Missing alt text on images

  • Blocking CSS/JS in robots.txt

  • Slow page load times (> 3 seconds)

  • Non-responsive design on mobile

  • Broken links (404 errors)

  • Thin content (< 300 words on important pages)

  • Keyword stuffing in meta tags or content

  • Using only h1 tags or skipping heading levels

  • Not setting canonical URLs (causes duplicate content issues)

✅ Best Practices:

  • Write unique, descriptive titles for each page

  • Create compelling meta descriptions that encourage clicks

  • Optimize images (compress, use modern formats, add alt text)

  • Implement proper URL structure (readable, hierarchical)

  • Create high-quality content that answers user questions

  • Build internal links to important pages

  • Update content regularly to keep it fresh

  • Monitor and fix errors in Google Search Console

  • Use HTTPS everywhere

  • Focus on user experience first, SEO second

Resources

Summary

This SEO skill provides everything needed to implement comprehensive SEO for modern SaaS applications:

  • Meta tags for social sharing and search engines

  • Structured data (Schema.org) for rich results

  • Dynamic sitemap generation

  • Performance optimization for Core Web Vitals

  • Complete checklist for pre-deploy verification

Apply these practices consistently across all public pages to maximize organic search visibility.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

seo-best-practices

No summary provided by upstream source.

Repository SourceNeeds Review
General

seo-best-practices

No summary provided by upstream source.

Repository SourceNeeds Review
General

image-gen

Generate AI images from text prompts. Triggers on: "生成图片", "画一张", "AI图", "generate image", "配图", "create picture", "draw", "visualize", "generate an image".

Archived SourceRecently Updated
General

explainer

Create explainer videos with narration and AI-generated visuals. Triggers on: "解说视频", "explainer video", "explain this as a video", "tutorial video", "introduce X (video)", "解释一下XX(视频形式)".

Archived SourceRecently Updated