diff --git a/config/docs.ts b/config/docs.ts index 1ace3bc3..c5f7700b 100644 --- a/config/docs.ts +++ b/config/docs.ts @@ -59,6 +59,11 @@ const sidebarNav: SidebarNavItem[] = [ href: "/docs/guides/animated-react-buttons", items: [], }, + { + title: "Animated React Text Effects", + href: "/docs/guides/animated-react-text-effects", + items: [], + }, ], }, { diff --git a/content/docs/changelog/2026-09.mdx b/content/docs/changelog/2026-09.mdx index 494fdd9b..b0e9f2bd 100644 --- a/content/docs/changelog/2026-09.mdx +++ b/content/docs/changelog/2026-09.mdx @@ -1,11 +1,13 @@ --- title: September 2026 -description: Homepage conversion fixes for GitHub stars and newsletter subscribe. +description: Homepage conversion fixes plus SEO guides comparing animated React kits and text effects. date: 2026-09-01 --- Tightened the homepage conversion path for GitHub stars and email subscribe: clearer asks, equal hero CTAs, an earlier newsletter block, a header star badge, and tracked subscribe/star events in PostHog. +Published an [Aceternity UI vs Magic UI vs Animata](/blog/aceternity-ui-vs-magic-ui-vs-animata) comparison and a [Top Animated React Text Effects (2026)](/docs/guides/animated-react-text-effects) guide for search and answer-engine discovery. + ## Site Rewrote star CTAs to lead with why (“Star to follow releases”), made the hero star control a full-size button on mobile, and replaced the icon-only header GitHub link with a visible Star · count pill. @@ -13,3 +15,9 @@ Rewrote star CTAs to lead with why (“Star to follow releases”), made the her Moved the featured newsletter up (after open source), added a “Just starred?” bridge to email, and made footer/exit-intent subscribe controls use a visible Subscribe button with risk-reversal copy. Made exit intent email-first and added mobile scroll-depth and time-on-page triggers. Hardened the stars ticker so it shows the real count on first paint instead of a `0,000+` flash. Added `newsletter_subscribe` and `github_star_click` PostHog events so conversion can be measured against home sessions. + +## Docs & blog + +Added a neutral surface-based comparison of Aceternity UI, Magic UI, and Animata (landing vs product UI, free tiers, Motion, accessibility, mixing with shadcn). + +Added a curated text-effects guide covering ten MIT presets with registry installs, Motion vs CSS guidance, accessibility notes, and ecosystem context. diff --git a/content/docs/changelog/index.mdx b/content/docs/changelog/index.mdx index a54b2f95..dc47a5b4 100644 --- a/content/docs/changelog/index.mdx +++ b/content/docs/changelog/index.mdx @@ -12,7 +12,7 @@ New components, bug fixes, and infrastructure changes, going back to the beta la ### [September 2026](/docs/changelog/2026-09) -Homepage conversion fixes for GitHub stars and newsletter subscribe — equal hero CTAs, earlier email opt-in, header Star pill, ticker first-paint fix, and PostHog conversion events. +Homepage conversion fixes for GitHub stars and newsletter subscribe — equal hero CTAs, earlier email opt-in, header Star pill, ticker first-paint fix, and PostHog conversion events. Published [Aceternity UI vs Magic UI vs Animata](/blog/aceternity-ui-vs-magic-ui-vs-animata) and [Top Animated React Text Effects](/docs/guides/animated-react-text-effects). ### [June 2026](/docs/changelog/2026-06) diff --git a/content/docs/guides/animated-react-text-effects.mdx b/content/docs/guides/animated-react-text-effects.mdx new file mode 100644 index 00000000..0f5923b3 --- /dev/null +++ b/content/docs/guides/animated-react-text-effects.mdx @@ -0,0 +1,252 @@ +--- +title: "Top Animated React Text Effects (2026)" +description: "Curated animated React text effects for Tailwind — typewriter, split, gradient, flip, and scroll reveals. Copy-paste or shadcn registry; MIT; a11y-minded." +seoTitle: "Top Animated React Text Effects (2026) — Copy-Paste Tailwind Components" +seoDescription: "Ten animated React text effects for Tailwind: typewriter, wave reveal, flip, gradient, split, scroll reveal, circular, glitch, gibberish, and shimmer. MIT copy-paste or shadcn registry." +date: 2026-09-14 +dateModified: 2026-09-14 +toc: true +published: true +labels: + - Guide + - Text + - React + - Tailwind +--- + +Start by picking one text preset, installing it via registry or paste, verifying reduced-motion behavior, then shipping. Rebuild SplitText in Motion or GSAP only when the brief needs a custom letter timeline. + +[Animata](https://animata.design/docs/text) is the copy-own lane for that: MIT text presets, registry installs, and accessibility patterns (sr-only full strings, aria-hidden decorative layers, reduced-motion hooks) documented before you copy. Many presets use the Web Animations API (WAAPI) via a shared `text-animator` runtime; others are plain React state, CSS keyframes, or Motion when scroll or continuous layout motion needs it. This guide is the text sibling of Animata's [animated React buttons](https://animata.design/docs/guides/animated-react-buttons) guide—practical, fair to the rest of the ecosystem, and clear about Motion versus CSS. + +Worth knowing up front: not every Animata text effect needs Motion, and Motion is not ruled out either. Typing Text, Wave Reveal, Text Flip, and several others are CSS/React/WAAPI; Scroll Reveal and Circular Text require Motion. Setup states Motion is optionally required for some complex animations ([docs/setup](https://animata.design/docs/setup); per-component docs under [docs/text](https://animata.design/docs/text)). Component counts can also drift—homepage **155+** ([animata.design](https://animata.design/)) versus agent catalog **~130** at [llms.txt](https://animata.design/llms.txt)—prefer the live page at publish. And "copy-paste" / registry means you own the source: edit timing, tokens, and copy freely. + +## How to choose + +Match the job to the stack before you paste. Effects fail when the interaction model does not match the surface—for example, a hover-only split on a mobile hero, or Motion for a gradient clip that CSS already handles. + +| Job | Pick | Avoid when | +| --- | --- | --- | +| Typewriter / terminal / AI "thinking" copy | [Typing Text](https://animata.design/docs/text/typing-text) | You need scroll-scrubbed typography—use Scroll Reveal or Motion/GSAP instead | +| Letter/word entrance with optional blur | [Wave Reveal](https://animata.design/docs/text/wave-reveal) | You refuse to add the docs' `@keyframes` / `@theme` snippet | +| Cycling headline words | [Text Flip](https://animata.design/docs/text/text-flip) | You need physics-grade letter trails—reach for Motion/GSAP custom SplitText | +| Brand gradient accent on a label | [Animated Gradient Text](https://animata.design/docs/text/animated-gradient-text) | The effect must track scroll progress (gradient ≠ scroll reveal) | +| Hover split / letter drama | [Split Text](https://animata.design/docs/text/split-text) | Touch-first surfaces with no hover—plan a static fallback | +| Scroll-linked opacity on copy | [Scroll Reveal](https://animata.design/docs/text/scroll-reveal) | You want zero Motion dependency | +| Rotating circular path lockups | [Circular Text](https://animata.design/docs/text/circular-text) | Continuous loops without a reduced-motion plan | +| RGB glitch / high-contrast display type | [Glitch Text](https://animata.design/docs/text/glitch-text) | Body-scale copy (the effect is for display type) | +| Decode / "AI reveal" from noise | [Gibberish Text](https://animata.design/docs/text/gibberish-text) | You need scroll-driven choreography | +| Continuous marketing shimmer / WAAPI preset | [Shimmer Sweep](https://animata.design/docs/text/shimmer-sweep) | You cannot accept the shared `text-animator` runtime (or looping motion without a fallback) | + +## Ten paste-ready picks + +Each one is MIT, documented, and installable with the registry URL under the pick. Browse the full category when you are done: [animata.design/docs/text](https://animata.design/docs/text). + +### 1. Typing Text + +Classic typewriter for heroes, empty states, and AI product chrome. It drives the caret with React state and effects—cursor blink, smooth word mode, repeat/wait—so you get a readable loop without a Motion dependency. Own the file and tune timing to your brand voice. Reach for it on hero typewriters, CLI-style marketing, onboarding prompts, and "generating…" affordances. + +Docs: [Typing Text](https://animata.design/docs/text/typing-text) + +```bash +pnpm dlx shadcn@latest add https://animata.design/r/text/typing-text.json +``` + +### 2. Wave Reveal + +Letter- or word-by-word entrance with an optional blur. Animation is CSS (`reveal-up` / `reveal-down` / `content-blur`); the component also ships an `sr-only` copy of the full string so assistive tech gets the message once while glyphs animate visually. Paste the `@keyframes` / `@theme` block from the docs—skip that and the entrance never runs. + +Strong on section titles, feature intros, and headline entrances. [Wave Reveal docs](https://animata.design/docs/text/wave-reveal). + +```bash +pnpm dlx shadcn@latest add https://animata.design/r/text/wave-reveal.json +``` + +### 3. Text Flip + +Cycling headline words via CSS `flip-words` keyframes—swap "Ship / Scale / Iterate" without orchestrating Motion timelines. React owns the word list; CSS owns the flip. No Motion package required. + +Use it for rotating value props, short marketing phrases, and hero subheads. [Text Flip docs](https://animata.design/docs/text/text-flip). + +```bash +pnpm dlx shadcn@latest add https://animata.design/r/text/text-flip.json +``` + +### 4. Animated Gradient Text + +Tailwind gradient clip plus CSS keyframes for a brand accent that moves. Lean stack: no animation engine, just utilities and a small keyframe loop you can theme. Product names, badge labels, pricing highlights, light marketing accents—this is the quiet polish pick. + +[Animated Gradient Text docs](https://animata.design/docs/text/animated-gradient-text) + +```bash +pnpm dlx shadcn@latest add https://animata.design/r/text/animated-gradient-text.json +``` + +### 5. Split Text + +Hover split drama: letters open vertically around the pointer with neighborhood falloff. Decorative letter layers are `aria-hidden`; an invisible sizing layer keeps layout stable. This is pointer-dependent—pair with a static (non-hover) presentation on touch-first layouts. Desktop marketing lockups and playful brand moments only; do not make critical copy hover-gated. + +[Split Text docs](https://animata.design/docs/text/split-text) + +```bash +pnpm dlx shadcn@latest add https://animata.design/r/text/split-text.json +``` + +### 6. Scroll Reveal + +Scroll-linked opacity on flattened children—sticky copy that brightens as the user scrolls the container. This one **requires Motion** (`motion/react`) and is honest about it: scroll progress values are Motion's job. Long-form storytelling, manifesto blocks, product narratives. + +[Scroll Reveal docs](https://animata.design/docs/text/scroll-reveal) + +```bash +pnpm dlx shadcn@latest add https://animata.design/r/text/scroll-reveal.json +``` + +### 7. Circular Text + +Rotating circular-path lockups for badges, seals, and "scroll for more" chrome. Continuous loops look great in demos—respect `prefers-reduced-motion` so the ring does not spin forever for every user. **Requires Motion**. + +[Circular Text docs](https://animata.design/docs/text/circular-text) + +```bash +pnpm dlx shadcn@latest add https://animata.design/r/text/circular-text.json +``` + +### 8. Glitch Text + +RGB-split glitch: magenta/cyan ghosts jitter while the base label stays sharp and readable. Ghosts are `aria-hidden`; co-located CSS includes `@media (prefers-reduced-motion: reduce)` so ghosts stop and fade. The CLI installs the TSX component and co-located CSS together. Keep it on display type—404s, high-contrast marketing, error/status labels—not body copy. + +[Glitch Text docs](https://animata.design/docs/text/glitch-text) + +```bash +pnpm dlx shadcn@latest add https://animata.design/r/text/glitch-text.json +``` + +### 9. Gibberish Text + +Decode from gibberish into real copy—useful for demos, generative UIs, and launch teasers. Implemented with React intervals, not a Motion timeline. Fast to own; easy to overuse. One moment per screen is usually enough. + +[Gibberish Text docs](https://animata.design/docs/text/gibberish-text) + +```bash +pnpm dlx shadcn@latest add https://animata.design/r/text/gibberish-text.json +``` + +### 10. Shimmer Sweep + +A WAAPI text-animator runtime preset: soft left-to-center shimmer for continuous marketing motion. The CLI pulls the shared `text-animator` runtime (and CSS) used by other text presets—budget that shared dependency once, reuse across the category. Continuous loops still need a reduced-motion story in your app shell. Not the Motion package—WAAPI. + +[Shimmer Sweep docs](https://animata.design/docs/text/shimmer-sweep) + +```bash +pnpm dlx shadcn@latest add https://animata.design/r/text/shimmer-sweep.json +``` + +Want more than these ten? The full text hub has the broader preset set (kinetic builds, shared-axis slides, underlines, counters, and more): **[Browse all text effects →](https://animata.design/docs/text)** + +## Install + +1. **Setup once:** [animata.design/docs/setup](https://animata.design/docs/setup) — Tailwind, `cn` (`clsx` + `tailwind-merge`), Motion optional when a component needs it. +2. **Registry (example):** + +```bash +pnpm dlx shadcn@latest add https://animata.design/r/text/typing-text.json +``` + +3. **Manual path:** files land under `components/animata/text/` (or the path your docs paste block uses). Own the source—edit timing, tokens, and copy. +4. **CSS extras:** some effects need global `@keyframes` / `@theme` (Wave Reveal, Text Flip-style keyframes). Others ship co-located CSS (Glitch Text; `text-animator.css` for WAAPI presets). Follow the component docs—do not assume every text file is Tailwind-only. + +Browse the catalog anytime: [animata.design/components](https://animata.design/components). Agents can also use the agent catalog linked above. + +## Motion vs CSS — when you need which + +Pick the lightest stack that does the job. + +CSS keyframes and Tailwind transitions are enough for flips, gradient clips, many reveals, glitch layers, and hover splits. Prefer them when the effect is decorative, local, and does not need scroll progress or layout measurement. + +WAAPI (`text-animator`) powers a family of Animata text presets—shared runtime, compositor-friendly loops, no Motion package. Useful for marketing cycles; still treat infinite loops as a reduced-motion concern. + +Reach for Motion (`motion/react`) when you need scroll-linked values, continuous path motion, or sequenced layout that CSS cannot express cleanly. Scroll Reveal and Circular Text are the clear examples in this list. + +Motion or GSAP for custom SplitText remains the right tool when you are authoring bespoke letter timelines, scrubbed pin scenes, or Club-level SplitText pipelines. Kits give you product-ready presets; they do not replace a custom Motion or GSAP SplitText build when that is the actual job. See [Motion's React Split Text example](https://motion.dev/examples/react-split-text) when you outgrow presets. + +Animata's posture matches the rest of the product kit: Motion optional for complex pieces—not "zero Motion forever," and not Motion for every label. + +## Accessibility and reduced motion + +Animated text fails quietly when decorative layers steal the accessible name, hover is the only affordance, or loops ignore `prefers-reduced-motion`. + +Wave Reveal keeps a full `sr-only` string beside animated glyphs—screen readers get the sentence once. Split Text marks decorative letter wrappers `aria-hidden` and uses an invisible sizing layer; still plan a non-hover static state for touch. Glitch Text exposes the base layer to assistive tech, hides RGB ghosts with `aria-hidden`, and disables ghost animation under `prefers-reduced-motion: reduce`. + +Hover-only effects (Split Text and similar) fail on touch—do not ship them as the only presentation of critical copy. Continuous loops (Circular Text, Shimmer Sweep, cycling flips) need reduced-motion fallbacks: pause, static first phrase, or CSS `animation: none` / Motion `useReducedMotion` in your shell. + +Accessibility is part of the paste surface—not a later ticket. + +## How this compares + +Short takes. These kits are strong; pick by surface. + +### Aceternity — cinematic text + +[Aceternity UI](https://ui.aceternity.com/components) remains a strong cinematic landing kit: heroes, shaders, and high-impact Motion text like [Text Generate Effect](https://ui.aceternity.com/components/text-generate-effect). Reach for it when the job is first-impression marketing motion—Animata text is aimed at a different surface. After paste, accessibility and bundle weight are yours to audit—same as any marketing kit. + +### Magic UI — TextAnimate + +[Magic UI TextAnimate](https://magicui.design/docs/components/text-animate) is polished Design Engineer marketing motion next to shadcn—blur/slide/scale presets, custom Motion variants, and an `accessible` screen-reader label option. Strong for landing micro-interactions; still verify reduced-motion and product-chrome fit the same way you would for any Motion-forward marketing component. + +### React Bits — kinetic gallery + +[React Bits](https://reactbits.dev) keeps expanding animated React experiments and production-leaning pieces. Worth browsing when you want kinetic variety beyond a single kit's opinion. + +### shadcn.io/text — freemium gallery + +[shadcn.io/text](https://www.shadcn.io/text) is a freemium text-effect gallery in the broader shadcn orbit. Useful for exploration; check license/tier per component before you treat it like an MIT copy-own library. + +### Cult UI + Motiq + +[Cult UI](https://cult-ui.com) sits in adjacent design-system craft. [Motiq](https://motiq.dev) belongs in the accessibility / reduced-motion conversation for motion-minded teams. Neither replaces a full text-preset catalog, but both are fair neighbors on a shortlist. + +### Motion / GSAP — build your own + +When presets are not enough, build: [Motion SplitText](https://motion.dev/examples/react-split-text) or GSAP SplitText for custom letter choreography. Kits accelerate shipping; engines win for bespoke timelines. + +## When not to use these Animata picks + +You need Aceternity-scale cinematic heroes / shaders? Use Aceternity (and similar kits) for that surface; Animata text is product-ready polish, not a full cinematic landing catalog. You specifically want Magic's TextAnimate catalog next to shadcn marketing? Use Magic for that Design Engineer marketing lane; mix kits by surface if needed. + +Every effect must be zero-Motion and zero-WAAPI? Scroll Reveal, Circular Text, and WAAPI presets will not fit that constraint—pick CSS-only entries or hand-roll. Critical copy depends on hover? Split-style drama is decorative; keep readable static text for touch and assistive tech. You need a full form/data primitive system? Start with [shadcn/ui](https://ui.shadcn.com/), then layer text motion where it helps. + +## FAQ + +### Are Animata text effects free / MIT? + +Yes. Animata's core library is **MIT, free forever**—**155+** components on the homepage copy-own model ([animata.design](https://animata.design/)). No paid tier required for these text presets. Treat sitewide counts as verify-at-publish (homepage versus agent-catalog drift noted above). + +### Do I need Motion for every text effect? + +No. Typing Text, Wave Reveal, Text Flip, Animated Gradient Text, Split Text, Glitch Text, Gibberish Text, and Shimmer Sweep (WAAPI) do not require the Motion package. **Scroll Reveal** and **Circular Text** do. Install Motion when the docs say so. + +### Does this work with Next.js and Vite? + +Yes. Animata targets modern React stacks including Next.js, Vite, Remix, Astro, Gatsby, and TanStack—see [setup](https://animata.design/docs/setup). Client components (`"use client"`) apply where hooks or browser APIs are used. + +### Can I build a typewriter in React with Tailwind without a package? + +Yes—and that is exactly [Typing Text](https://animata.design/docs/text/typing-text): React state/effects + Tailwind, registry or paste, no Motion. You own the file after install. + +### Split text without GSAP Club—GSAP vs Motion vs a kit component? + +**Kit component:** Animata [Split Text](https://animata.design/docs/text/split-text) for hover split drama you own (pointer-dependent; accessibility pattern documented). **Motion:** use [Motion's SplitText example](https://motion.dev/examples/react-split-text) when you need custom letter timelines without GSAP Club. **GSAP SplitText:** still excellent for scrubbed, Club-level letter pipelines—reach for it when the creative brief needs that engine, not when a kit preset already covers the job. + +### How should I handle reduced motion? + +Honor `prefers-reduced-motion`. Prefer components that already wire fallbacks (Glitch Text CSS; Wave Reveal's `sr-only` string). For continuous loops (Circular Text, Shimmer Sweep, cycling flips), pause or render static copy. Hover-only splits need a non-hover presentation. + +## Next steps + +1. [Text category overview](https://animata.design/docs/text) — full preset list (WAAPI called out for many presets). +2. [Setup](https://animata.design/docs/setup) — Tailwind, `cn`, Motion optional. +3. [Animated React buttons guide](https://animata.design/docs/guides/animated-react-buttons) — same copy-own pattern for CTAs. +4. [Browse all components](https://animata.design/components) — buttons, cards, scroll, text, and more. +5. [Aceternity UI vs Magic UI vs Animata](/blog/aceternity-ui-vs-magic-ui-vs-animata) — when to use each kit by surface. + +Ship one high-traffic headline first, verify reduced-motion and assistive tech, then expand. Own the files after install. diff --git a/lib/metadata.ts b/lib/metadata.ts index 680fe0ca..c7d667ee 100644 --- a/lib/metadata.ts +++ b/lib/metadata.ts @@ -241,21 +241,36 @@ function buildBreadcrumbJsonLd(doc: PublishedDoc) { } function buildGuideItemListJsonLd(doc: PublishedDoc, description: string) { - if (doc.slugAsParams !== "guides/animated-react-buttons") { + const guideLists: Record> = { + "guides/animated-react-buttons": [ + { name: "AI Button", url: "/docs/button/ai-button" }, + { name: "Duolingo Button", url: "/docs/button/duolingo" }, + { name: "Ripple Button", url: "/docs/button/ripple-button" }, + { name: "Shining Button", url: "/docs/button/shining-button" }, + { name: "Swipe Button", url: "/docs/button/swipe-button" }, + { name: "Status Button", url: "/docs/button/status-button" }, + { name: "Animated Follow Button", url: "/docs/button/animated-follow-button" }, + { name: "Get Started Button", url: "/docs/button/get-started-button" }, + ], + "guides/animated-react-text-effects": [ + { name: "Typing Text", url: "/docs/text/typing-text" }, + { name: "Wave Reveal", url: "/docs/text/wave-reveal" }, + { name: "Text Flip", url: "/docs/text/text-flip" }, + { name: "Animated Gradient Text", url: "/docs/text/animated-gradient-text" }, + { name: "Split Text", url: "/docs/text/split-text" }, + { name: "Scroll Reveal", url: "/docs/text/scroll-reveal" }, + { name: "Circular Text", url: "/docs/text/circular-text" }, + { name: "Glitch Text", url: "/docs/text/glitch-text" }, + { name: "Gibberish Text", url: "/docs/text/gibberish-text" }, + { name: "Shimmer Sweep", url: "/docs/text/shimmer-sweep" }, + ], + }; + + const items = guideLists[doc.slugAsParams]; + if (!items) { return null; } - const items = [ - { name: "AI Button", url: "/docs/button/ai-button" }, - { name: "Duolingo Button", url: "/docs/button/duolingo" }, - { name: "Ripple Button", url: "/docs/button/ripple-button" }, - { name: "Shining Button", url: "/docs/button/shining-button" }, - { name: "Swipe Button", url: "/docs/button/swipe-button" }, - { name: "Status Button", url: "/docs/button/status-button" }, - { name: "Animated Follow Button", url: "/docs/button/animated-follow-button" }, - { name: "Get Started Button", url: "/docs/button/get-started-button" }, - ]; - return { "@context": "https://schema.org", "@type": "ItemList", @@ -351,10 +366,83 @@ export function buildBlogMetadata(blog: PublishedBlog): Metadata { description, path: blog.slug, type: "article", - keywords: [blog.title, ...(blog.labels ?? [])], + keywords: [ + blog.title, + ...(blog.labels ?? []), + "animated React components", + "Tailwind CSS", + ], }); } +function buildBlogAuthorJsonLd(blog: PublishedBlog) { + if (!blog.author || blog.author === "AnimataDesign") { + return { + "@type": "Organization", + name: BRAND_SUFFIX, + url: siteConfig.url, + }; + } + + return { + "@type": "Person", + name: blog.author, + url: `https://twitter.com/${blog.author}`, + }; +} + +function buildBlogFaqJsonLd(blog: PublishedBlog) { + if (blog.slugAsParams !== "aceternity-ui-vs-magic-ui-vs-animata") { + return null; + } + + const faqs = [ + { + question: "What is the difference between Aceternity UI, Magic UI, and Animata?", + answer: + "Aceternity UI is strongest for cinematic landing pages. Magic UI is strongest for polished marketing micro-interactions next to shadcn/ui. Animata is strongest for product UI polish you own under MIT, with accessibility and reduced-motion patterns included before paste.", + }, + { + question: "Is Animata a free open-source Aceternity alternative?", + answer: + "For product UI animated components you own, yes—Animata is free MIT open source. It is not a 1:1 substitute for Aceternity's cinematic landing catalog. Many teams use both.", + }, + { + question: "When should I use Aceternity UI, Magic UI, or Animata?", + answer: + "Use Aceternity for marketing heroes and high-impact landing sections. Use Magic for marketing micro-interactions beside shadcn. Use Animata for buttons, cards, tabs, scroll, and text inside the product.", + }, + { + question: "Is Animata free forever?", + answer: + "Yes. Animata's animated React components are free, open source, and MIT-licensed for the core library.", + }, + { + question: "Do I need Motion for Animata?", + answer: + "Not for everything. Motion is optionally required for some complex animations. Check each component's docs before assuming Motion is required.", + }, + { + question: "Magic UI vs Animata for app UI?", + answer: + "For in-app product chrome with ownership and accessibility defaults, prefer Animata. For marketing sections and Design Engineer micro-interactions beside shadcn, prefer Magic. They can coexist.", + }, + ]; + + return { + "@context": "https://schema.org", + "@type": "FAQPage", + mainEntity: faqs.map((faq) => ({ + "@type": "Question", + name: faq.question, + acceptedAnswer: { + "@type": "Answer", + text: faq.answer, + }, + })), + }; +} + export function buildBlogJsonLd(blog: PublishedBlog, description: string) { const headline = blog.seoTitle ?? blog.title; @@ -369,17 +457,7 @@ export function buildBlogJsonLd(blog: PublishedBlog, description: string) { datePublished: blog.date, dateModified: blog.dateModified ?? blog.date, image: siteConfig.ogImage, - author: blog.author - ? { - "@type": "Person", - name: blog.author, - url: `https://twitter.com/${blog.author}`, - } - : { - "@type": "Organization", - name: BRAND_SUFFIX, - url: siteConfig.url, - }, + author: buildBlogAuthorJsonLd(blog), publisher: { "@type": "Organization", name: BRAND_SUFFIX, @@ -389,6 +467,11 @@ export function buildBlogJsonLd(blog: PublishedBlog, description: string) { url: siteConfig.ogImage, }, }, + isAccessibleForFree: true, + mainEntityOfPage: { + "@type": "WebPage", + "@id": absoluteUrl(blog.slug), + }, }; const breadcrumb = { @@ -401,7 +484,8 @@ export function buildBlogJsonLd(blog: PublishedBlog, description: string) { ], }; - return [article, breadcrumb]; + const faq = buildBlogFaqJsonLd(blog); + return faq ? [article, breadcrumb, faq] : [article, breadcrumb]; } export const homePageMetadata = createPageMetadata({ diff --git a/scripts/build-llms-txt.js b/scripts/build-llms-txt.js index 8f7b6de9..33563ee2 100644 --- a/scripts/build-llms-txt.js +++ b/scripts/build-llms-txt.js @@ -74,6 +74,12 @@ function buildIndex(byCategory) { "", `Install any component with: \`pnpm dlx shadcn@latest add ${SITE_URL}/r/{category}/{component}.json\``, "", + "## Guides & comparisons", + "", + `- [Top Animated React Buttons (2026)](${SITE_URL}/docs/guides/animated-react-buttons)`, + `- [Top Animated React Text Effects (2026)](${SITE_URL}/docs/guides/animated-react-text-effects)`, + `- [Aceternity UI vs Magic UI vs Animata](${SITE_URL}/blog/aceternity-ui-vs-magic-ui-vs-animata)`, + "", ]; for (const { slug, title } of CATEGORY_ORDER) {