fix(site/src/pages/TemplateBuilder): validate customizations form before submit - #28081
Draft
jeremyruppel wants to merge 1 commit into
Draft
fix(site/src/pages/TemplateBuilder): validate customizations form before submit#28081jeremyruppel wants to merge 1 commit into
jeremyruppel wants to merge 1 commit into
Conversation
…ore submit Convert the Template Builder customizations step to a Formik form with a Yup schema and surface aggregated validation errors in an Alert at the top of the step. This avoids inline field errors that would disrupt the horizontal two-column layout, and stops empty organization/name submissions from hitting the API with an unhelpful backend error. The wizard's Create Template button submits the step form via the form attribute. Only valid submits reach the create mutation; a genuinely invalid organization still surfaces the backend message via the existing error alert.
jeremyruppel
commented
Aug 12, 2026
| TemplateBuilderWizardState, | ||
| } from "./wizardState"; | ||
|
|
||
| export const TEMPLATE_CUSTOMIZATIONS_FORM_ID = "template-customizations-form"; |
Contributor
Author
There was a problem hiding this comment.
this feels slightly hacky to me so suggestions welcome! right now this is used to point the submit button at the form since the button lives outside this view
jeremyruppel
commented
Aug 12, 2026
|
|
||
| export const TEMPLATE_CUSTOMIZATIONS_FORM_ID = "template-customizations-form"; | ||
|
|
||
| const MAX_DESCRIPTION_CHAR_LIMIT = 128; |
Contributor
Author
There was a problem hiding this comment.
I'm not positive what the actual length limit is for descriptions (and I don't recall there being one in the template builder package). this is, in all likelihood, validated somewhere but I'm at a loss. totally fine keeping it this way but it smells like duplication
jeremyruppel
marked this pull request as ready for review
August 12, 2026 20:13
Contributor
Author
|
some good feedback in slack, so I'm going to take this back into draft for now |
jeremyruppel
marked this pull request as draft
August 13, 2026 13:51
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the unhelpful backend error when creating a template in the Template Builder with no organization selected (DEVEX-744).
The customizations step is now a Formik form with a Yup schema. Validation runs on submit and errors are aggregated in a single
Alertat the top of the step, rather than inline under fields, which preserves the horizontal two-column layout. Only valid submits reach the create API, so an empty organization now shows "Select an organization to continue." instead of hitting the backend. A genuinely invalid selection still surfaces the backend's message via the existing error alert.Changes
TemplateCustomizationsStep.tsx: Formik + Yup form; organization is always required (the page is gated on the create-template permission, so there is always at least one permitted org and it is auto-selected when only one exists); aggregated top-of-step error summary.TemplateBuilderPageView.tsx: the wizard's "Create Template" button submits the step form via theformattribute; addedonCreateplumbing; relaxed the customizations continue gate to the provisioner check.wizardState.ts:toCreateTemplateRequest(state, customizations)builds the request from the submitted form values; removed the now-vestigialorganizationIdfrom the reducer.TemplateBuilderPage.tsx: adapts the create call to the new signature.TemplateCustomizationsStep.stories.tsx: interaction tests for missing organization, missing name, single-org auto-select, and valid submit.Testing
pnpm --dir site exec tsc -p . --noEmit(clean)pnpm --dir site exec biome check src/pages/TemplateBuilder(clean)wizardState.test.ts(27 passed) andTemplateCustomizationsStep.stories.tsx(4 passed)Screen.Recording.2026-08-12.at.3.52.37.PM.mov
Implementation plan
DEVEX-744: Form validation for the Template Builder customizations step
Problem
In the new Template Builder wizard, creating a template with no organization selected produces an unhelpful backend error (empty
organization_idsent to the API). There is no client-side validation on the final "Customizations" step:computeCanContinueonly checksnameand provisioner availability, so the "Create Template" button is enabled even when the organization is missing.The customizations form is a horizontal two-column grid. Showing per-field inline errors (Formik
helperText) would push fields down and break column alignment. We want validation before submit, with messages aggregated at the top of the step rather than inline under fields.Decision (confirmed with user)
CreateTemplateForm), rather than ad-hoc reducer validation.utils/formUtils.ts.Approach
Make
TemplateCustomizationsStepa Formik form that is the source of truth for the five customization fields. Validate on submit; render an aggregated error summary Alert at the top of the step. Connect the wizard's existing "Create Template" button (which lives in the parent nav bar) to the child form using the standardform="<id>" type="submit"HTML association, so no imperative handle or extra callback is needed. Only valid submits reach the API.Steps
TemplateCustomizationsStep.tsx: convert to Formik with a Yup schema (nameValidator,displayNameValidator, description max 128,iconValidator, organization always required); initial values seeded from wizard state; aggregated error Alert at the top; keep provisioner reporting and org auto-select.TemplateBuilderPageView.tsx: wire the last-step button to submit the form via theformattribute; add anonCreateprop; relax the customizations continue gate to the provisioner check.wizardState.ts:toCreateTemplateRequest(state, customizations)composes the request from base/modules in state plus submitted values.TemplateBuilderPage.tsx: adapthandleCreate.Behavior notes
createErroralert; only the empty-org case is caught client-side.Post-plan refinements (from review)
orgRequired), since the page is permission-gated and always has at least one permitted org.toCreateTemplateRequestkeeps the submitted form values authoritative (no fallback to state, which would resurrect optional fields a user deliberately cleared).organizationIdfield from the reducer state.Buttoncomponent.Testing
wizardState.test.tsfor the newtoCreateTemplateRequestsignature.Generated by Coder Agents on behalf of @jeremyruppel.