🌐 US-Proxy
class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
Skip to content

feat(site/src/pages/TemplateBuilder): auto-fill customization fields from base template - #27272

Merged
jeremyruppel merged 1 commit into
mainfrom
jeremy/devex-586-auto-fill-customization-fields-from-selected-base-template
Jul 22, 2026
Merged

feat(site/src/pages/TemplateBuilder): auto-fill customization fields from base template#27272
jeremyruppel merged 1 commit into
mainfrom
jeremy/devex-586-auto-fill-customization-fields-from-selected-base-template

Conversation

@jeremyruppel

@jeremyruppel jeremyruppel commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Closes DEVEX-586.

The Template Builder wizard's final Customizations step rendered empty inputs for ID, Display name, Description, and Icon. This seeds those fields with sensible defaults derived from the selected base template, while keeping every field editable.

Changes

All frontend, in site/src/pages/TemplateBuilder/wizardState.ts:

  • SelectedBaseMeta now carries description, mapped in toSelectedBaseMeta.
  • New pure helper baseCustomizationDefaults(base) maps the base to { name: base.id, displayName: base.name, description, icon }.
  • SET_BASE seeds the four customization fields when the base changes (still clearing base variable values). Re-selecting the same base preserves user edits.
  • initWizardState seeds the same defaults for the ?base= deeplink entry path.
  • RESET_CUSTOMIZATIONS (fired on back-navigation) now resets only organization/provisioner state, so auto-filled values survive stepping back and forth.

No change was needed in TemplateCustomizationsStep.tsx; it already binds to these state fields, so seeded values render and stay editable. Existing placeholders remain as the fallback when a base value is empty (e.g. scratch).

Default mapping

Form field State key Source
ID name base.id
Display name displayName base.name
Description description base.description
Icon icon base.icon

base.id is used for the ID field because base ids are already valid template slugs (docker, aws-linux, ...). Icon values are already served asset paths (/icon/*, /emojis/*), so no lookup map is needed.

Testing

  • wizardState.test.ts: 27 passing, including new coverage for seeding, base-change re-seed, same-base edit preservation, RESET_CUSTOMIZATIONS, initWizardState, toSelectedBaseMeta, and baseCustomizationDefaults.
  • biome check clean; tsc --noEmit clean.
Screenshot 2026-07-15 at 2 17 19 PM
Implementation plan

DEVEX-586: Auto-fill customization fields from selected base template

Goal

In the Template Builder wizard, the final Customizations step currently renders empty inputs for Display name, Description, ID, and Icon. Pre-populate these with sensible defaults derived from the selected base template, while keeping every field editable. Organization is already auto-selected when a single org is available, so it is out of scope beyond leaving it untouched.

Source: Linear DEVEX-586 (Ben Potter): "Would love if all these options ... were auto-filled and generated and can be edited versus the user manually filling it out." Fields called out: display name, description, ID, and icon.

Current behavior (findings)

Frontend lives in site/src/pages/TemplateBuilder/.

  • TemplateCustomizationsStep.tsx renders the four fields bound to state.displayName, state.description, state.name (the "ID" field), and state.icon. All start empty (initialWizardState).
  • wizardState.ts holds the state, the wizardReducer, and the SelectedBaseMeta UI type.
    • SelectedBaseMeta did not carry description.
    • toSelectedBaseMeta(base) maps the API TemplateBuilderBase into SelectedBaseMeta.
    • SET_BASE set the base and cleared baseVariableValues only when the base id changed; customization fields were left empty.
    • RESET_CUSTOMIZATIONS (dispatched by handleBack) blanked org/provisioner plus name, displayName, description, icon.
    • initWizardState(preselectedBase) seeded baseTemplateId and selectedBase for deeplinks but left customization fields empty.
  • API type TemplateBuilderBase exposes id, name, description, icon, os, variables, prerequisites.
  • Backend (coderd/templatebuilder_handler.go) builds each base from the built-in TemplateExample: id = ex.ID, name = ex.Name, description = ex.Description, icon = ex.Icon.
  • Base IDs are valid template names (lowercase, hyphen-separated): docker, kubernetes, aws-linux, aws-windows, gcp-linux, gcp-windows, azure-linux, digitalocean-linux, scratch.

Default mapping

Form field State key Default source
ID (required) name base.id
Display name displayName base.name
Description description base.description
Icon icon base.iconUrl (base.icon)
Organization organizationId unchanged (already auto-selected)

Rationale for name = base.id: base ids are guaranteed valid template slugs, whereas slugifying the human display name is lossy and can collide. The field stays editable.

Icon default: confirmed, no map needed

The API already returns normalized, served asset paths in base.icon (e.g. /icon/docker.png, /icon/aws.svg, /emojis/1f4e6.png for scratch), the same values CreateTemplatePage assigns when creating from a built-in example. IconField accepts any URL/path, so every base renders correctly. A base-id-to-icon map is unnecessary.

Implementation

Frontend-only, in wizardState.ts:

  1. Add description?: string to SelectedBaseMeta; map it in toSelectedBaseMeta.
  2. Add pure helper baseCustomizationDefaults(base) returning { name, displayName, description, icon }.
  3. SET_BASE: on base change, spread the defaults alongside the baseVariableValues: {} reset; on same-base re-selection, preserve existing values.
  4. initWizardState(preselectedBase): spread defaults into the returned state.
  5. Narrow RESET_CUSTOMIZATIONS to reset only organizationId and hasProvisioners.
  6. toCreateTemplateRequest already sends the fields, so no payload change.

Tests

Reducer unit tests in wizardState.test.ts for seeding, base-change re-seed, same-base edit preservation, RESET_CUSTOMIZATIONS, initWizardState, toSelectedBaseMeta (description carried), and baseCustomizationDefaults.

Scope / non-goals

  • No backend changes; the API already returns all needed fields.
  • Organization auto-selection is unchanged.
  • No slug transformation of display names (base id is used directly).
  • No base-id-to-icon map.

Opened by Coder Agents on behalf of @jeremyruppel.

…from base template

Seed the customizations step (ID, display name, description, icon) with
defaults derived from the selected base template, keeping every field
editable. Defaults are re-seeded when the base changes and preserved on
back-navigation and same-base re-selection.

Implements DEVEX-586.
@jeremyruppel
jeremyruppel marked this pull request as ready for review July 15, 2026 18:13
@linear-code

linear-code Bot commented Jul 15, 2026

Copy link
Copy Markdown

DEVEX-586

@jeremyruppel
jeremyruppel requested a review from aqandrew July 15, 2026 18:14
@jeremyruppel
jeremyruppel merged commit c309f4d into main Jul 22, 2026
75 of 78 checks passed
@jeremyruppel
jeremyruppel deleted the jeremy/devex-586-auto-fill-customization-fields-from-selected-base-template branch July 22, 2026 20:09
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 22, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants