There is no build step on this website. No package.json, no bundler, no CSS
preprocessor, no dependency manager, no lockfile. The whole thing is PHP files, one hand-written
stylesheet, one hand-written script and a folder of fonts. Deploying it is copying a directory
onto a server.
This is a deliberate choice rather than a shortcut, and it is worth being precise about what it actually costs, because “no dependencies” is usually said with more romance than arithmetic.
What the decision was made against
The requirement was that this site must run on ordinary shared hosting — the cPanel kind, with an FTP login and a PHP version somebody else chooses — and must still install and run in four years with no attention paid to it in between.
That second half is the one that decides it. A build pipeline is not a one-time cost; it is a standing obligation. The bundler releases a major version, the Node version reaches end of life, a transitive dependency is deprecated, and a site nobody has touched in eighteen months no longer builds — not because the site changed, but because the ground under it did. For a marketing site of six pages, that maintenance is the largest single cost of ownership, and it buys almost nothing.
What replaces the tooling
The jobs a build step normally does still have to be done. They just get done differently.
Design tokens would come from a preprocessor's variables. They come from CSS custom properties instead, declared once at the top of the stylesheet — which is better, since they are live values in the browser rather than compiled-away text:
:root {
--surface-0: #07080d;
--primary: #0cf993;
--section-y: clamp(72px, 9vw, 120px);
}
Cache-busting would come from content-hashed filenames. It comes from the filesystem instead — the URL carries the file's modification time, so an edited file is a new URL and an unchanged one keeps its year-long cache:
function asset(string $path): string
{
$path = 'assets/' . ltrim($path, '/');
$file = APP_ROOT . '/' . $path;
$ver = is_file($file) ? filemtime($file) : null;
return url($path) . ($ver ? '?v=' . $ver : '');
}
Components would come from a framework. They come from require. The
header, the footer, the document head and the contact form are each one file, included by the
pages that need them. It is the oldest idea in server-side web development and it has not stopped
working.
Minification does not happen at all, and that turns out to be fine: the server compresses text on the way out, which gets most of the way there for a stylesheet of this size.
What it genuinely costs
I would be lying if I said the trade was free.
-
No type checking. PHP's own type declarations and
strict_typescatch a fair amount, but there is no compiler telling me a variable is the wrong shape before I load the page. -
No component reuse across pages beyond includes. Anything more sophisticated
than passing a variable before a
requirehas to be written by hand. -
Discipline replaces enforcement. Nothing stops me pasting a hex value instead
of using a token, or writing an inline
onclick. On a team, that is exactly the kind of rule a build step should be enforcing rather than a person remembering. - No tree-shaking. Every visitor downloads the whole stylesheet. At this size it does not matter. At ten times this size it would.
What it buys
The list is short and all of it is real. Nothing to install, so nothing to fail to install. No lockfile, so no dependency drift and no supply-chain surface — there is no third-party code running on this site at all, which is also why the privacy notice is short. And no client-side framework to download and execute before the first paragraph of text can appear, which is most of why the pages feel instant.
There is a security dividend too. The content security policy on this site is
script-src 'self' with no exceptions, because there is nothing to make an exception
for — no CDN, no analytics tag, no embedded widget. That policy is only possible because of what
was left out.
The part that makes it a decision rather than an ideology
PaidLane — the product this studio is actually building — is a TypeScript application with a framework, a component library, a migration tool, a test suite and a build pipeline. All the things this site does without.
That is not a contradiction. It is the same question answered honestly for a different problem. An application that handles other people's money has offline drafts to reconcile, money arithmetic that must be right to the cent, access rules that must hold under attack and hundreds of tests that need to run before every deploy. There, a build step earns its keep several times over on the first day.
A six-page site that has to survive four years of neglect on shared hosting is a different problem, and it deserves a different answer. The mistake is not picking either one. It is picking the same one twice without checking.