Skip to content

layout: one width for every page, blog post sidebar, rebuilt footer, fixes #161, fixes #439 - #704

Merged
stasadev merged 2 commits into
mainfrom
20260729_stasadev_revamp
Jul 29, 2026
Merged

layout: one width for every page, blog post sidebar, rebuilt footer, fixes #161, fixes #439#704
stasadev merged 2 commits into
mainfrom
20260729_stasadev_revamp

Conversation

@stasadev

@stasadev stasadev commented Jul 29, 2026

Copy link
Copy Markdown
Member

The Issue

Both of those live in the shell of the page, so this takes on the inconsistencies around them at the same time. Every page picked its own width (max-w-4xl, -5xl, -6xl, -7xl) and its own gutter, so nothing lined up between blocks or between pages. The footer had grown into one flat list that mixed social accounts with pages and named several of them twice. A blog post opened with a full-width feature image, which meant scrolling before you could read the first paragraph, and the space beside the text was doing nothing.

How This PR Solves The Issue

Preview base: https://20260729-stasadev-revamp.ddev-com-front-end.pages.dev/

Page Before After Preview Live
Every page max-w-4xl (56rem) on most pages, max-w-5xl/-6xl/-7xl on the homepage's sections, and a different px-* gutter per block --site-width: 72rem via .site-container, one .site-gutter (1.5rem, 2rem from 64rem up). Long-form text is capped separately at --reading-measure (42rem), wired into the typography plugin, so a wider page didn't make lines harder to read preview live
Header nav at max-w-4xl, logo sitting left of the content it heads the site container and gutter, so the logo lines up with the page at every width (#161) preview live
Homepage hero headline, buttons, platform list in a 4xl column with the terminal floated off the right edge two columns: copy holds a minimum width, the terminal is a fixed 40rem beside it (its output is a character grid that can't reflow, so it can only be clipped, never squeezed), clipped to a peek between md and the width where both fit, hidden below md. Headline now names Node.js alongside PHP; the platform badges came out (#439) preview live
Homepage stack logos eight logos with p-10 each, wrapping onto two lines at full width one row spaced with a gap instead of per-logo padding, and the whole set is a data array — all eight fit on one line preview live
Blog post full-width feature image above the post, "Posted In" as the only thing in the right column feature image beside the title, categories as pills under it, and a sticky sidebar with a newsletter callout and Similar Posts. The post itself starts at the top of the page preview live
Blog listing SVG feature images letterboxed inside the card while photos filled it SVG cards fill the box the same way, and the six release/how-to banner SVGs were re-canvassed to 3:2 with side padding so nothing is cropped and nothing touches the edge preview live
/download a list of files and nothing else sidebar with the release it's showing, release notes, all releases, checksums, installation steps, and a "Need Help?" card preview live
/get-started instructions only; if a step failed you had to go looking same "Need Help?" card, sticky beside the instructions preview live
/sponsor tier cards with their own black-and-white buttons (no dark-mode hover); PayPal and invoicing buried in prose "Ways to Sponsor" sidebar — GitHub Sponsors, PayPal, invoice or transfer — plus "Other Ways to Help"; tier cards now use the site's own buttons preview live
/about five oversized stats stacked in a bare column the same numbers in a "DDEV Today" sidebar card, and the story now ends with the sponsorship ask preview live
/usage-stats a long single column with no way to jump between sections "On This Page" index beside the charts, sponsorship ask at the end preview live
/brand, /contact, /foundation, /privacy plain markdown column, nothing beside it "On This Page" index, opt-in per page with index: true in frontmatter; /foundation also ends with the sponsorship ask preview live
Footer one flat list mixing social accounts with pages, with Discord, GitHub and the blog appearing twice and the feeds in the middle of it three bands: logo and social icons, then Product / Community / Project columns, then the copyright line with Privacy and the RSS/JSON feeds preview live

What's new

  • NewsletterCallout and SimilarPosts in the blog post sidebar, and CategoryPills shared by the post and its cards.
  • PageIndex, an "On This Page" nav built in the browser from the page's own h2 ids, so it can't drift from the content.
  • SponsorCTA, one sponsorship ask with one look and one top margin, on /about, /foundation, /usage-stats and the end of each Get Started walkthrough. It replaces quickstart/CommunityCTA, which said much the same thing in a different box.
  • SidebarLinks, HelpLinks, ReleaseLinks, SponsorWays for the sidebar cards, and size="small" on CtaButton for buttons in a sidebar.
  • lib/posts.ts (ordering, adjacent posts, similarity) and lib/images.ts (the public/img glob that three components were each declaring).
  • CSS: .site-container / .site-gutter, .page-grid / .content-column / .sidebar-column, .sidebar-card / .sidebar-label, .sponsor-cta.

Notes

  • The newsletter callout beside the post and the shape of the new footer were inspired by https://upsun.com/blog/ai-fatigue-engineering-teams/.
  • Similar Posts ranks by what the posts say, not just their categories: a tf-idf vector per post over its title, summary, categories and body, compared by cosine similarity, with a shared category and a shared author as smaller nudges. Categories alone were far too coarse — nine of them cover 140 posts, so every release note matched every other one equally. The list cuts off relative to its best match, so a post on a subject nothing else covers shows three good matches instead of five padded ones, and newsletters only match other newsletters (a monthly digest has a word in common with almost everything).
  • Every page above was checked against the dev server, and the new @apply utilities were checked in the compiled CSS.
  • I also replaced heavy gifs with smaller webp:
     cd public/img/blog/2026/07
     for f in ddev-start ddev-stop ddev-restart; do
       gif2webp -mixed -m 6 -min_size "$f-v1-25-2-vs-v1-25-3.gif" -o "$f-v1-25-2-vs-v1-25-3.webp"
     done

🤖 Developed with assistance from Claude Code

- Fixes #161: the hero and nav stayed at
`max-w-4xl` while the viewport kept growing, so from 1024px up the extra space
turned into void margin instead of page.

- Fixes #439: the homepage terminal was
absolutely positioned at `right: -40rem` inside a `h-72` box, so on a 13" screen
it hung off the side at the wrong size.

Both of those live in the shell of the page, so this takes on the
inconsistencies around them at the same time. Every page picked its own width
(`max-w-4xl`, `-5xl`, `-6xl`, `-7xl`) and its own gutter, so nothing lined up
between blocks or between pages. The footer had grown into one flat list that
mixed social accounts with pages and named several of them twice. A blog post
opened with a full-width feature image, which meant scrolling before you could
read the first paragraph, and the space beside the text was doing nothing.

Preview base: https://20260729-stasadev-revamp.ddev-com-front-end.pages.dev/

| Page | Before | After | Preview | Live |
| --- | --- | --- | --- | --- |
| Every page | `max-w-4xl` (56rem) on most pages, `max-w-5xl`/`-6xl`/`-7xl` on the homepage's sections, and a different `px-*` gutter per block | `--site-width: 72rem` via `.site-container`, one `.site-gutter` (1.5rem, 2rem from 64rem up). Long-form text is capped separately at `--reading-measure` (42rem), wired into the typography plugin, so a wider page didn't make lines harder to read | [preview](https://20260729-stasadev-revamp.ddev-com-front-end.pages.dev/) | [live](https://ddev.com/) |
| Header | nav at `max-w-4xl`, logo sitting left of the content it heads | the site container and gutter, so the logo lines up with the page at every width (#161) | [preview](https://20260729-stasadev-revamp.ddev-com-front-end.pages.dev/) | [live](https://ddev.com/) |
| Homepage hero | headline, buttons, platform list in a 4xl column with the terminal floated off the right edge | two columns: copy holds a minimum width, the terminal is a fixed 40rem beside it (its output is a character grid that can't reflow, so it can only be clipped, never squeezed), clipped to a peek between `md` and the width where both fit, hidden below `md`. Headline now names Node.js alongside PHP; the platform badges came out (#439) | [preview](https://20260729-stasadev-revamp.ddev-com-front-end.pages.dev/) | [live](https://ddev.com/) |
| Homepage stack logos | eight logos with `p-10` each, wrapping onto two lines at full width | one row spaced with a gap instead of per-logo padding, and the whole set is a data array — all eight fit on one line | [preview](https://20260729-stasadev-revamp.ddev-com-front-end.pages.dev/) | [live](https://ddev.com/) |
| Blog post | full-width feature image above the post, "Posted In" as the only thing in the right column | feature image beside the title, categories as pills under it, and a sticky sidebar with a newsletter callout and Similar Posts. The post itself starts at the top of the page | [preview](https://20260729-stasadev-revamp.ddev-com-front-end.pages.dev/blog/release-v1-25-3/) | [live](https://ddev.com/blog/release-v1-25-3/) |
| Blog listing | SVG feature images letterboxed inside the card while photos filled it | SVG cards fill the box the same way, and the six release/how-to banner SVGs were re-canvassed to 3:2 with side padding so nothing is cropped and nothing touches the edge | [preview](https://20260729-stasadev-revamp.ddev-com-front-end.pages.dev/blog/) | [live](https://ddev.com/blog/) |
| `/download` | a list of files and nothing else | sidebar with the release it's showing, release notes, all releases, checksums, installation steps, and a "Need Help?" card | [preview](https://20260729-stasadev-revamp.ddev-com-front-end.pages.dev/download/) | [live](https://ddev.com/download/) |
| `/get-started` | instructions only; if a step failed you had to go looking | same "Need Help?" card, sticky beside the instructions | [preview](https://20260729-stasadev-revamp.ddev-com-front-end.pages.dev/get-started/) | [live](https://ddev.com/get-started/) |
| `/sponsor` | tier cards with their own black-and-white buttons (no dark-mode hover); PayPal and invoicing buried in prose | "Ways to Sponsor" sidebar — GitHub Sponsors, PayPal, invoice or transfer — plus "Other Ways to Help"; tier cards now use the site's own buttons | [preview](https://20260729-stasadev-revamp.ddev-com-front-end.pages.dev/sponsor/) | [live](https://ddev.com/sponsor/) |
| `/about` | five oversized stats stacked in a bare column | the same numbers in a "DDEV Today" sidebar card, and the story now ends with the sponsorship ask | [preview](https://20260729-stasadev-revamp.ddev-com-front-end.pages.dev/about/) | [live](https://ddev.com/about/) |
| `/usage-stats` | a long single column with no way to jump between sections | "On This Page" index beside the charts, sponsorship ask at the end | [preview](https://20260729-stasadev-revamp.ddev-com-front-end.pages.dev/usage-stats/) | [live](https://ddev.com/usage-stats/) |
| `/brand`, `/contact`, `/foundation`, `/privacy` | plain markdown column, nothing beside it | "On This Page" index, opt-in per page with `index: true` in frontmatter; `/foundation` also ends with the sponsorship ask | [preview](https://20260729-stasadev-revamp.ddev-com-front-end.pages.dev/foundation/) | [live](https://ddev.com/foundation/) |
| Footer | one flat list mixing social accounts with pages, with Discord, GitHub and the blog appearing twice and the feeds in the middle of it | three bands: logo and social icons, then Product / Community / Project columns, then the copyright line with Privacy and the RSS/JSON feeds | [preview](https://20260729-stasadev-revamp.ddev-com-front-end.pages.dev/) | [live](https://ddev.com/) |

## What's new

- `NewsletterCallout` and `SimilarPosts` in the blog post sidebar, and
  `CategoryPills` shared by the post and its cards.
- `PageIndex`, an "On This Page" nav built in the browser from the page's own
  `h2` ids, so it can't drift from the content.
- `SponsorCTA`, one sponsorship ask with one look and one top margin, on
  `/about`, `/foundation`, `/usage-stats` and the end of each Get Started
  walkthrough. It replaces `quickstart/CommunityCTA`, which said much the same
  thing in a different box.
- `SidebarLinks`, `HelpLinks`, `ReleaseLinks`, `SponsorWays` for the sidebar
  cards, and `size="small"` on `CtaButton` for buttons in a sidebar.
- `lib/posts.ts` (ordering, adjacent posts, similarity) and `lib/images.ts`
  (the `public/img` glob that three components were each declaring).
- CSS: `.site-container` / `.site-gutter`, `.page-grid` / `.content-column` /
  `.sidebar-column`, `.sidebar-card` / `.sidebar-label`, `.sponsor-cta`.

## Notes

- The newsletter callout beside the post and the shape of the new footer were
  inspired by https://upsun.com/blog/ai-fatigue-engineering-teams/.
- Similar Posts ranks by what the posts say, not just their categories: a
  tf-idf vector per post over its title, summary, categories and body, compared
  by cosine similarity, with a shared category and a shared author as smaller
  nudges. Categories alone were far too coarse — nine of them cover 140 posts,
  so every release note matched every other one equally. The list cuts off
  relative to its best match, so a post on a subject nothing else covers shows
  three good matches instead of five padded ones, and newsletters only match
  other newsletters (a monthly digest has a word in common with almost
  everything).
- Every page above was checked against the dev server, and the new `@apply`
  utilities were checked in the compiled CSS.

🤖 Developed with assistance from [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 29, 2026

Copy link
Copy Markdown

Deploying ddev-com-front-end with  Cloudflare Pages  Cloudflare Pages

Latest commit: c40ae4d
Status: ✅  Deploy successful!
Preview URL: https://025618cb.ddev-com-front-end.pages.dev
Branch Preview URL: https://20260729-stasadev-revamp.ddev-com-front-end.pages.dev

View logs

@stasadev stasadev changed the title layout: one width for every page, blog post sidebar, rebuilt footer layout: one width for every page, blog post sidebar, rebuilt footer, fixes #161, fixes #439 Jul 29, 2026

@rfay rfay left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing. The blog page is so very much better and readable, without the distraction of the huge featureImage. It's all so great. Love the "Similar Posts".

What an amazing improvement!

@stasadev
stasadev merged commit 44ef579 into main Jul 29, 2026
5 checks passed
@stasadev
stasadev deleted the 20260729_stasadev_revamp branch July 29, 2026 17:27
@rfay

rfay commented Jul 30, 2026

Copy link
Copy Markdown
Member

Somehow this didn't work the same everywhere. Some examples:

image image

This one was one of the preview examples, and it's fine. I guess I was thinking that all the blogs were reorganized this way.

image

@stasadev

stasadev commented Jul 30, 2026

Copy link
Copy Markdown
Member Author

Somehow this didn't work the same everywhere

ddev.com is scaled here:

image

This results in a mobile view (the nav bar is hidden) at a wider width.

peek

I opened:

stasadev added a commit to stasadev/ddev.com that referenced this pull request Jul 30, 2026
## The Issue

Follow-up to the review on ddev#704. The header nav and the blog post title both
switched to their narrow layouts at `lg` (1024px). Browser zoom shrinks the
viewport in CSS pixels, so at 110-125% a 1200px window falls under that and
the nav collapsed wholesale under the menu button.

`w-2/3` on the nav's right-hand wrapper capped its contents at two thirds of
the container, which is why the threshold had to be that high.

The byline's edit link was anchored to the full 72rem `site-container` instead
of the text, landing about 26rem past the end of it on posts with no feature
image.

## How This PR Solves The Issue

- Nav links come from one array rendered into both the bar and the menu. A
  script measures them and drops links from the end until the rest fit, moving
  each one into the menu. The button shows only when something is hidden.
  Without the script the markup still falls back to `hidden lg:flex`.
- Nothing in the bar may shrink, or the measurements come back compressed and
  report room that isn't there. The menu button's width stays reserved while
  it's hidden, so the result can't oscillate.
- `.title-grid` puts the blog title beside its feature image from 52rem, with
  the image column at `clamp(16rem, 36%, 25rem)` so it shrinks instead of
  stacking.
- The byline row is capped at `--reading-measure`.

## Manual Testing Instructions

1. `ddev npm run dev`
2. Drag the window from 1400px to 320px: links should leave the bar one at a
   time and appear in the menu, with the logo never compressed.
3. At 1200px, zoom to 110%, 125% and 150%: as many links as fit at each.
4. Compare /blog/release-v1-25-3/ against a post with no feature image, at
   1400px, 900px and 700px.
5. With JavaScript off, all links above 1024px and the button below it.

## Release/Deployment Notes

None.

🤖 Developed with assistance from [Claude Code](https://claude.ai/code)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
stasadev added a commit to stasadev/ddev.com that referenced this pull request Jul 30, 2026
## The Issue

Follow-up to the review on ddev#704. The header nav and the blog post title both
switched to their narrow layouts at `lg` (1024px). Browser zoom shrinks the
viewport in CSS pixels, so at 110-125% a 1200px window falls under that and
the nav collapsed wholesale under the menu button.

`w-2/3` on the nav's right-hand wrapper capped its contents at two thirds of
the container, which is why the threshold had to be that high.

The byline's edit link was anchored to the full 72rem `site-container` instead
of the text, landing about 26rem past the end of it on posts with no feature
image.

## How This PR Solves The Issue

- Nav links come from one array rendered into both the bar and the menu. A
  script measures them and drops links from the end until the rest fit, moving
  each one into the menu. The button shows only when something is hidden.
  Without the script the markup still falls back to `hidden lg:flex`.
- Nothing in the bar may shrink, or the measurements come back compressed and
  report room that isn't there. The menu button's width stays reserved while
  it's hidden, so the result can't oscillate.
- `.title-grid` puts the blog title beside its feature image from 52rem, with
  the image column at `clamp(16rem, 36%, 25rem)` so it shrinks instead of
  stacking.
- The byline row is capped at `--reading-measure`.

## Manual Testing Instructions

Preview: https://pr-REPLACE_ME_WITH_PR_NUMBER.ddev-com-fork-previews.pages.dev/

1. Drag the window from 1400px to 320px: links should leave the bar one at a
   time and appear in the menu, with the logo never compressed.
2. At 1200px, zoom to 110%, 125% and 150%: as many links as fit at each.
3. Compare `/blog/release-v1-25-3/` against a post with no feature image, at
   1400px, 900px and 700px.
4. With JavaScript off, all links above 1024px and the button below it.

## Release/Deployment Notes

None.

🤖 Developed with assistance from [Claude Code](https://claude.ai/code)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
stasadev added a commit to stasadev/ddev.com that referenced this pull request Jul 30, 2026
## The Issue

Follow-up to the review on ddev#704. The header nav and the blog post title both
switched to their narrow layouts at `lg` (1024px). Browser zoom shrinks the
viewport in CSS pixels, so at 110-125% a 1200px window falls under that and
the nav collapsed wholesale under the menu button.

`w-2/3` on the nav's right-hand wrapper capped its contents at two thirds of
the container, which is why the threshold had to be that high.

The byline's edit link was anchored to the full 72rem `site-container` instead
of the text, landing about 26rem past the end of it on posts with no feature
image.

## How This PR Solves The Issue

- Nav links come from one array rendered into both the bar and the menu. A
  script measures them and drops links from the end until the rest fit, moving
  each one into the menu. The button shows only when something is hidden.
  Without the script the markup still falls back to `hidden lg:flex`.
- Nothing in the bar may shrink, or the measurements come back compressed and
  report room that isn't there. The menu button's width stays reserved while
  it's hidden, so the result can't oscillate.
- `.title-grid` puts the blog title beside its feature image from 52rem, with
  the image column at `clamp(16rem, 36%, 25rem)` so it shrinks instead of
  stacking.
- The byline row is capped at `--reading-measure`.

## Manual Testing Instructions

Preview: https://pr-REPLACE_ME_WITH_PR_NUMBER.ddev-com-fork-previews.pages.dev/

1. Drag the window from 1400px to 320px: links should leave the bar one at a
   time and appear in the menu, with the logo never compressed.
2. At 1200px, zoom to 110%, 125% and 150%: as many links as fit at each.
3. Compare `/blog/release-v1-25-3/` against a post with no feature image, at
   1400px, 900px and 700px.
4. With JavaScript off, all links above 1024px and the button below it.

## Release/Deployment Notes

None.

🤖 Developed with assistance from [Claude Code](https://claude.ai/code)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
stasadev added a commit to stasadev/ddev.com that referenced this pull request Jul 30, 2026
## The Issue

Follow-up to the review on ddev#704. The header nav and the blog post title both
switched to their narrow layouts at `lg` (1024px). Browser zoom shrinks the
viewport in CSS pixels, so at 110-125% a 1200px window falls under that and
the nav collapsed wholesale under the menu button.

`w-2/3` on the nav's right-hand wrapper capped its contents at two thirds of
the container, which is why the threshold had to be that high.

The menu behind that button was a `div` only the script could reveal, so with
JavaScript off there was no way to reach the nav links below 1024px at all.

The byline's edit link was anchored to the full 72rem `site-container` instead
of the text, landing about 26rem past the end of it on posts with no feature
image.

## How This PR Solves The Issue

- Nav links come from one array rendered into both the bar and the menu. A
  script measures them and drops links from the end until the rest fit, moving
  each one into the menu. The button shows only when something is hidden.
  Without the script the markup still falls back to `hidden lg:flex`.
- The menu is a `details`/`summary`, so it opens with JavaScript off and the
  script keeps no open/close code of its own. The separate close button is
  gone; the summary toggles.
- Nothing in the bar may shrink, or the measurements come back compressed and
  report room that isn't there. The menu's width stays reserved while it's
  hidden, so the result can't oscillate.
- `.title-grid` puts the blog title beside its feature image from 52rem, with
  the image column at `clamp(16rem, 36%, 25rem)` so it shrinks instead of
  stacking.
- The byline row is capped at `--reading-measure`.

## Manual Testing Instructions

Preview: https://pr-REPLACE_ME_WITH_PR_NUMBER.ddev-com-fork-previews.pages.dev/

1. Drag the window from 1400px to 320px: links should leave the bar one at a
   time and appear in the menu, with the logo never compressed.
2. At 1200px, zoom to 110%, 125% and 150%: as many links as fit at each.
3. Compare `/blog/release-v1-25-3/` against a post with no feature image, at
   1400px, 900px and 700px.
4. With JavaScript off: all links above 1024px, and below it the button opens
   the menu.

## Release/Deployment Notes

None.

🤖 Developed with assistance from [Claude Code](https://claude.ai/code)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Animation is way too big now Increase the hero and nav bar width on larger screens 1024px and up.

2 participants