Skip to content

Add a /learn hub page and collapse nav and footer onto it - #20698

Draft
jeffmerrick wants to merge 13 commits into
masterfrom
jeffmerrick/learn-page
Draft

Add a /learn hub page and collapse nav and footer onto it#20698
jeffmerrick wants to merge 13 commits into
masterfrom
jeffmerrick/learn-page

Conversation

@jeffmerrick

@jeffmerrick jeffmerrick commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Closes the docs half of pulumi/marketing#1792: a single front door at /learn that points at every learning resource — the Dev Hub, Pulumi Academy, the get-started path, workshops, and the blog's series and tutorials.

Important

This PR stacks on two open PRs and should not merge before them. The diff below includes their commits.

  • Surface recent blog posts and the next event on the homepage #20665 (jeffmerrick/issue-20584-latest-on-homepage) — hard dependency. Provides the portable events/event-card.html, events/upcoming.html, and renderEventCountdowns() running outside .template-event-list.
  • Add a copy-prompt agent CTA to the homepage hero #20662 (jeffmerrick/issue-20327-homepage-agent-cta) — soft dependency. Provides static/onboard.md and the generic theme/src/ts/copy-text.ts clipboard module that the "For agents" half uses. If it doesn't land, dropping the agents: key from content/learn/_index.md removes that half and nothing else changes.

Once both are on master, this branch just needs a rebase.

It also should not go live before pulumi/marketing-web#82. That's the Dev Hub itself, in a different repo, so it isn't a merge-order dependency in git terms — but /dev-hub/ 404s until it ships, and this PR links it from the spotlight card and the site footer. If that PR slips, either hold this one or drop the two Dev Hub links and add them back later.

What's here

/learn was an alias. It was declared on content/tutorials/_index.md, so /learn 302'd to /tutorials/. That entry is removed — Hugo would otherwise emit a duplicate-target-path warning and pick an order-dependent winner. The 32 deeper /learn/<tutorial>/ aliases on child pages sit below the new page's path and are unaffected (verified: /learn/embedding-pulumi/ still redirects to /tutorials/embedding-pulumi/).

A bespoke section page, modeled on State of Agentic Infrastructure rather than the template-partials system. All content lives in content/learn/_index.md frontmatter; layouts/learn/list.html dispatches each top-level key to a partial in the private layouts/partials/learn/ namespace, so a section disappears by dropping its key. Styling is inline Tailwind over the shared primitives (.card, .card-highlight, .btn, .badge, the heading-*/body-* scale) — no new SCSS file. /learn is outside /docs, so no dark-mode pass applies.

Page composition:

  1. Hero — the centered h1 + description pattern from /case-studies/.
  2. Spotlight — Dev Hub and Pulumi Academy as two dark violet-950 cards with centered copy and bottom-aligned CTAs.
  3. New to Pulumi? — For humans and For agents, split across one card. The human half is four cloud links over a Get started link; the agent half is the onboarding prompt and a copy control sharing one outlined box, plus links to Agent Skills and the Pulumi MCP server. Per AGENTS.md §"AI and agent positioning", it names Claude Code, Cursor, and Codex as first-class rather than presenting Neo as the only option.
  4. Workshops and events — upcoming events (capped at half the grid) then curated on-demand recordings.
  5. Blog series — four curated series, beginner-first.
  6. Latest tutorials — the four newest posts in the tutorials category.

layouts/partials/events/on-demand.html is new: the mirror of events/upcoming.html (past, has a youtube_url, newest-first). The events grid uses it to back-fill any curated slug that no longer resolves, so a deleted or renamed event can never leave a hole.

Nav and footer collapse onto the new page. In the header's "For engineers", Templates, Tutorials, and Pulumi guides become one Learn entry. Its icon is compass, not graduation-cap — that one reads as Pulumi Academy. In the footer's Resources column, Templates, Tutorials, and Guides become Learn, with Dev Hub and Pulumi Academy listed under it.

Meta image is generated on-brand at build time (titleSection("learn", false) in scripts/generate-meta-images.mjs); no meta_image in frontmatter.

Changes outside /learn

Three shared-partial fixes fell out of building the page. Each is a strict improvement on its own and affects the blog:

  • blog/post-meta.html — bylines no longer wrap oddly at any card width, without the caller having to know how wide its grid is. Each bullet is grouped with the segment it introduces, so a separator can't be stranded at the end of a line (the original bug: a dangling ). Reading time drops out below a 22rem container query, which is roughly where the full byline stops fitting. Below that the author name truncates, since it's the only variable-width segment. This is the theme's first container-query use — Tailwind v4 ships them in core, no plugin needed.
  • shared/_badge.scss.badge gets font-normal. The weight was inherited before, so a badge composed onto a heading or inside a <strong> rendered bold and stopped looking like a badge.
  • blog/avatars.htmlmin-w-0 and a truncating label, so the name is what gives in a narrow card.

