How can you improve your website with AI?

Written by , Founder

  • Published
  • 9 min read

Quick answer: AI lets you describe almost any piece you would like on your website, from motion graphics and animated diagrams to calculators, quizzes and sharper copy, and then builds it for you. All you need is a clear, precise prompt, and a person to check the result before it goes live. Read on to see a real prompt running beside the component it builds, and how a few sentences reshape it.

prompt537 lines
You are given a task to integrate an existing React component in the codebase

The codebase should support:
- shadcn project structure  
- Tailwind CSS
- Typescript

If it doesn't, provide instructions on how to setup project via shadcn CLI, install Tailwind or Typescript.

Determine the default path for components and styles. 
If default path for components is not /components/ui, provide instructions on why it's important to create this folder
Copy-paste this component to /components/ui folder:
```tsx
ai-agent-pipeline.tsx
"use client"

import { useEffect, useState } from "react"
import { motion, AnimatePresence } from "framer-motion"

const messages = [
  'Received: "Summarize Q3 performance for stakeholder report..."',
  "Chunking input → 847 tokens → 6 embeddings generated",
  "Vector search complete: 5 chunks, avg cosine sim 0.89",
  "Injecting context into prompt template (1,204 tokens)",
  "LLM inference: 3 tool calls dispatched in parallel",
  "Tool: send_email → draft created, 312 words, pending approval",
  "Tool: update_crm → record Q3_2024 flagged as reviewed",
  "Tool: generate_report → PDF queued for 17:00 dispatch",
  "Workflow complete. 3 actions dispatched in 342ms.",
  "Idle. Listening for next trigger event...",
]

function AnimatedDot({
  path,
  duration,
  delay,
  size,
  opacity,
}: {
  path: string
  duration: number
  delay: number
  size: number
  opacity: number
}) {
  return (
    <circle r={size} fill="#0052FF" opacity={opacity}>
      <animateMotion
        dur={`${duration}s`}
        repeatCount="indefinite"
        begin={`${delay}s`}
        path={path}
      />
    </circle>
  )
}

function PulsingDot({
  cx,
  cy,
  color,
  duration,
  delay = 0,
}: {
  cx: number
  cy: number
  color: string
  duration: number
  delay?: number
}) {
  return (
    <motion.circle
      cx={cx}
      cy={cy}
      r={2.8}
      fill={color}
      animate={{ opacity: [0.15, 1, 0.15] }}
      transition={{
        duration,
        delay,
        repeat: Infinity,
        ease: "easeInOut",
      }}
    />
  )
}

function StatusIndicator({
  cx,
  cy,
  color,
  pulsing = false,
  duration = 1.9,
  delay = 0,
}: {
  cx: number
  cy: number
  color: string
  pulsing?: boolean
  duration?: number
  delay?: number
}) {
  if (pulsing) {
    return (
      <motion.circle
        cx={cx}
        cy={cy}
        r={3}
        fill={color}
        animate={{ opacity: [0.3, 1, 0.3] }}
        transition={{
          duration,
          delay,
          repeat: Infinity,
          ease: "easeInOut",
        }}
      />
    )
  }
  return <circle cx={cx} cy={cy} r={3} fill={color} opacity={0.95} />
}

export default function EnterpriseAIPipeline() {
  const [messageIndex, setMessageIndex] = useState(0)
  const [workflows, setWorkflows] = useState(1247)

  useEffect(() => {
    const messageInterval = setInterval(() => {
      setMessageIndex((prev) => (prev + 1) % messages.length)
    }, 2700)

    const workflowInterval = setInterval(() => {
      setWorkflows((prev) => prev + 1)
    }, 7200)

    return () => {
      clearInterval(messageInterval)
      clearInterval(workflowInterval)
    }
  }, [])

  const paths = {
    p1: "M116,88 L158,88",
    p2: "M268,88 L306,88",
    p3: "M411,88 C425,88 435,50 448,50",
    p4: "M411,88 L448,88",
    p5: "M411,88 C425,88 435,126 448,126",
  }

  return (
    <div className="bg-[#090909] border border-white/[0.08] rounded-[14px] overflow-hidden font-sans w-[620px] mx-auto">
      {/* Header */}
      <div className="px-[18px] py-[11px] border-b border-white/[0.06] flex items-center justify-between">
        <div className="flex items-center gap-[7px]">
          <motion.span
            className="w-[6px] h-[6px] rounded-full bg-green-500 inline-block"
            animate={{ opacity: [1, 0.2, 1] }}
            transition={{ duration: 2, repeat: Infinity, ease: "easeInOut" }}
          />
          <span className="text-[10px] text-white/30 tracking-[0.1em] font-mono">
            AGENT PIPELINE · LIVE
          </span>
        </div>
        <span className="text-[10px] text-white/[0.18] font-mono">
          3 agents · 0 errors
        </span>
      </div>

      {/* SVG Pipeline Visualization */}
      <svg width="100%" viewBox="0 0 580 172" className="block">
        <defs>
          <marker
            id="ma"
            viewBox="0 0 10 10"
            refX="8"
            refY="5"
            markerWidth="5"
            markerHeight="5"
            orient="auto"
          >
            <path
              d="M2 1.5L7.5 5L2 8.5"
              fill="none"
              stroke="rgba(0,82,255,0.45)"
              strokeWidth="1.6"
              strokeLinecap="round"
              strokeLinejoin="round"
            />
          </marker>
        </defs>

        {/* Connection Paths */}
        <path
          d={paths.p1}
          fill="none"
          stroke="rgba(0,82,255,0.22)"
          strokeWidth="1.5"
          strokeDasharray="3 5"
          markerEnd="url(#ma)"
        />
        <path
          d={paths.p2}
          fill="none"
          stroke="rgba(0,82,255,0.22)"
          strokeWidth="1.5"
          strokeDasharray="3 5"
          markerEnd="url(#ma)"
        />
        <path
          d={paths.p3}
          fill="none"
          stroke="rgba(0,82,255,0.15)"
          strokeWidth="1.5"
          strokeDasharray="3 5"
        />
        <path
          d={paths.p4}
          fill="none"
          stroke="rgba(0,82,255,0.15)"
          strokeWidth="1.5"
          strokeDasharray="3 5"
        />
        <path
          d={paths.p5}
          fill="none"
          stroke="rgba(0,82,255,0.15)"
          strokeWidth="1.5"
          strokeDasharray="3 5"
        />

        {/* Animated dots along paths */}
        <AnimatedDot path={paths.p1} duration={1.05} delay={0} size={2.5} opacity={1} />
        <AnimatedDot path={paths.p1} duration={1.05} delay={0.35} size={1.8} opacity={0.65} />
        <AnimatedDot path={paths.p1} duration={1.05} delay={0.7} size={1.3} opacity={0.35} />

        <AnimatedDot path={paths.p2} duration={0.88} delay={0.18} size={2.5} opacity={1} />
        <AnimatedDot path={paths.p2} duration={0.88} delay={0.62} size={1.8} opacity={0.65} />

        <AnimatedDot path={paths.p3} duration={1.3} delay={0.08} size={2.2} opacity={0.9} />
        <AnimatedDot path={paths.p3} duration={1.3} delay={0.65} size={1.5} opacity={0.55} />

        <AnimatedDot path={paths.p4} duration={1.15} delay={0.28} size={2.2} opacity={0.9} />
        <AnimatedDot path={paths.p4} duration={1.15} delay={0.85} size={1.5} opacity={0.55} />

        <AnimatedDot path={paths.p5} duration={1.4} delay={0.45} size={2.2} opacity={0.9} />
        <AnimatedDot path={paths.p5} duration={1.4} delay={1.0} size={1.5} opacity={0.55} />

        {/* Trigger Node */}
        <rect
          x="16"
          y="66"
          width="100"
          height="44"
          rx="8"
          fill="#141414"
          stroke="rgba(255,255,255,0.09)"
          strokeWidth="0.5"
        />
        <text
          x="66"
          y="83"
          textAnchor="middle"
          fontSize="9.5"
          fill="rgba(255,255,255,0.28)"
          fontFamily="system-ui"
          letterSpacing=".07em"
        >
          TRIGGER
        </text>
        <text
          x="66"
          y="100"
          textAnchor="middle"
          fontSize="12"
          fill="rgba(255,255,255,0.82)"
          fontFamily="system-ui"
        >
          User Query
        </text>
        <text
          x="66"
          y="122"
          textAnchor="middle"
          fontSize="8.5"
          fill="rgba(255,255,255,0.18)"
          fontFamily="monospace"
        >
          node-01
        </text>

        {/* Vector DB Node */}
        <rect
          x="158"
          y="66"
          width="110"
          height="44"
          rx="8"
          fill="#141414"
          stroke="rgba(255,255,255,0.09)"
          strokeWidth="0.5"
        />
        <text
          x="213"
          y="83"
          textAnchor="middle"
          fontSize="9.5"
          fill="rgba(255,255,255,0.28)"
          fontFamily="system-ui"
          letterSpacing=".07em"
        >
          VECTOR DB
        </text>
        <text
          x="213"
          y="100"
          textAnchor="middle"
          fontSize="12"
          fill="rgba(255,255,255,0.82)"
          fontFamily="system-ui"
        >
          Semantic Search
        </text>
        <text
          x="213"
          y="122"
          textAnchor="middle"
          fontSize="8.5"
          fill="rgba(255,255,255,0.18)"
          fontFamily="monospace"
        >
          pinecone
        </text>

        {/* LLM Agent Node */}
        <rect
          x="306"
          y="53"
          width="105"
          height="70"
          rx="10"
          fill="#050D1C"
          stroke="#0052FF"
          strokeWidth="1"
        />
        <rect x="318" y="53.5" width="80" height="1" rx="0.5" fill="rgba(51,117,255,0.5)" />
        <text
          x="358"
          y="78"
          textAnchor="middle"
          fontSize="9.5"
          fill="rgba(51,117,255,0.65)"
          fontFamily="system-ui"
          letterSpacing=".07em"
        >
          LLM AGENT
        </text>
        <text
          x="358"
          y="97"
          textAnchor="middle"
          fontSize="13"
          fill="#fff"
          fontFamily="system-ui"
          fontWeight="500"
        >
          Processing
        </text>
        <PulsingDot cx={346} cy={113} color="#0052FF" duration={1.2} delay={0} />
        <PulsingDot cx={358} cy={113} color="#0052FF" duration={1.2} delay={0.4} />
        <PulsingDot cx={370} cy={113} color="#0052FF" duration={1.2} delay={0.8} />
        <text
          x="358"
          y="139"
          textAnchor="middle"
          fontSize="8.5"
          fill="rgba(0,82,255,0.4)"
          fontFamily="monospace"
        >
          claude-3-sonnet
        </text>

        {/* Output Nodes */}
        <rect
          x="448"
          y="35"
          width="116"
          height="30"
          rx="7"
          fill="#111"
          stroke="rgba(255,255,255,0.07)"
          strokeWidth="0.5"
        />
        <text
          x="490"
          y="53.5"
          textAnchor="middle"
          fontSize="11"
          fill="rgba(255,255,255,0.62)"
          fontFamily="system-ui"
        >
          Email Draft
        </text>
        <StatusIndicator cx={550} cy={43} color="#22c55e" />

        <rect
          x="448"
          y="73"
          width="116"
          height="30"
          rx="7"
          fill="#111"
          stroke="rgba(255,255,255,0.07)"
          strokeWidth="0.5"
        />
        <text
          x="490"
          y="91.5"
          textAnchor="middle"
          fontSize="11"
          fill="rgba(255,255,255,0.62)"
          fontFamily="system-ui"
        >
          CRM Update
        </text>
        <StatusIndicator cx={550} cy={81} color="#f59e0b" pulsing duration={1.9} />

        <rect
          x="448"
          y="111"
          width="116"
          height="30"
          rx="7"
          fill="#111"
          stroke="rgba(255,255,255,0.07)"
          strokeWidth="0.5"
        />
        <text
          x="490"
          y="129.5"
          textAnchor="middle"
          fontSize="11"
          fill="rgba(255,255,255,0.62)"
          fontFamily="system-ui"
        >
          Report Gen
        </text>
        <StatusIndicator cx={550} cy={119} color="#f59e0b" pulsing duration={2.2} delay={0.35} />
      </svg>

      {/* Message Display */}
      <div className="border-t border-white/[0.06] px-[18px] py-[9px] h-[52px]">
        <div className="flex gap-2 items-start h-full">
          <span className="text-[#0052FF]/55 font-mono text-[13px] leading-[1.5] shrink-0">
            ›
          </span>
          <div className="relative flex-1 overflow-hidden h-full">
            <AnimatePresence mode="wait">
              <motion.div
                key={messageIndex}
                initial={{ opacity: 0, y: 5 }}
                animate={{ opacity: 1, y: 0 }}
                exit={{ opacity: 0, y: -5 }}
                transition={{ duration: 0.25 }}
                className="font-mono text-[11px] text-white/[0.42] leading-[1.55] absolute inset-0"
              >
                {messages[messageIndex]}
              </motion.div>
            </AnimatePresence>
          </div>
        </div>
      </div>

      {/* Stats Footer */}
      <div className="border-t border-white/[0.06] px-[18px] py-[10px] flex gap-[22px] items-center">
        <div>
          <div className="text-[9px] text-white/20 tracking-[0.09em] mb-[3px]">WORKFLOWS</div>
          <motion.div
            key={workflows}
            initial={{ scale: 1.05 }}
            animate={{ scale: 1 }}
            className="text-[16px] text-white/[0.72] font-mono"
          >
            {workflows.toLocaleString()}
          </motion.div>
        </div>
        <div>
          <div className="text-[9px] text-white/20 tracking-[0.09em] mb-[3px]">TOKENS</div>
          <div className="text-[16px] text-white/[0.72] font-mono">4.2M</div>
        </div>
        <div>
          <div className="text-[9px] text-white/20 tracking-[0.09em] mb-[3px]">AVG LATENCY</div>
          <div className="text-[16px] text-white/[0.72] font-mono">342ms</div>
        </div>
        <div className="ml-auto text-right">
          <div className="text-[9px] text-white/[0.18] tracking-[0.09em] mb-[3px]">STACK</div>
          <div className="text-[10px] text-[#0052FF]/55 font-mono">Claude · Pinecone</div>
        </div>
      </div>
    </div>
  )
}


demo.tsx
import EnterpriseAIPipeline from "@/components/ui/ai-agent-pipeline";

export default function EnterpriseAIPipelineDemo() {
  return (
    <div className="flex min-h-[400px] w-full items-center justify-center bg-black p-8">
      <EnterpriseAIPipeline />
    </div>
  )
}

```

