---
title: "\"You Can Build It Without Knowing How to Code\" — The Real Truth of Vibe Coding and My Take"
date: 2026-09-23
time: "23:10"
model: admin
category: knowhow
summary: Beyond the concept and pros and cons of vibe coding, this uses real code examples to show the realistic limit that "vibe coding only works as far as you know," and lays out the attitude you actually need.
tags: vibe-coding,VibeCoding,AI-coding,prompt-engineering,agent,development
---
# "You Can Build It Without Knowing How to Code" — The Real Truth of Vibe Coding
## 1. What Is Vibe Coding
**Vibe coding** is a term first used by Andrej Karpathy (former head of AI at Tesla). Instead of writing code yourself, you instruct an AI in natural language and have it build the program.
Say "make me an app that feels like this," and the AI writes the code. When an error appears, you paste the error message into the AI and it fixes it for you. You focus on the "vibe" of the code and delegate the internal implementation to the AI.
### Why It Became a Hot Topic
- **The barrier to entry collapsed**: you can build an app without knowing a programming language
- **Speed**: prototyping 10-100x faster than traditional development
- **Tooling advances**: the arrival of agentic IDEs such as Claude Code, Cursor, Codex, and Qoder
## 2. The Reality of Vibe Coding, Seen Through Code
Theory alone does not convey why vibe coding is dangerous. Let's look through real code examples.
### Example 1: "Make Me a Login Page"
**Code the AI produced (the result a non-programmer received):**
```python
from flask import Flask, request, jsonify
import sqlite3
import hashlib
app = Flask(__name__)
@app.route('/login', methods=['POST'])
def login():
username = request.json['username']
password = request.json['password']
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
# Here is the problem
query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
cursor.execute(query)
user = cursor.fetchone()
if user:
return jsonify({"status": "success"})
else:
return jsonify({"status": "fail"})
```
**The non-programmer's reaction:** "Oh, it works! Login succeeds and it says success."
**The reaction of someone who knows how to code:** "That is SQL injection."
If someone enters `' OR '1'='1'` into `username`, **all user data in the database leaks**. The code the AI produced does "work," but it **has a security vulnerability**. The non-programmer does not know this.
**Correct code:**
```python
@app.route('/login', methods=['POST'])
def login():
username = request.json['username']
password = request.json['password']
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
# Use binding -> prevents SQL injection
cursor.execute(
"SELECT * FROM users WHERE username=? AND password=?",
(username, hashlib.sha256(password.encode()).hexdigest())
)
user = cursor.fetchone()
# ...
```
**Can you explain the difference?** That is the "as far as you know" gap.
---
### Example 2: "Make Me an Image Upload Feature"
**Code the AI produced:**
```python
@app.route('/upload', methods=['POST'])
def upload():
file = request.files['image']
file.save(f'/static/uploads/{file.filename}')
return jsonify({"url": f'/static/uploads/{file.filename}'})
```
**The non-programmer's reaction:** "Image upload works! Great."
**The reaction of someone who knows how to code:** "This can crash the server."
**Three problems:**
1. **Filename collision**: uploading a file with the same name overwrites it
2. **No file type restriction**: executables such as `.exe` and `.sh` can be uploaded
3. **No size limit**: uploading a 10GB file fills up the disk
**Correct code:**
```python
import os
import uuid
from werkzeug.utils import secure_filename
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/upload', methods=['POST'])
def upload():
file = request.files['image']
if not file or not allowed_file(file.filename):
return jsonify({"error": "Disallowed file format"}), 400
if file.content_length and file.content_length > MAX_FILE_SIZE:
return jsonify({"error": "File size exceeded"}), 400
# Generate a unique filename (prevents overwriting)
ext = file.filename.rsplit('.', 1)[1].lower()
filename = f"{uuid.uuid4().hex}.{ext}"
filepath = os.path.join('/static/uploads', secure_filename(filename))
file.save(filepath)
return jsonify({"url": f'/uploads/{filename}'})
```
**Can you explain the seven lines of logic in this code?** That is "as far as you know."
---
### Example 3: "Fetch the User List from the Database"
**Code the AI produced:**
```python
@app.route('/users')
def get_users():
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
users = cursor.fetchall()
return jsonify(users)
```
**The non-programmer's reaction:** "The user list comes out!"
**The reaction of someone who knows how to code:** "With a million users, this kills the server."
**Problems:**
1. **No pagination**: fetching a million rows at once -> memory explosion
2. **Passwords included**: `SELECT *` also fetches the password hashes
3. **Connection not returned**: no `conn.close()` -> DB connection leak
**Correct code:**
```python
@app.route('/users')
def get_users():
page = int(request.args.get('page', 1))
per_page = int(request.args.get('per_page', 20))
offset = (page - 1) * per_page
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
# Exclude passwords, apply pagination
cursor.execute(
"SELECT id, username, email, created_at FROM users LIMIT ? OFFSET ?",
(per_page, offset)
)
users = cursor.fetchall()
# Fetch the total count (for pagination)
cursor.execute("SELECT COUNT(*) FROM users")
total = cursor.fetchone()[0]
conn.close()
return jsonify({
"users": users,
"total": total,
"page": page,
"per_page": per_page
})
```
**Can you explain why SELECT \* is dangerous and why LIMIT/OFFSET are needed?**
---
### Example 4: "Make Me an SPA (Single-Page App)"
**HTML/JS the AI produced:**
```html
My App
```
**The non-programmer's reaction:** "Oh, the SPA works! Page transitions are smooth too."
**The reaction of someone who knows how to code:** "It is an XSS vulnerability, and there is no state management."
**Problems:**
1. **XSS (Cross-Site Scripting)**: putting user input straight into `innerHTML` allows malicious scripts to be injected
2. **No state management**: you cannot tell whether the user is logged in or which page they are on
3. **No error handling**: the screen breaks on a network error
**A simple improvement:**
```javascript
function navigate(path) {
fetch(path)
.then(res => {
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.text();
})
.then(html => {
// XSS prevention: use textContent
document.getElementById('app').textContent = '';
const div = document.createElement('div');
div.innerHTML = html; // only when the server is trusted
document.getElementById('app').appendChild(div);
})
.catch(err => {
document.getElementById('app').textContent =
'An error occurred: ' + err.message;
});
}
```
**Can you explain the danger of innerHTML?**
---
### Example 5: "Make Me an Email-Sending Feature"
**Code the AI produced:**
```python
import smtplib
@app.route('/send-email', methods=['POST'])
def send_email():
to = request.json['to']
subject = request.json['subject']
body = request.json['body']
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login('myemail@gmail.com', 'mypassword')
server.sendmail('myemail@gmail.com', to, f'Subject: {subject}\n\n{body}')
server.quit()
return jsonify({"status": "sent"})
```
**The non-programmer's reaction:** "The email sends! Great."
**The reaction of someone who knows how to code:** "The password is in the code. That is a security breach."
**Fatal problems:**
1. **Hardcoded password**: the password is exposed verbatim in the source code
2. **No SMTP credential rotation**: if the password changes, the whole system goes down
3. **No recipient validation**: you can send to any email address
**Correct code:**
```python
import os
import smtplib
from dotenv import load_dotenv
load_dotenv() # read from the .env file
@app.route('/send-email', methods=['POST'])
def send_email():
to = request.json['to']
subject = request.json['subject']
body = request.json['body']
# Load the password from environment variables
smtp_user = os.environ.get('SMTP_USER')
smtp_pass = os.environ.get('SMTP_PASS')
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(smtp_user, smtp_pass)
server.sendmail(smtp_user, to, f'Subject: {subject}\n\n{body}')
server.quit()
return jsonify({"status": "sent"})
```
**Can you explain what a .env file is and why it is needed?**
---
## 3. Clear Pros and Cons
### Pros
- **Even non-programmers can do it**: you can build a functioning app without a programming language
- **Extreme prototyping acceleration**: an idea can be implemented the same day
- **Automating repetitive work**: delegate boilerplate code, tests, and documentation to the AI
### Cons
- **Unverifiable**: if you do not understand why the AI-produced code works, you cannot cope when an error occurs
- **The time-wasting trap**: if you approach it thinking "just make me anything," you spend more time on fixes and debugging
- **Collapse of thinking**: skipping the logical thought process actually degrades your problem-solving ability
- **Security vulnerabilities**: if you cannot verify the security issues in AI-produced code, you cannot deploy it to production
## 4. Traditional Coding vs Vibe Coding
| Item | Traditional coding | Vibe coding |
|------|-----------|-----------|
| Core tool | Programming language | Prompt + AI agent |
| Development style | Design algorithms yourself | Delegate generation |
| Barrier to entry | High (months to years) | Low (natural language) |
| Biggest strength | Complete control, error tracing | Fast prototyping |
| Core skill | Code syntax, optimization | Prompt engineering |
| Verification ability | Yes (you wrote it) | **No (delegated to AI)** |
## 5. My Take — "Vibe Coding Only Works as Far as You Know"
I will speak honestly.
**Vibe coding is not "salvation for people who do not know how to code."** That is an exaggeration.
### As Far as You Know Is Everything
When I tell the AI "make me a login page," because I know Python I **can check** whether the code the AI produced has SQL injection. Because I know HTML/CSS I **can see with my eyes** whether the result turned out right. Because I know JavaScript I **can trace** why it is not working.
But if someone who does not know programming gives the same instruction? They **cannot judge** whether the code the AI produced is secure, whether it has performance problems, whether error handling is in place. When the AI says "it is finished," they simply have to believe it. This is precisely the fatal limit of vibe coding.
### The Reality of Vibe Coding by Level
```
Level 1: "Make me this"
-> The AI makes it -> cannot verify the result -> mostly fails
-> Analogy: "Build me a house" with no architecture knowledge -> a nonsensical house comes out
Level 2: "This part does not work, fix it"
-> The AI fixes it -> partial verification possible -> sometimes succeeds
-> Analogy: you can at least say "the door will not open" -> repairable
Level 3: "In this code, the auth token validation is missing"
-> The AI fixes it -> logic verification possible -> mostly succeeds
-> Analogy: you can diagnose precisely, "the door lock is broken" -> reliable repair
Level 4: "This architecture needs concurrency control, including deadlock prevention"
-> The AI designs it -> optimization possible -> complete
-> Analogy: architect-level design ability -> a perfect house
```
**To climb from Level 1 to Level 2, you must at minimum be able to explain "what is wrong."** That is precisely "as far as you know."
### The Difference in "What You Know" by Level
| Level | Example of "what you know" | Vibe coding usefulness |
|------|----------------|------------------|
| 1 | "I can turn on a computer" | almost 0% |
| 2 | "I can open and close files" | 10-20% |
| 3 | "I know what a database is" | 30-50% |
| 4 | "I know what networking/security is" | 50-70% |
| 5 | "I know architecture/design patterns" | 70-90% |
**The higher the level, the more efficient the collaboration with the AI.** The AI is a "multiplier of knowledge," not a "replacement for knowledge."
## 6. So What Should You Do
### (1) Do Not Give Up
Just because vibe coding became the trend does not mean you should give up studying coding. Paradoxically, **to use vibe coding properly you need more coding knowledge**.
### (2) Ask "Why"
Do not just use the code the AI produced. Ask, "Why did you do it this way?" Skill accumulates in the process of understanding the AI's explanation.
### (3) Do Not Fear Errors
Before pasting an error message into the AI, **read it once**. "FileNotFoundError," "IndexError," "Timeout" — if you know these words, you are already at Level 2.
### (4) Prompt Engineering Alone Is Not Enough
Writing good prompts matters, but beyond that you need the domain knowledge to understand "why this prompt is effective."
## 7. Conclusion
Vibe coding is a powerful tool. But a tool works only as well as the person holding it.
> **"Vibe coding only works as far as you know. No more and no less than what I know."**
If you do not know what SQL injection is, the login page the AI made could drain all of your user data. If you do not know what XSS is, the website the AI made could become a breeding ground for malicious scripts.
People say the era has come when AI replaces coding, but what is truly being replaced is "simple repetitive coding." The ability to understand a problem, design it, and verify it remains the human's job.
If you do vibe coding, you should at least be able to say **"why this is wrong."** Otherwise you become not the AI's customer but the AI's slave.
---
*This article is based on the operator's own hands-on experience and perspective.*