What changed, and why it matters
Six changes separate the two versions. Each one is shown as it is written in the old site and in the new one: short excerpts from the real files, trimmed to the lines that matter.
Change 1
A layout that fits the screen
The old page is 1100 pixels wide, whatever the device, and never tells phones how to size it. The new one uses a flexible grid and a width that follows the screen, so the same page works from a small phone to a wide monitor.
<!-- no viewport meta in <head> -->
#wrapper { width: 1100px; margin: 0 auto }
.project-box { float: left; width: 333px }
.project-box img { width: 333px; height: 222px }<meta name="viewport" content="width=device-width, initial-scale=1">
.main { width: min(1100px, 100% - 2 * clamp(16px, 4vw, 32px)) }
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}Change 2
Pictures sized for each device
The old site sends the same 2400-pixel JPEG to a phone and to a desktop. The new one offers each picture in four widths and two modern formats; the browser downloads the one it needs. Width and height reserve the space, so text doesn’t jump when a picture arrives.
<img src="images/ashgrove-kitchen.jpg"
alt="Ashgrove Kitchen" width="340"><picture>
<source type="image/avif"
srcset="ashgrove-kitchen-480.avif 480w, …-800.avif 800w, …-1200.avif 1200w, …-1600.avif 1600w"
sizes="(max-width: 700px) 100vw, (max-width: 1100px) 50vw, 360px">
<source type="image/webp" srcset="…" sizes="…">
<img src="ashgrove-kitchen-800.webp" alt="" width="2400" height="1600"
loading="lazy" decoding="async">
</picture>Change 3
The browser does what the plugins did
Four jQuery libraries loaded, in order, before anything appears on screen, to drive a slider, a lightbox and one accordion. The new site uses what browsers now have built in: <details> for the accordion, <dialog> for the enlarged picture, and CSS scroll-snap for the gallery. To be precise about it: the new site still sends JavaScript, the Next.js runtime that makes moving between pages instant, and in total it is about as much as the old plugins. The difference is when it arrives: none of it holds back the first paint.
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/jquery-ui/jquery-ui.min.js"></script>
<script src="vendor/slick/slick.min.js"></script>
<script src="vendor/lightbox/js/lightbox.min.js"></script>
$('.slider').slick({ autoplay: true, dots: true });
$('#accordion').accordion({ heightStyle: 'content' });<details name="details-ashgrove-kitchen" open>
<summary>The brief</summary> …
</details>
<dialog> … </dialog> // opened with dialog.showModal()
.gallery { overflow-x: auto; scroll-snap-type: x mandatory }Change 4
One font file instead of a font family and an icon set
The old site loads a typeface in six separate weights and the whole of Font Awesome for five icons. The new one uses one variable font that covers every weight, and draws its three icons as small inline SVGs.
<link rel="stylesheet" href="vendor/playfair/400.css">
<link rel="stylesheet" href="vendor/playfair/500.css">
… 600, 700, 800, 900 …
<link rel="stylesheet" href="vendor/fontawesome/css/all.min.css">
<i class="fa-solid fa-building fa-3x"></i>const fraunces = Fraunces({ variable: "--font-halverne", subsets: ["latin"] });
// one self-hosted, variable woff2, preloaded
<svg viewBox="0 0 24 24" width="40" height="40" aria-hidden="true">…</svg>Change 5
Only the CSS the site uses
The old theme stylesheet carries years of rules for widgets the site no longer has, and every page downloads all of it. The new site’s styles live next to the components that use them, so a page gets only what it needs.
/* Halverne Studio theme v2.3 */
…
/* tabs (unused on this site) */
.tabs-1{…} .tabs-1:hover{…} .ie7 .tabs-1,.ie8 .tabs-1{…}
/* pricing (unused on this site) */ …app/after/after.module.css → only the studio site's classes
app/after/projects/[slug]/… → gallery and dialog styles, with the galleryChange 6
Pages built from parts, not copied by hand
In the old site every page is its own HTML file with the header, menu and footer pasted in; a change to the menu means editing every file. The new site is built from React components with Next.js: the header, a project card or the picture component is written once and used everywhere.
index.html
projects.html
project-ashgrove-kitchen.html
project-quayside-library.html
… each with its own copy of the header, menu and footerapp/after/layout.tsx → header, menu, footer: once
app/after/Picture.tsx → every picture on the site
app/after/projects/[slug]/page.tsx → all six project pages from one template