HTML, CSS, and JavaScript Explained for Vibe Coders — Lesson 1

Vibe Coding Foundations · 01 / 12 · Wednesday lessons
한국어 · English

HTML describes the meaning and structure of a page. CSS controls its presentation and layout. JavaScript adds programmed behavior. A browser uses them to produce the page you see. But changing that page is not necessarily the same as changing its source file—or saving the data you entered. The language definitions follow the official MDN references for HTML, CSS, and JavaScript.

Imagine you have asked an AI to build a small notes app. There is a heading, an input, and a button. It looks finished. Before asking for more features, you want to answer a more useful question: Where did this result come from, and what will actually change when I edit it?

In this lesson, you will find the code behind a heading and its size, compare adding a note with editing a source file, and check whether the example contains a way to save notes. You do not need to memorize every line. The aim is to connect a small change with evidence you can inspect.

The three roles · Start the exercise · Predict and compare · Troubleshooting · Check your understanding

Three roles do not require three files

In our example, HTML marks up the heading, input, button, and list. CSS sets their size and spacing. JavaScript checks the input and adds a list item when the form is submitted. CSS is not merely decoration: readable type and usable spacing affect whether someone can use the page comfortably.

What you are looking forWhere it appears in this example
The heading textHTML: <h1>One-line Notes</h1>
The heading size and spacingCSS inside <style>
Checking input and adding a noteJavaScript inside <script>
A guide to this teaching example, not a rule that each language has only one possible job.

These roles overlap. HTML has built-in behavior, CSS can animate things, and JavaScript can change styles. Start with the responsibilities shown here rather than trying to classify every possible web feature.

The starter keeps all three in one HTML file. This lets you observe the result before dealing with paths between files. The optional three-file exercise at the end separates the same example; it does not add features.

Start with one file: memo-start.html

You need a computer, a browser, and a plain-text editor. You can read the lesson on a phone, but the file-editing exercise is intended for a computer. There is no account, API key, installation command, domain purchase, or payment step.

This is a deliberately non-saving notes app. Use invented practice text, not passwords, personal information, or work material. The lesson is about understanding a page, not using it as a reliable place to keep notes.

Get the English exercise files — ZIP v1.1
Includes the single-file starter, a three-file version, English instructions, and an example screenshot.

Download the ZIP from Google Drive, then extract it before opening the app. In the extracted lesson-01-en folder, read README.txt and open memo-start.html in your browser. Compare it with expected-screen.png and the startup description below. You can leave the three-files folder for the optional exercise.

Prefer to create the file yourself? Follow the steps below. Downloaded the ZIP already? Skip the file-creation steps and go to the startup check. The complete code remains available below as an alternative when downloading is inconvenient.

  1. Create a folder called memo-lesson-01.
  2. Copy the complete code below into a plain-text file called memo-start.html. Copy through the final </html>.
  3. Open that file in your browser. If it opens in an editor, use Open with and choose the browser.
Saving on Windows

In Notepad, choose Save As, enter memo-start.html, use All files as the file type, and keep UTF-8 encoding. Make sure the result is not memo-start.html.txt. In Windows 11 File Explorer, View → Show → File name extensions makes the ending visible. Renaming an extension does not convert a rich-text document into plain HTML. See Microsoft’s explanation of file extensions.

Saving and reopening on macOS

In TextEdit, switch to Format → Make Plain Text before pasting. Save with the name memo-start.html; keep the HTML extension if asked. When reopening it to edit code, use the option to ignore rich-text commands rather than editing a formatted preview. Keep UTF-8 encoding. Apple documents this in Work with HTML documents in TextEdit. Menu wording can differ between operating-system versions.

Complete starter code — copy into memo-start.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>One-line Notes — Lesson 1</title>
  <!-- CSS: type size and layout -->
  <style>