Install NPM dependencies:
```bash
framer-motion
```

Implementation Guidelines
 1. Analyze the component structure and identify all required dependencies
 2. Review the component's argumens and state
 3. Identify any required context providers or hooks and install them
 4. Questions to Ask
 - What data/props will be passed to this component?
 - Are there any specific state management requirements?
 - Are there any required assets (images, icons, etc.)?
 - What is the expected responsive behavior?
 - What is the best place to use this component in the app?

Steps to integrate
 0. Copy paste all the code above in the correct directories
 1. Install external dependencies
 2. Fill image assets with Unsplash stock images you know exist
 3. Use lucide-react icons for svgs or logos if component requires them
Left: the prompt. Right: what it builds, running live. Every label and number is placeholder text from the prompt; nothing is connected.

Source: the prompt and the component it builds were published on 21st.dev.

This whole website was built the same way. Here’s how we built it with AI.

Why does this change things for a business website?

It changes who can shape a website: the person who understands the business can now describe a page in plain words and have it built, without waiting on a designer and then a developer. For most of the web’s history, anything clever on a page came with a queue. You explained the idea to a designer, the designer handed it to a developer, and some time later a first version arrived and the conversation began again. So the animated diagram that would have explained your process in five seconds, or the calculator that would have answered a customer’s first question before they picked up the phone, stayed on the wish list: always worth having, never quite worth the wait.

AI takes most of that queue away. The idea and the instruction become the same thing. You write down, precisely, what you want to see, and the model writes the code. The card above began life as nothing more than the text beside it.

That is the real shift, and it is less about technology than about who gets to shape a website. The person who understands the business can now describe the page directly, in their own words, and see it take form.

What can AI improve on your website?

AI can improve six parts of a website: its copy, its SEO basics, its accessibility, its motion graphics, its interactive components and the automation behind it. The temptation is to start with the most impressive of them. The better place to start is the work that quietly eats your week: the product descriptions you have been meaning to rewrite, the page titles nobody has touched since launch, the diagram you sketch on a whiteboard for every new customer. These jobs are slow by hand and easy to judge by eye, which makes them ideal for AI. Here is where it helps most, and what stays with you:

AreaWhat AI can doWhat you still decide
Copy and contentFirst drafts of pages, headings and product descriptions, and plainer rewrites of what you haveEvery claim, in your own voice
SEO basicsDraft page titles, descriptions and structured dataThat each one is accurate and matches the page
AccessibilityDraft image descriptions, flag low contrast and missing labelsThe final check, ideally with real users
Motion graphicsAnimated diagrams, subtle movement, a process shown step by stepWhether the movement helps the message or distracts from it
Interactive componentsCalculators, comparison tables, a short quiz that points visitors to the right serviceWhat the answers mean for your business
AI automationSend an enquiry to the right inbox, draft the first reply, file the detailsWhat is sent to a customer without a person reading it

Notice the right-hand column. AI is a remarkably capable builder, but it builds what it is told. It will not decide what your business stands for, which offer leads, or what a customer needs to hear before they trust you. Those judgements are what turn a website that looks finished into one that brings in work, and they stay with you.

What is vibe coding?

Vibe coding is building software by describing what you want in everyday language and letting an AI model write the code. The computer scientist Andrej Karpathy gave it the name in February 2025, and it has since become shorthand for a new way of making things on screen.

For a website, the idea goes further than it first appears. If every piece of a site can begin as a written description, a website stops being a pile of files only a developer can read and becomes a library of prompts: one for the header, one for the contact form, one for the animated diagram halfway down the page. Each is a building block you can read, keep, reuse and refine. Your website becomes something you can talk about in sentences, and change in sentences too.

What makes a good AI prompt for a website component?

A good prompt leaves very little to chance: it states the sizes, colours and timing, names the tools the project uses, and says where the file belongs. This is where prompt engineering earns its name. Think of a prompt as the brief you would hand a brilliant contractor who works at extraordinary speed, takes every word literally, and has never met you. Anything you leave unsaid, they will decide for you.

The prompt above is long for exactly that reason. It fixes the card at 620 pixels wide. It sets the size, brightness and start time of each of the eleven moving dots, and the speed of each line they travel along. It names the tools the project uses and where the file belongs, and it closes with the questions the AI should settle before wiring anything in. Very little is left to chance.

Leave any of that out and the model fills the gap on its own, choosing its own sizes, colours and timing, and choosing differently the next time you ask. That is why so many AI-built pages look alike: the model was left to guess, and it guessed the average. A short prompt gets you a component. A detailed one gets you this component.

How do you change a component once AI has built it?

To change the component, you change the prompt, not the code. This is where working in prompts pays off. We added five instructions to the end of the same prompt: a new purpose, a lighter palette, an honest header, a log that makes no claims, and one section taken out.

prompt6 lines
Before you copy the component, make these changes:
1. Make it an enquiry pipeline for a website, not an AI agent pipeline. Nodes: TRIGGER "Contact form" (node-01), CHECKS "Validation" (in code), and in the centre BRIEF "Drafting" (model call). Outputs: "Email to owner", "Booking link", "Brief filed".
2. Use a light palette: background #fbf9ee, dark text, accent #14594f in place of #0052FF, and #b7791f for the pending lights.
3. Change the header to "ENQUIRY PIPELINE · DEMO", and the text on its right to "sample data".
4. Replace the log messages with steps that describe the enquiry, and claim no numbers.
5. Remove the stats footer: its numbers are invented.
Same layout, same timing. New wording, new colours, and one section fewer.

Look at what stayed the same. The layout, the proportions and the rhythm of the moving dots are exactly where they were, because nothing in the edit mentioned them. Every change is a sentence you can read back, and everything you did not touch stays put.

For a business, that is the quiet advantage. Your website’s design decisions are written down in words anyone on the team can follow, rather than buried in code only one person understands.

What should you check before it goes live?

Check four things before an AI-built component goes live: that every number on it is real, that it fits a phone, that it respects a visitor’s reduced-motion setting, and that it suits the tools your site already uses. Speed is the gift of AI, and it is also the risk. Something that took seconds to build still deserves the scrutiny you would give anything with your name on it. Look closely at the original component and four problems surface:

  • Invented numbers. "LIVE", "4.2M tokens" and "342ms" are placeholder text. On a real business site they would be claims about a system that does not exist.
  • Width. At a fixed 620 pixels, it runs off the side of a phone held upright.
  • Reduced motion. The prompt ignores the setting some visitors use to ask for less movement. This page adds a still version.
  • Your setup. It assumes tools this site does not use, so it was adapted rather than pasted in.

None of this is a reason to avoid AI. It is the reason a person still signs off. The machine brings the speed; people bring the judgement. Deciding what each prompt says, and checking what it builds, is where the craft now lives.

What else do people ask about AI and websites?

Can AI build a whole website?

Yes, piece by piece. A single prompt for an entire site leaves nearly every decision to the model, and the result tends to look like everyone else’s. Building it one component at a time keeps the decisions, and the character, with you.

Will Google penalise a website for using AI?

Not for using AI. Google’s guidance on AI-generated content is about value, not tools: pages written mainly to rank, especially many thin pages generated at once, can break its spam policies whoever wrote them. Useful, accurate pages are fine however they were made.

Should you add an AI chatbot to your website?

Only if visitors ask questions a chatbot can answer reliably from your own information, such as opening times, services or how to book. If the answers need judgement, a clear contact form and a quick human reply usually serve people better. Either way, check what it says before it goes live.

Can AI make your website faster?

It can help find and fix what slows a page down, such as oversized images or code the page never uses. Measure before and after with a free tool like Google’s PageSpeed Insights, rather than taking a speed-up on trust.

Can AI help your website show up in ChatGPT and Google’s AI answers?

It can help you write pages those tools can read and quote: each question answered plainly near the top, accurate structured data, and a clear statement of who you are and where you work. Nobody can guarantee a mention, and anyone who promises one is guessing.

Do you need to know how to code to vibe code?

Not to start. To put something on a real business site, someone needs to read what the AI built and check that it works on a phone, loads quickly and does what the prompt asked.

Is AI-generated code safe to use on a business website?

It can be, if it is checked like any other code: what it installs, what it sends and where, and anything that handles customer details. Code nobody has read should not go live.

What is prompt engineering?

Writing instructions precise enough that the model has nothing to guess. For a website component that means every size, colour and timing, plus how the project is set up.

Want this done for your business? How we build websites walks through the seven steps, from a first call to handover. Rather learn to do it yourself? Practical AI training teaches it on your own work.

Your next step.

Tell us which part of your site you would describe first, and we will show you what its prompt would need to say.