Skip to content

Add a Pulumi Design Guidelines guide for component authors#19779

Draft
joeduffy wants to merge 1 commit into
masterfrom
joeduffy/design_guidelines
Draft

Add a Pulumi Design Guidelines guide for component authors#19779
joeduffy wants to merge 1 commit into
masterfrom
joeduffy/design_guidelines

Conversation

@joeduffy

Copy link
Copy Markdown
Member

What this adds

A new multi-page Pulumi Design Guidelines guide under Building & Extending, covering how to design components and packages well — as distinct from the mechanics of building them, which the existing component and packaging guides already cover. It is prescriptive rather than reference, organized around scannable DO / CONSIDER / AVOID / DON'T recommendations (a convention borrowed from the .NET Framework Design Guidelines).

Eight pages:

  1. Introduction (_index.md) — philosophy, audience, how to read the conventions
  2. Choosing the right abstraction — the Goldilocks altitude; when not to build a component
  3. Naming — type tokens and properties projected across languages; child naming
  4. Designing inputs and outputs — args shape, secure defaults, Input<T>, secrets, stable contracts
  5. Composition and resource structureparent, option propagation, components-of-components
  6. Single- vs. multi-cloud abstractions — when portability earns its keep vs. lowest-common-denominator
  7. Designing for multiple languages — the serialization boundary, representable types, enums, schema-driven docs
  8. Versioning and evolution — semver, breaking changes, defaults-as-contract, deprecation, aliases

The guidance is grounded in how Pulumi's own component libraries are designed (AWSX's high-level VPC inputs and sensible defaults; EKS's exposed kubeconfig and escape hatches).

Implementation notes

  • New guideline shortcode (layouts/shortcodes/guideline.html) renders the four color-coded callouts. It reuses the existing .note container and adds per-type color + icon (check-circle / lightbulb / warning / prohibit); the recommendation text supplies the bold lead word, which the styles then color.
  • Styles live in the SCSS source (theme/src/scss/_notes.scss), since the committed assets/css/bundle.css is a generated artifact. The red semantic color trio already existed in _theme.scss. Reviewers running make serve/make build will get the recompiled bundle automatically.
  • Nav: Design Guidelines sits immediately after Components (the natural next step once you can build one); surrounding section weights shift by one.

Verification

  • make lint — 0 markdown errors, prettier clean
  • make lint-prose (Vale) — 0 errors; only nag-level write-good warnings remain
  • Hugo build — exit 0, no template errors; all 8 pages render; callouts produce correct classes/icons; choosers render; nav links resolve

🤖 Generated with Claude Code

@joeduffy

joeduffy commented Jun 20, 2026

Copy link
Copy Markdown
Member Author

@CamSoper @cnunciato A lot of work to make these "great," but I've been dreaming of a Pulumi (Component) Design Guidelines for quite some time, borne out of discussions with customers. I helped contribute to the .NET Design Guidelines back in the early days, so that's partly where the inspiration came from ...

Would love to know what you think of the idea!

@pulumi-bot

pulumi-bot commented Jun 20, 2026

Copy link
Copy Markdown
Collaborator

@pulumi-bot

pulumi-bot commented Jun 20, 2026

Copy link
Copy Markdown
Collaborator

Lighthouse Performance Report

Commit: df5ca66 | Metric definitions

Page Device Score FCP LCP TBT CLS SI
Homepage Mobile 🔴 26 5.9s 12.2s 2623ms 0.079 9.2s
Homepage Desktop 🟡 60 0.7s 1.6s 317ms 0.283 2.5s
Install Pulumi Mobile 🟡 54 7.1s 14.2s 238ms 0.000 7.1s
Install Pulumi Desktop 🟡 80 1.1s 2.3s 22ms 0.014 2.6s
AWS Get Started Mobile 🟡 54 6.9s 14.1s 242ms 0.000 6.9s
AWS Get Started Desktop 🟡 84 1.1s 2.6s 24ms 0.031 1.1s

@joeduffy joeduffy force-pushed the joeduffy/design_guidelines branch from 6401475 to 916cd35 Compare June 20, 2026 00:57
This adds a new multi-page guide under Building & Extending covering how to
design Pulumi components and packages well, as distinct from the mechanics of
building them that the existing component and packaging guides already cover.
The guide is prescriptive rather than reference: it is organized around
scannable DO / CONSIDER / AVOID / DON'T recommendations, a convention borrowed
from the .NET Framework Design Guidelines, and spans choosing the right
abstraction, naming, inputs and outputs, composition, single- versus
multi-cloud, multi-language ergonomics, and versioning.

The recommendation callouts are a new `guideline` shortcode. Rather than
duplicate the existing note layout, it reuses the `.note` container and adds
four color-coded variants and a per-type icon; the recommendation text supplies
the bold lead word, which the styles then color. The variant styles live in the
SCSS source under theme/, since the committed bundle.css is a generated
artifact and editing it directly would not survive a build.

The guidance is grounded in how Pulumi's own component libraries are designed —
AWSX's high-level VPC inputs and sensible defaults, EKS's exposed kubeconfig and
escape hatches — so the recommendations reflect practice rather than theory.

Design Guidelines sits immediately after Components in the nav, since it is the
natural next step once an author knows how to build one; the surrounding
section weights shift by one to make room.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@joeduffy joeduffy force-pushed the joeduffy/design_guidelines branch from 916cd35 to df5ca66 Compare June 20, 2026 01:02
@joeduffy

Copy link
Copy Markdown
Member Author

@claude Review this.

@pulumi-bot

pulumi-bot commented Jun 21, 2026

Copy link
Copy Markdown
Collaborator

Claude finished @joeduffy's task in 3m 42s —— View job


PR Review: Pulumi Design Guidelines

  • Read all changed files
  • Review shortcode implementation
  • Review SCSS changes
  • Review nav/menu changes
  • Review content quality and accuracy
  • Compile and post findings

This is a high-quality addition. The structure is sound, the DO/CONSIDER/AVOID/DON'T framing is implemented consistently, and the guidance is grounded in real AWSX/EKS patterns rather than invented examples. A few things to address before merging:


Broken links (must fix)

Two See also entries point to a URL that doesn't exist:

/docs/tutorials/abstraction-encapsulation/

The tutorial lives at content/tutorials/abstraction-encapsulation/, which Hugo renders as /tutorials/abstraction-encapsulation/ (no /docs/ prefix). There is no alias mapping it to /docs/tutorials/....

Affected files:

  • content/docs/iac/guides/building-extending/design-guidelines/_index.md (line 73)
  • content/docs/iac/guides/building-extending/design-guidelines/abstraction.md (line 197)

Fix this →


Minor issues

Python consumer examples use raw dict style (abstraction.md lines 70–75, single-vs-multi-cloud.md lines 98–105)

vpc = Vpc("app", {
    "cidr_block": "10.0.0.0/16",
    "number_of_availability_zones": 3,
})

This is valid, but inputs-and-outputs.md teaches readers to define StaticPageArgs as a TypedDict and pass it as a typed object. The consumer-side examples here using raw dicts quietly contradict that teaching. Preferred form would be Vpc("app", VpcArgs(cidr_block=..., ...)). Not a blocker, but worth aligning.

composition.mdregisterOutputs timing statement is slightly overstated (line 159)

"Children registered past that point race against the completion signal and can be missed in the component's reported state."

Children created after registerOutputs will still register with the engine — they won't be silently dropped. What they won't appear in is the component's declared outputs (the dict you pass to registerOutputs). The actual hazard is subtler: you get an incomplete output snapshot, not missing resources. Recommend adjusting the wording to avoid alarming readers unnecessarily.

versioning-and-evolution.md — prose alias example is language-ambiguous (line 173)

Adding aliases: [{ name: "${name}-storage" }]...

The ${name}-... template syntax is TypeScript/JavaScript. At minimum a brief clarifying phrase like "in TypeScript, for example" would help. A small code snippet (even one tab) would be clearest, consistent with how all other concrete examples in this guide are presented.


Implementation

guideline.html shortcode — clean, well-commented for a shortcode (the usage example in the comment earns its keep), and the four icon choices (check-circle, lightbulb, warning, prohibit) map naturally onto the four severity levels.

_notes.scss — correct nesting (&.guideline-do inside .note {}), reuses the existing color variable triples consistently. The var(--color-red-*) trio for DON'T reads with appropriate weight vs. AVOID's orange.

Nav weightsmenus.yml correctly shifts Providers from 3→4 and Using Existing Tools from 4→5; packages/_index.md shifts 2→3; Design Guidelines enters at weight 2 between Components and Packages. The ordering is logical.


What's working well

The content itself is excellent:

  • Altitude calibration (abstraction.md) — the "name test" heuristic, the escape-hatch vs. altitude tension, and the warning about tag propagation being repeatedly filed against AWSX are all things that will actually help authors who've never had this feedback before.
  • Multi-language property naming (naming.md) — showing all five projections of numberOfAvailabilityZones in one chooser block is worth a thousand words.
  • Secrets propagation rule (inputs-and-outputs.md) — the "propagate secretness from inputs into derived outputs" guideline is easy to miss and important to get right.
  • URN identity framing (composition.md) — calling out that renaming a child in a released component destroys live resources is the highest-stakes piece of operational knowledge in this whole guide, and it's placed and contextualized well.
  • "YAML is a consumer too" (designing-for-languages.md) — excellent litmus test. Concise and actionable.
  • Defaults are part of the contract (versioning-and-evolution.md) — this framing elevates the default-change hazard from an implementation detail to a design principle, which is exactly right.

The cross-linking between pages is dense and well-targeted — readers following any thread will land on the right continuation.
| Branch preview

@CamSoper

Copy link
Copy Markdown
Contributor

@joeduffy The .NET Design Guidelines framing is a natural fit here -- the DO/CONSIDER/AVOID/DON'T taxonomy works really well for this kind of prescriptive guidance. The "defaults are part of the contract" and URN identity sections especially are things I wish existed in written form earlier.

FYI, the @claude trigger runs a lighter review pass. For the full detailed treatment with agent-based fact-checkers, you'll need to move this out of draft.

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.

3 participants