* { box-sizing: border-box; }
body {
  margin: 0;
  padding: 32px 20px;
  background: #f4f3ef;
  color: #252525;
  font: 18px/1.7 system-ui, sans-serif;
}
main { max-width: 640px; margin: 24px auto; }
.eyebrow { font-size: 14px; }
h1 { font-size: 36px; line-height: 1.3; }
form { display: grid; gap: 12px; margin-top: 32px; }
input, button { font: inherit; padding: 12px; }
input { width: 100%; min-width: 0; }
button { cursor: pointer; }
button:disabled { cursor: not-allowed; }
:focus-visible { outline: 3px solid #531348; outline-offset: 3px; }
#feedback { min-height: 1.7em; }
#memo-list { padding-left: 24px; }
#memo-list li { overflow-wrap: anywhere; margin: 12px 0; }
  </style>
</head>
<body>
  <!-- HTML: heading, input, button, and list -->
  <main>
    <p class="eyebrow">Vibe Coding Foundations · 01</p>
    <h1>One-line Notes</h1>
    <p id="notice">Practice only. Reloading clears the notes.</p>
    <form id="memo-form" novalidate>
      <label for="memo-input">Practice note</label>
      <input id="memo-input" type="text" maxlength="140"
             autocomplete="off" aria-describedby="notice feedback">
      <button id="add-button" type="submit" disabled>Add to list</button>
    </form>
    <p id="feedback" role="status">Checking JavaScript…</p>
    <p id="empty">No notes added yet.</p>
    <ul id="memo-list" aria-label="Added notes"></ul>
    <noscript><p>JavaScript must be enabled for this exercise.</p></noscript>
  </main>
  <!-- JavaScript: responding to input -->
  <script>
const form = document.querySelector('#memo-form');
const input = document.querySelector('#memo-input');
const button = document.querySelector('#add-button');
const list = document.querySelector('#memo-list');
const feedback = document.querySelector('#feedback');
const empty = document.querySelector('#empty');

button.disabled = false;
feedback.textContent = 'Ready. Enter a short practice note.';

form.addEventListener('submit', (event) => {
  event.preventDefault();
  const text = input.value.trim();

  if (!text) {
    feedback.textContent = 'Enter a note instead of leaving it blank.';
    input.focus();
    return;
  }

  const item = document.createElement('li');
  item.textContent = text;
  list.append(item);
  empty.hidden = true;
  feedback.textContent = 'Added to the list, not saved to a file.';
  input.value = '';
  input.focus();
});
  </script>
</body>
</html>

At startup, you should see One-line Notes, an empty input, an enabled Add to list button, and the message Ready. Enter a short practice note. The list starts empty. Compare the structure and messages below; your system’s font or button appearance may differ.

One-line Notes at startup: an empty input, an enabled Add to list button, a ready message, and no notes.
The English example rendered from the supplied code in Linux Chromium 144. This is not a Windows or macOS file-opening test.

A managed computer may block local HTML or JavaScript. Do not bypass your organization’s security policy to complete this lesson. You can still inspect the code and record the exercise as not yet run. The testing limits for this article are listed at the end.

Predict first, then make one change

Experiment A: add a note without editing the file

Predict: If you add a sentence using the app, will that sentence also appear inside the original HTML file?

Do: Enter My first practice note and select Add to list. Then open memo-start.html in your text editor—not in the browser’s inspector—and look for the sentence you just entered.

Expected result for this code: the sentence appears in the on-screen list, but it has not been written into the source file. The script creates a list item in the current browser document. It does not contain code that writes the note to disk, browser storage, or a server.

Reload the page and check whether the list becomes empty. Also try submitting an empty input and an input containing only spaces. Both should produce an explanatory message without adding an item. Do not record these outcomes as checked until you have actually observed them.

Experiment B: change the source and save it

Predict: Will changing a heading in the source file behave like adding a note in the app?

Do: In your editor, change <h1>One-line Notes</h1> to <h1>My first notes app</h1>. Save with Ctrl+S on Windows or Command+S on macOS. Reload the same file in the browser.

Expected result: the new heading remains because it is in the saved source. The notes list starts empty because those notes were not saved. A single reload can therefore preserve one change while discarding another.

Next, change only font-size: 36px in the h1 CSS rule to font-size: 28px. Save and reload. The heading should be smaller while adding a note still works. Restore the original text and size afterward. Changing one thing at a time makes it easier to connect cause and result.

Optional experiment C: change the current page in developer tools

In Chrome or Edge, right-click the heading and choose Inspect. In the Elements panel, edit the heading’s text. You are changing the current document representation, often called the DOM. Check the original file in your editor: without extra persistence tooling, that edit has not rewritten it. Reload to compare again.

This observation assumes an ordinary inspection session with no Workspaces, Local Overrides, or other tools configured to persist changes. It is not a claim that developer tools can never save anything. See Chrome’s guide to inspecting and editing the DOM. You do not need to paste commands into the Console for this experiment.

Screen change, source edit, and saved data are different

Where you make the changeExpected result in this example
Add a note using the appThe current list changes. The source file does not. Reloading starts an empty list.
Edit the heading in a text editor and saveThe source file changes. Reloading reads the changed heading.
Edit the heading in the Elements panelThe current document changes. Without persistence tools, the source remains unchanged and reloading restores its heading.
Conditions: the supplied no-storage example, the same saved source file, and no developer-tool persistence features. This is not a universal description of every web app or navigation action.

Something appearing on screen proves that it appeared on screen. It does not, by itself, prove where it was saved. In another app, the answer may be browser storage or a remote database. You need evidence from that app’s code and behavior, not a conclusion borrowed from this example.

When the result does not match

You see code rather than an app. Check whether you opened the file in an editor or a browser. Check its full name, including the extension. Make sure the file is plain text saved as HTML, not a rich-text document with a new name.

The button stays disabled. In this example, JavaScript enables it during initialization. Check that you copied the entire code, including the closing script and HTML tags, and that scripts are permitted in the environment. Do not solve a policy restriction by weakening security controls.

The heading does not change. Confirm that you saved, that the editor and browser refer to the same folder, and that you edited <h1> rather than the browser-tab text in <title>. If you are using the optional three-file version, the HTML file is index.html.

The page looks different. Small differences in fonts and native buttons are not automatically bugs. Missing layout or unexpectedly large differences are a reason to check whether the full style block was copied. In the three-file version, also check that style.css is beside index.html.

A note unexpectedly survives reloading. First confirm which file and version you opened, what action you used to reload, and whether the code has been changed to use storage. The expected result depends on the supplied code, not merely on the page being called a notes app.

Before requesting a fix, write down: the file you opened → the exact change → the expected result → the observed result. That is more useful than “it does not work,” and it gives you a way to check whether a proposed fix actually helped.

Ask the AI to explain before it changes anything

Share only the relevant example code. Remove credentials, personal information, and private work material. Then use a request like this:

Do not edit the code yet. Point to the file names and code that define the content, presentation, and input behavior. Explain where a note is stored and where it is read back, if anywhere. Separate what you can observe from what you are inferring. Do not invent a server or database you have not seen. Suggest the smallest check I can perform and the result I should expect.

The useful part is not a magic wording. It is asking for evidence before a change. An AI saying “the data is saved” is not the same as you testing the behavior and locating the relevant save-and-load code.

Check your understanding

  1. Where would you change the heading’s text, its size, and the behavior of adding a note?
  2. Why can a changed heading remain after a reload while an added note disappears?
  3. What evidence would you need before claiming that another app really saves its data?
Answers and explanations

1. The heading text is in the HTML h1 element. Its size is in the CSS h1 rule. The form’s JavaScript listener checks the input and adds an item. These are locations in this example, not a rigid rule for every implementation.

2. Saving an edit in the text editor changes the source that the browser reads. Adding a note changes the current document but does not write that note anywhere persistent in this code. Both are screen changes; only one is also a saved source edit.

3. Identify where the app writes data, where it reads it back, and what scope that storage has. Then test the promised behavior: for example, reloading in the same environment. That test alone does not establish cross-device sharing, account isolation, or reliable backups.

Your completion check is practical: point to one piece of code, predict a result, run the change, and compare. If you have only read the article, record understood the explanation; exercise not yet checked rather than claiming an experiment you did not run.

Going further: DOM, storage, servers, and deployment

The DOM is the browser’s document representation that scripts and developer tools can inspect or change. It is not automatically a rewrite of the original HTML file. Our script creates an li element and changes that current representation.

This example contains no backend, API request, database, or browser-storage code. That does not mean every app needs a server to retain anything: browsers provide client-side storage mechanisms too. See MDN’s client-side storage guide. We will separate temporary state from storage in lesson 6.

Opening a file on your computer is also not the same as publishing it for other people on the internet. Deployment is the subject of lesson 11. For now, understanding this small local example is enough.

Optional: separate the same example into three files

Work on a copy in a separate folder. Save the HTML as index.html. Move only the CSS between the style tags into style.css, without the tags themselves. Replace that whole style element with <link rel="stylesheet" href="style.css">.

Move only the JavaScript between the script tags into app.js. Remove the original inline script element. Add <script src="app.js" defer></script> in the document head. Keep all three files together and open index.html.

For this external classic script, defer delays execution until HTML parsing has finished. The original single-file script appears after the elements it uses. These are two appropriate arrangements for this example, not interchangeable rules for every kind of script. See the MDN script reference. This optional step changes file organization, not the lesson’s behavior.

Next: what does “open a terminal and run this” mean?

Lesson 2 is planned for Wednesday, October 7, 2026. We will connect folders, commands, a running local process, and the address you open in a browser. You will learn what you are starting and how to stop it—not just which command to copy.

All English lessons · 이 강의 한국어로 읽기

Example version and verification limits

September 30, 2026 · Example version 1.1. The Korean and English editions share the same teaching goals and app behavior. The interface text, practice phrases, and instructions are localized. This is an original teaching example and a hypothetical learning situation, not a reported customer project.

Checked: Linux Chromium 144, using code injected into browser documents. Both languages and both the single-file and combined three-file contents were checked for startup, empty and spaces-only input, text insertion, focus return, 140-character input, markup-like input remaining text, changed heading and font size, and horizontal overflow at widths of 320, 390, 768, and 1440 pixels.

Not checked: the actual local-file open and reload path, Windows/macOS file dialogs, relative-file loading, Safari/Firefox, screen-reader behavior, the live blog theme on each device, or real beginner learning outcomes. The test environment blocked file-URL navigation. Starting a fresh browser document from the source was not an actual file reload.

This was a sequential self-check, not an independent review or a production security certification. Complete starter code remains available in this article alongside the ZIP link at the start of the exercise.

Download update, September 30, 2026: the Korean and English ZIP files were checked for anyone-with-the-link viewer permissions and linked to their respective lessons. ZIP integrity and packaged file names were checked. A separate signed-out download could not be completed in the review environment, so permission checks are not presented as an end-to-end download test.


다른 글 보기 · 주제 탐색 · 작성자와 편집 기준 · 문의·정정 요청

RUDA DIRECTOR에서 더 알아보기

지금 구독하여 계속 읽고 전체 아카이브에 액세스하세요.

계속 읽기