Skip to content

Remove the starter templates and their CI jobs - #48

Merged
n4ff4h merged 52 commits into
devfrom
plan/remove-templates
Nov 1, 2026
Merged

n4ff4h merged 52 commits into
devfrom
plan/remove-templates

Conversation

@n4ff4h

@n4ff4h n4ff4h commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator

Removes the Laravel + Inertia CI job and the templates/ directory, which also takes the Next.js template and its CI job with it.

Stacked on plan/e-docs (#45), merge last. It sits on top because Part A edits files in templates/, and deleting them lower in the stack would conflict. Until #41–#45 merge, this diff includes them; the change itself is the last commit.

Removed

What Detail
templates/laravel-inertia-react, templates/nextjs 86 tracked files
.github/workflows/templates.yml Held only the two template jobs
build:templates, typecheck:templates Root scripts; typecheck no longer needs its filter
Workspace entry and lockfile importers 1067 lockfile lines removed
Ignore rules .prettierignore, eslint.config.js, changesets ignore
Doc references README, AGENTS.md, the "Starter templates" section of the Inertia and Next.js guide

The Inertia and Next.js guide itself stays, since the library still supports both.

What this drops

templates/nextjs held the only check that really server-rendered Onu in a production app (test:ssr). The unit test first-render.test.tsx still covers markup stability for the clock-based components through renderToString, but nothing now runs a full framework build.

Checks

Lint, format, typecheck, docs check, 2820 unit tests, MCP and Figma tests, build, size, build:web, pnpm audit --prod and the frozen install under pnpm 12.16.1 all pass locally.

🤖 Generated with Claude Code

n4ff4h and others added 30 commits November 1, 2026 10:41
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The changesets fixed group keeps @javaabu/onu and @javaabu/onu-mcp together, and
scripts/sync-plugin-version.mjs keeps the plugin manifest in step; the release
workflow fails if it differs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The @font-face rules move to fonts-thaana.css, imported by tailwind.css, styles.css and
fonts.css. New budget: fonts-thaana.css 400 B (327 B measured). tailwind.css stays within
8.5 kB (7.97 kB) and styles.css within 4.5 kB (4.38 kB). fonts.css drops to 400 B now the
font faces moved out (306 B).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both share React context with the app, so a second copy silently disconnects them.
@tanstack/react-query is a required peer, not optional as first planned: the core entry
imports ApiSelect statically, so an app without the package would fail to build.

The fallback QueryClient moves from a module singleton (shared across SSR requests) to
each OnuProvider, or the component when there is no provider. getOnuQueryClient is gone,
and invalidateApiOptions takes the client first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nothing in src, web or templates used it; every Onu select is built on cmdk. The primitives budget drops from 165 kB to 130 kB (124.25 kB measured).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Chevron renders an Icon that already mirrors, so the rotate-180 on top turned the arrows back to their LTR direction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A caller's data-slot replaced Button's, so the 44 px rule in base.css no longer matched. Button now always emits data-slot=button, and the 34 callers that named their button (27 Button, 7 InputGroupButton) use data-part. The plan listed 7; the rest had the same bug.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The module-level confirm() has no locale, so it keeps the English default; useConfirm uses the provider's. ValidationError.message is now empty when no message is given, so ValidationSummary shows form.errorSummaryTitle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The link and embed dialogs only have URL fields, so the alt text field is the only free-text field in the editor dialogs. The dialogs are rendered by the editors, not the toolbar, so the prop goes straight there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New keys: listing.moveItemMenu, moveItemUp, moveItemDown, choice.switchAccountFrom, form.editValue. Removed: listing.moveUp, moveDown. listing.moveTo stays as the menu's heading.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The button is rotated 90 degrees, so a mirrored chevron pointed the wrong way along the vertical axis.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… on a span

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
useNow starts from null and ticks on mount. RelativeDate also calls useNow, so it gets the same placeholder (the exact date). PublishBox now shares useNow instead of its own Date.now() state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
--onu-overlay keeps today's look (black at 10%) in both modes. App sidebar and the docs nav had the same hex fallbacks as _shell.ts and app-header.tsx, so they change too. figma/tokens-studio.json and the plugin are regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replaces six copies. Tabs, Wizard, Callout, FilterPanel and PasswordInput move to the hook too, so null is no longer read as uncontrolled there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
onChange now only means the native event. The renamed props: every date picker, map, editor, inline and repeating form control, LanguageSwitcher, ImageInput, AvatarUpload, AdditionalFilesUpload, TimePanel, useListingState, the custom filter and bulk action render props, and the map adapter shapes. PhoneInput's internal country select keeps onChange, because react-phone-number-input calls it. FileInput drops onChange(files). onReject takes an array everywhere.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
md becomes default on the four components named in the plan. AvatarUpload's keys already match UserAvatar's once that happens. NumberInput is h-8 at default with smaller stepper buttons, and TextInput gets the same size prop (h-7, h-8, h-10). Other md sizes (StatusBadge, IconText, Countdown, BottomSheet, SlideOver, ProgressBar, Hero, MapLegendSwatch) were not in the plan and are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Seven components now spread rest props and ref on their root, the multi-part components gain classNames slot maps, and asChild is added to BackToTop, ConditionalLink and LinkButton. Button keeps loadingText inside an asChild child, so SubmitButton asChild works while processing. The Definition of Done now asks for asChild only where an app may need to replace the one rendered element.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New modules: lib/initials, lib/url, hooks/use-copy-to-clipboard, use-merged-ref, use-async-search; toArray moves to lib/utils.

Root exports: toArray is removed. getInitials stays because docs/display-and-feedback/user-avatar.md documents it; the media entry's initials export is removed. normalizeUrl now returns string | null; TextInput keeps its own handling of //host and unsafe values on blur.

useAsyncSearch serves Autocomplete/TagsInput, CommandPalette and PlaceSearchBox. ApiSelect does not fit: TanStack Query owns its fetching, cancelling and caching, so it keeps only the debounced value, useDebouncedValue, now in the same module with the same 300 ms default. Retry now skips the debounce at every site (it already did in PlaceSearchBox). The form's filter(Boolean) stays at the form call sites.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LanguageSwitcher and RepeatingGroup gain defaultValue; Callout, FilterPanel and Lightbox gain defaultOpen. Lightbox open and onOpenChange are optional, and index is controlled only when passed. Uncontrolled, Lightbox tracks its own slide, so reopening resumes where it was instead of at the first slide. LanguageSwitcher without value or defaultValue still follows the provider's locale.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CommandPalette and OverlayMenu title were only ever sr-only accessible names, so they become label with no visible change. TopNav navLabel and Tabs listLabel become label; CommandPalette minQueryLength and PlaceSearchBox/usePlaceSearchBox minLength become minChars. MapView, Carousel, ButtonGroup, Autocomplete and ApiSelect already used these names. AppSidebar navLabel is not in the plan's list and is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Delete unused keys from en and dv after checking literal and dynamic use: common.{ok,clearAll,apply,edit,view,search,remove,add,open,menu,error,success,warning,info}, overlay.openCommandPalette, chart.typeSparkline, layout.{footer,moreActions}, display.readMore, choice.{options,rating}, listing.{sortByColumn,sortDirection,sortNone,firstPage,lastPage,deletedRecords,tabWithCount,exportAs}. No candidate turned out to be reached dynamically.

Wire listing.filtersApplied through useAnnouncer in FilterPanel and listing.selectionCleared in DataTable, with tests. Drop the stale export and comment from media/index.ts.

Dhivehi: common.clear, date.clearTime and file.clearSelection now use the clear word; common.delete, editor.{deleteRow,deleteColumn,deleteTable,deleteBlock}, display.{deleteComment,deleteNote} and listing.deletePermanently use the delete word. input.signatureClear keeps its erase word.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pure move of components/form/auth-forms.tsx into sign-in-form, register-form, forgot-password-form and reset-password-form, with the shared shell in _auth-shell. Tests split the same way. Root exports are unchanged; the auth forms docs page covers the new files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New e2e-smoke.yml: a11y and Thaana specs in Chromium, path-filtered to packages/onu, web and e2e. The full five-browser and visual run in e2e.yml is unchanged. YAML parsed locally; the workflow itself has not been run on GitHub Actions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
n4ff4h and others added 22 commits November 1, 2026 11:56
pnpm figma:test needs no secret (passes with an empty environment), so it runs in ci.yml after the MCP tests. It was failing: the kit had drifted from React. Bring it in line so the step can be green: Tag, UserAvatar and Modal size md -> default (C4), Callout variant -> tone with neutral and danger (C3), and the Card plain variant (da4edb1). StatusBadge keeps md because React does. Regenerated figma/plugin/code.js.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Remove the src/ui exclusion; threshold src/ui/** 70 for lines, statements, functions and branches. Add primitives-smoke.test.tsx: one smoke + axe test per primitive file (54 entries) in LTR and RTL. The aggregate was already 80.22 lines / 80.36 statements / 74.92 functions / 71.25 branches from other tests, and is now 96.55 / 96.61 / 99.07 / 82.75. Overall 98.33 lines, 97.32 statements, 96.66 functions, 93.64 branches.

Real axe bugs fixed: Calendar week numbers passed scope and week onto a td; ItemGroup had role=list with no listitems (role removed); CommandSeparator is a role=separator inside cmdk's listbox, now aria-hidden.

test:coverage still exits 1 because of an uncaught wysiwyg-editor error present before this commit; D4 handles it. All thresholds pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stub getContext and window.focus in test/setup.ts, including frame windows (the five focus lines came from the print frame in src/export/pdf.ts). 'Not implemented' lines: 108 before, 6 after; the 6 left are link-click navigations.

isolate: false is NOT kept. Three runs in a row all failed, with different failures each time: 41 failed in 6 files (20.2s), 29 in 7 (44.9s), 15 in 4 (19.3s), against 47-55s and all green with isolation. The failures are state leaking across files (Radix focus guards left in the body, leftover nodes, mocks such as recharts and Google Maps), so there is no trivial fix. Durations with isolation: 48.3s before the stubs, 48.6s and 55.3s after.

Fix the uncaught 'Cannot read properties of null (reading commands)': the B5 Thaana test left the image dialog open, so Radix's close-focus timer ran afterDialog on a destroyed editor. The test now closes the dialog. vitest now exits 0; it exited 1 before. The source still throws if a real editor unmounts with a dialog open; not changed here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DateCalendar: arrows, Home, End, Page Up and Page Down in LTR and RTL, and Enter. IconText: first test file, with axe in both directions. No bugs found.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Seven react-hooks/exhaustive-deps disables now carry a -- reason. The as any casts in editor/_highlight.ts are replaced by the isLoadable type guard.

The PHYSICAL regex now also catches origin-(top-|bottom-)left/right, slide-in-from-/slide-out-to-left/right, and translate-x- (not translate-x-0) when the string has no rtl: partner. Classes on data-[side=...]: are not hits, because Radix's side is physical. The src/ui exemption for this rule narrows to ui/sheet.tsx and ui/sidebar.tsx.

Hits: components/date/_period-grid.tsx and maps/_placeholder-adapter.tsx centre on a physical left, so they get inline disables with reasons. ui/navigation-menu.tsx moves to slide-*-start/end (tw-animate-css has them): LTR is unchanged and RTL motion now follows the reading direction. Patch changeset added. Size budgets unchanged, none exceeded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The peer table now lives on the installation page; DEPENDENCIES.md keeps licences and links there, and docs/requirements.md links there. Media pages list the whole entry's static peers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Compared each Props table with the component's TypeScript props and added what was missing, including the props Parts B and C added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Point the changelog link at the package changelog, strike removed items in REQUIREMENTS, drop removed components from the Onu skill, and use the Part C names in Callout, PublishBox, FilterPanel, bulk actions and UserAvatarGroup.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ConditionalLink, EmptyState, IconText, the unsaved changes guard and StatusBadge now describe their role, name and what a disabled or decorative state exposes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pnpm 12 keeps the version from packageManager in a section of pnpm-lock.yaml, and a frozen install fails if it is missing. Moving to 12.16.1 in 15ccf53 changed package.json only, so every CI job has failed at pnpm install since. It didn't show locally because an older global pnpm that switches itself to 12.16.1 doesn't check this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
next 16.4.3 (critical RCE and high DoS, templates/nextjs). shadcn 4.23.0, a dev dependency, which moves its zod to 4.6.7. In the lockfile, within existing ranges: body-parser 2.4.0, qs 6.17.1, fast-uri 3.1.9, ip-address 10.7.5, undici 7.30.1 and 8.12.3, systeminformation 5.33.19. pnpm audit --prod is clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deletes templates/ (Laravel + Inertia and Next.js) and .github/workflows/templates.yml, which only held those two jobs, along with their scripts, workspace entry, ignore rules and doc links. The Inertia and Next.js guide stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The open dialog's focus timer ran after the editor unmounted, and vitest's unhandled error made test:coverage exit 1. D4 has the same fix; this brings it down to where the test was added, so #42 and #43 pass on their own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@n4ff4h
n4ff4h merged commit 3fd665e into dev Nov 1, 2026
3 checks passed
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.

1 participant