Documentation · Chapter 05

Serve CSS, images,
and JavaScript.

The browser can directly request files under public/. It must never receive private files under src/.

We improve reading-list without changing its HTTP logic or temporary session storage.

Public root and URL path

public/css/app.css/css/app.css
public/img/logo.svg/img/logo.svg
public/js/books.js/js/books.js

The word public does not appear in the URL because this folder is already the server's exposed root. A /src/views/books/index.php URL must remain inaccessible.

Create a simple CSS foundation

public/css/app.css

phpaml — zsh
:root {
    color-scheme: light;
    font-family: system-ui, sans-serif;
    color: #171717;
    background: #f7f7f5;
}

body { margin: 0; }
.container { width: min(68rem, calc(100% - 2rem)); margin-inline: auto; }
header { border-bottom: 1px solid #d7d7d2; }
nav { display: flex; gap: 1rem; padding-block: 1rem; }
main { padding-block: 3rem; }
input, button { min-height: 2.75rem; font: inherit; }
.field-error { color: #a40018; }

CSS improves presentation without moving HTML structure or PHP logic. Start with foundations: readable width, contrast, spacing, and usable fields.

Add an image with alternative text

phpaml — zsh
<img src="/img/logo.svg"
     width="40" height="40"
     alt="Reading List">

width and height reserve space before download. alt describes useful information. If the image is purely decorative, use alt="" so a screen reader ignores it.

JavaScript only when it adds value

phpaml — zsh
<script src="/js/books.js" defer></script>

defer downloads the script without blocking HTML parsing and runs it after the document is parsed. The CRUD should remain functional without it. A script can add delete confirmation or a visual enhancement, never replace server validation.

A specific page can load a specific script

Add /js/books.js only to Books pages when other pages do not need it. This avoids unnecessary browser work.