TNS
VOXPOP
As a JavaScript developer, what non-React tools do you use most often?
Angular
0%
Astro
0%
Svelte
0%
Vue.js
0%
Other
0%
I only use React
0%
I don't use JavaScript
0%
NEW! Try Stackie AI
AI Engineering / Software Development / Vibe Coding

A beginner’s guide to vibe coding

Vibe coding isn't just for experts — here's how to describe your way to a working app without writing a single line of code yourself.
Mar 15th, 2026 9:00am by
Featued image for: A beginner’s guide to vibe coding
Featured image by Dina Gazizova for Unsplash+.
We talk a lot about vibe coding. And to be honest, I’d heard the term far too many times before I took it seriously. It made no sense to me in the way that I think about vibes. How can you code based on a feeling? There are rules darn it (slams fits on desk). Well, apparently we can code based on vibes (but there are still rules). Yes, we need to be careful when deploying apps on the web. But that doesn’t mean we can’t also have a little fun and take the easier route when possible. As someone who now works with Claude Code on a regular basis, and has used the prompt “I don’t like the way it looks please change everything and try again” more than once, I can confirm. It is absolutely easier. Since the tooling environment is accessible to people from all backgrounds, I thought it would be useful to cover some basics. The remainder of this article will talk about what vibe coding is and some of its fundamentals so you too can tell Claude, “I don’t like the way it looks please change everything and try again.”

What is vibe coding?

Vibe coding lets developers focus on design decisions, constraints, and outcomes rather than syntax. It does so by using generative AI to build applications by describing the intent, architecture, and user experience of a system rather than manually writing every line of code. Vibe coding helps people with and without a background in computer science or software development build applications.

Getting started with vibe coding

With traditional development, developers start assembling the pieces and working out different parts of the application. That could look like defining, building, and testing functions, loops, variables, etc. And once enough of the pieces are assembled, they’ll start assembling everything into a working system. Vibe coding starts with vibes. Rather than working through a few functions, you can share your intent and desired functionality with generative AI and then AI will work out all the details. Let’s think through something simple, adding a new UI to a page. The new UI should accomplish the following:
  • iterate through an array
  • render a component for each item
  • display them in a list
In more traditional software development, you could start tackling the problem with this line of thinking: Create a loop that iterates through an array of task objects and renders a card component for each task. With vibe coding, you’re focused more on describing the functionality and result rather than the build. The solution (aka the prompt) for the same task as above would look more like the following sentence. Build a responsive card list that displays tasks from an array. Each task should render as a card with clear spacing, dark-mode support, and a subtle hover animation. The prompt communicates behavior and design intent, not just implementation details. If you prompted AI with more technical instruction, you may not get your desired outcome at this stage. Yes, there is a time and place for more technical instruction but we won’t cover that here.

Vibe coding tools

It’s clear we’re in the age of AI. My experience from this past year leads me to believe that working with AI is only going to continue getting easier, more efficient, and more impactful. So if you’re someone who vibe codes, I’d be on the lookout for new tools regularly. Here are some popular tools that allow developers to treat AI as a collaborative layer in the development process rather than a separate system.
  • Cursor is an AI-native integrated development environment (IDE) that understands your codebase and can generate or refactor code across files.
  • GitHub Copilot is an AI-powered extension for existing IDEs like VS Code or JetBrains, providing inline code suggestions and generating code as you type.
  • Replit is a platform for rapid prototyping and deployment, letting you generate and deploy apps quickly.
  • Framer Motion is a declarative animation library for React that adds motion and interactions with minimal code.
  • Tailwind CSS is a utility-first CSS framework that lets you describe design intent in plain, human-readable terms, making it easy for AI to translate your aesthetic into working styles.

Vibe coding prompt design

Truthfully, this section could be its own blog because there’s a ton to cover. There’s no perfect way to design a prompt, and better prompts will come from trial and error. But here are some simple principles to help you get started.

Structured prompts

The clearer the prompt, the closer the code will be to your desired results. Rather than asking for AI to build an app, help it understand the vibes. In this case, the vibes are problem, constraints, and desired experience. The C.A.S.E. Framework is one approach. Context: What does the application do? Example: A Pomodoro timer that helps users focus and take breaks during work sessions. Aesthetic: What will the app look like? Are there any UI constraints? Example: A clean dashboard layout with large numbers and minimal distractions. The timer sound should be soft and non-intrusive.  Stack: What frameworks, libraries, or languages should it use? Example: React and Tailwind CSS. Experience: How will the application feel to the user? Example: Calm, focused, and distraction-free. Can you prompt AI with something like “Build a Pomodoro timer” and get a Pomodoro timer? Yes. Will it be the one you want? No. Yes, I know this from experience. The examples above can be built into the structured prompt below:
  • Build a Pomodoro timer using React for the frontend logic and Tailwind CSS for styling.
  • Display a 25-minute countdown with Start and Reset buttons.
  • Use a clean dashboard layout with large, readable numbers and generous whitespace.
  • The experience should feel calm, distraction-free, and easy to focus on.
  • We’ll use this for our code example.
You’re always welcome to include more detail in your prompts but I wouldn’t suggest including less. These prompts also help you, the developer, think through what you want the user to experience with your application.

Vibe coding a Pomodoro timer

Let’s turn our prompt into a real application. I’m going to use VS code and Gemini for this example. If you want to code along but don’t have the specific AI tooling, a chatbot is a great way to start.  I don’t usually vibe code with Gemini but it’s great for this example. Note: Don’t vibe code with ChatGPT.  In my experience, ChatGPT writes code with bugs in it and can’t debug. It keeps you looped into doing the same thing over and over again.  I pasted our prompt into Gemini exactly as it’s listed above. When you code with a chatbot like Gemini or Claude and work outside of that environment (i.e. copy/ paste into an IDE), it still helps with all the steps. Gemini chose to build our React project with Vite. Vite is the industry standard for starting React projects these days because it’s incredibly fast. Open your terminal and run:
npm create vite@latest my-pomodoro -- --template react
Then move into the project folder:
cd my-pomodoro
Then install dependencies and start the server:
npm install
npm run dev
Your app will go live athttp://localhose:5173. The code below is Gemini’s response to our prompt: Replace the code insrc/App.jsxwith the code below.
import { useState, useEffect } from 'react';
import './App.css';

function App() {
  const [minutes, setMinutes] = useState(25);
  const [seconds, setSeconds] = useState(0);
  const [isActive, setIsActive] = useState(false);

  useEffect(() => {
    let interval = null;

    if (isActive) {
      interval = setInterval(() => {
        if (seconds > 0) {
          setSeconds(seconds - 1);
        } else if (minutes > 0) {
          setMinutes(minutes - 1);
          setSeconds(59);
        } else {
          // Timer finished
          clearInterval(interval);
          setIsActive(false);
          alert("Time's up! Take a breath.");
        }
      }, 1000);
    } else {
      clearInterval(interval);
    }

    // This "cleans up" the timer if the user leaves the page
    return () => clearInterval(interval);
  }, [isActive, minutes, seconds]);

  const toggleTimer = () => setIsActive(!isActive);

  const resetTimer = () => {
    setIsActive(false);
    setMinutes(25);
    setSeconds(0);
  };

  // Helper to make "5" look like "05"
  const displayTime = (val) => String(val).padStart(2, '0');

  return (
    <div className="container">
      <div className="timer-card">
        <h1>Focus</h1>
        <div className="display">
          {displayTime(minutes)}:{displayTime(seconds)}
        </div>
        <div className="controls">
          <button className="btn-primary" onClick={toggleTimer}>
            {isActive ? 'Pause' : 'Start'}
          </button>
          <button className="btn-secondary" onClick={resetTimer}>
            Reset
          </button>
        </div>
      </div>
    </div>
  );
}

export default App;
Replace the code insrc/App.csswith the code below.
/* Calm Background & Base Reset */
body {
  margin: 0;
  padding: 0;
  background-color: #f0f4f8; /* Soft blue-grey */
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

/* The Main Container */
.container {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
}

/* The Card holding the timer */
.timer-card {
  text-align: center;
  background: white;
  padding: 5rem 6rem; /* Generous internal padding */
  border-radius: 32px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.04);
  max-width: 500px;
  width: 90%;
}

/* "Focus" Title */
h1 {
  color: #627d98;
  font-weight: 300;
  text-transform: uppercase;
  letter-spacing: 0.2rem;
  margin: 0;
  margin-bottom: 5rem; /* Large gap below the title */
}

/* The Countdown Numbers */
.display {
  font-size: 8rem;
  font-weight: 700;
  color: #102a43;
  line-height: 1;
  margin-bottom: 5rem; /* Large gap below the numbers */
  font-variant-numeric: tabular-nums; /* Prevents numbers from jumping when they change */
}

/* Button Container */
.controls {
  display: flex;
  gap: 1.5rem;
  justify-content: center;
}

/* Shared Button Styles */
button {
  padding: 1.2rem 2.5rem;
  border-radius: 16px;
  border: none;
  font-size: 1.1rem;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s ease;
  outline: none;
}

button:hover {
  opacity: 0.9;
  transform: translateY(-2px);
}

button:active {
  transform: translateY(0);
}

/* Specific Button Colors */
.btn-primary {
  background-color: #48bb78; /* Calm green */
  color: white;
}

.btn-secondary {
  background-color: #e4e7eb;
  color: #486581;
}
Your result will look like this: What do you think? Is it an elegant, easy to understand, non-intrusive timer? Is it what you expected? What would you change or refine? Play with this a little. See how easy it is to change the amount of time on the timer. Press start, then pause. Get a feel for how it works then get started on something more exciting!
Group Created with Sketch.
TNS owner Insight Partners is an investor in: Calm.
TNS DAILY NEWSLETTER Receive a free roundup of the most recent TNS articles in your inbox each day.