Verification

  • make build — no duplicate-target-path warning for /learn, no fingerprinted-asset panic, and the meta-image generator picks up the new section.
  • make lint — clean.

Worth a look on a local server: /learn/ end to end, /tutorials/ with its child aliases, the copy-prompt button writing to the clipboard, and the blog's own card grids to confirm the byline change reads correctly there.

🤖 Generated with Claude Code

jeffmerrick and others added 9 commits August 3, 2026 11:50
Groups the hero's Get started / Download open source buttons into a
"For humans" card and adds a "For agents" card beside it, whose single
button copies a one-line onboarding prompt for a coding agent. Hosts the
prompt's target as a static /onboard.md.

Extracts the hero CTA row into partials/hero-ctas.html, now shared by the
split and centered layouts, and drops the arrow icon from the primary CTA.

Co-Authored-By: Claude <noreply@anthropic.com>
Between sm and md the two CTA cards have stacked but the buttons are still
in a row, so the "For humans" buttons hugged their text and left ~218px of
the card empty. Stretch them across it in that band only.

Also widens the hero's text column to 55% (visual to 40%) and caps the
secondary title at max-w-lg.

Co-Authored-By: Claude <noreply@anthropic.com>
The button showed the prompt itself, truncated, which clipped to a few
useless words at desktop widths. Show a short label instead and let the
tooltip and the clipboard carry the full prompt.

The card now hugs the button rather than growing into the leftover space,
and the button carries a min-width so it holds its size when the label
swaps to the copied state. Also restores the arrow on Get started.

Co-Authored-By: Claude <noreply@anthropic.com>
Adds a "What's new at Pulumi" section near the bottom of the homepage: a
three-tile row of the latest blog posts (excluding the general category)
with the next upcoming event in the last slot, falling back to three posts
when nothing is coming up.

Reuses the existing card partials rather than inventing new tiles. To make
the event card usable outside /events/, it now derives its own link and
date from the event page and renders just the <article>; the filterable
<li> moved to events/event-list-item.html, and the "what's upcoming" query
moved to events/upcoming.html so the list page and the homepage can't
drift. blog/feed.html exposes its non-general post pool, and the new
blog/card/contained.html boxes the medium card in a .card so it sits
alongside the event tile. The countdown badge renderer is no longer gated
on the events list.

Refs #20584

Co-Authored-By: Claude <noreply@anthropic.com>
navigator.clipboard only exists in a secure context, so on the plain-HTTP
S3 preview builds it is undefined, writeText threw, and the button did
nothing at all — not even the copied confirmation. Fall back to a selected
off-screen textarea, and only report success when the write actually
landed.

Also widens the prompt tooltip, which was pinned to the button and got
narrow when the button shrank to a short label.

Co-Authored-By: Claude <noreply@anthropic.com>
Size it to nothing with no border or padding, and hide it from assistive
tech and the tab order, so there is nothing to render even if a browser
ignores the off-screen offset.

Co-Authored-By: Claude <noreply@anthropic.com>
/learn becomes the single front door to every Pulumi learning resource:
the Dev Hub, Pulumi Academy, the get-started path, workshops, and the
blog's series and tutorials. Closes the docs half of
pulumi/marketing#1792.

It was previously an alias on content/tutorials/_index.md, which had to
go before a real page could live at that path (Hugo would otherwise emit
a duplicate-target-path warning and pick an order-dependent winner). The
32 deeper /learn/<tutorial>/ aliases on child pages sit below the new
page's path and are unaffected.

The page is a bespoke section layout modeled on State of Agentic
Infrastructure, not a template-partials page: all content lives in
content/learn/_index.md frontmatter and each top-level key dispatches to
a partial in the private learn/ namespace, so a section disappears by
dropping its key. Styling is inline Tailwind over the shared primitives
(.card, .card-highlight, .btn, the heading-*/body-* scale) — no new SCSS.

Also adds events/on-demand.html, the mirror of events/upcoming.html, so
the events grid can back-fill any curated slug that no longer resolves
and never renders a hole.

Nav and footer collapse onto the new page: "Templates", "Tutorials", and
"Pulumi guides" become one "Learn" entry (icon `compass`, since
`graduation-cap` reads as Academy), and the footer's Resources column
replaces "Templates", "Tutorials", and "Guides" with "Learn".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Design pass on the new page:

- The two spotlight cards go dark (violet-950), so the headline
  destinations anchor the top of the page against the lighter sections
  below. The illustrations' palette is inverted to suit: the faint outer
  frames drop from violet-200 to violet-800, and the glyph rises from
  violet-700 to violet-200, preserving the original hierarchy. These are
  permanently dark cards, not a dark-mode variant — /learn is outside
  /docs, so there is no theme toggle and no second set of assets.
- Spotlight content is centered, the headings step up to heading-2, and
  the CTAs become btn-xl buttons pinned to the foot of the card, so both
  land on the same baseline whatever the copy above them does. The
  external-link icon comes off Pulumi Academy.
- "New to Pulumi?" sits on a shared card-highlight panel, with both
  children on the same violet-50 fill so the group reads as one surface.
  Its lead line moves into the For humans card, where it belongs.
- Cloud links become btn-outline tiles (stronger border, white against
  the violet ground) carrying the icon-only 32x32 marks rather than the
  wordmark SVGs. Get started matches the agent card's links as a
  btn-link.
- Section headings below the spotlight take the font-overline treatment
  the blog's rows already use, with the in-card labels as h3s under them.
- The agent card shows the onboarding prompt in full in a code block
  above the copy button, so the reader can see what they're handing
  their agent before they hand it over.
- Latest tutorials shows four posts in a 4-column grid, matching the
  series row above it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@pulumi-bot

pulumi-bot commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Your site preview for commit 5352662 is ready! 🎉

http://www-testing-pulumi-docs-origin-pr-20698-5352662d.s3-website.us-west-2.amazonaws.com

Changed pages:

@pulumi-bot

pulumi-bot commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Lighthouse Performance Report

Commit: 5352662 | Metric definitions

Page Device Score FCP LCP TBT CLS SI
Homepage Mobile 🔴 34 3.2s 8.7s 1865ms 0.000 8.1s
Homepage Desktop 🟢 90 0.8s 1.0s 204ms 0.033 1.4s
Install Pulumi Mobile 🟡 57 6.1s 9.3s 62ms 0.054 8.2s
Install Pulumi Desktop 🟡 84 1.4s 2.1s 0ms 0.016 1.6s
AWS Get Started Mobile 🟡 56 6.0s 8.5s 42ms 0.087 8.1s
AWS Get Started Desktop 🟡 81 1.3s 1.9s 0ms 0.049 2.9s

Copy: Pulumi Academy has one course, so "guided video courses taught by
the Pulumi team" overclaimed on every axis. The card now describes the
experience rather than a catalog ("Learn by watching..."), the CTA is
"Start watching" rather than "Start a course", and the plural is gone
from the hero, the meta description, and the nav item. The agent card's
lead loses "coding" to stop it widowing a word; the three named agents
carry that meaning already.

Bylines no longer wrap oddly at any card width, without the caller
having to know how wide its grid is. Each bullet is grouped with the
segment it introduces, so a separator can't be stranded at a line end;
reading time drops out below a 22rem container query, which is roughly
where the full byline stops fitting; and below that the author name
truncates, since it's the only variable-width segment. This is the
theme's first container-query use — Tailwind v4 ships them in core.

Badges get font-normal in the shared .badge base. The weight was
inherited before, so a badge composed onto a heading or inside a
<strong> rendered bold and stopped looking like a badge.

Layout: the spotlight and "New to Pulumi?" group tighter than the page's
rhythm and sit above a full-width rule, which lives between two
containers rather than inside one — a full-bleed break-out would need
100vw and overflow by the width of the scrollbar. Inside the card, the
cloud grid and the prompt box carry mt-auto themselves rather than their
CTAs, so both settle onto the same baseline when one description wraps
and the other doesn't. The prompt and its copy control share one
outlined box, repainted light.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The two destinations /learn spotlights get their own footer entries,
directly under Learn in the Resources column, so readers who already
know where they're going don't have to route through the hub.

Plain links, matching the column's existing convention — the Slack,
support, and brand entries are all absolute URLs without target
attributes, so Academy follows suit rather than being a one-off.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
One conflict, in the homepage frontmatter: master moved the hero badge on
to the Terraform/HCL release while this branch (via the stacked #20662)
added the For humans / For agents CTA keys to the same block. Both are
wanted, so the resolution is the union — master's newer badge, this
branch's CTA keys.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants