Applies the copy glossary to about 370 strings and 64 call sites:
service (not app/application/site), sign in/out (not log in/out),
server and panel server (not box/machine/host), Delete destroys /
Remove detaches / Uninstall is for software, New opens a form and
Create submits it, settings, backup vs snapshot vs restore point,
extensions and Features, environment variables, compose project,
two-factor authentication. Confirm dialogs that destroy something now
use the same verb on the title and the button instead of "Confirm".
Backend messages that reach toasts verbatim ("Application not
found" x95 and others) are listed in plan 88 for the typed-error
work rather than edited here.
1,250 strings across 223 files, edited at their inline English
defaults (en.json regenerated, keys unchanged):
- sentence case for buttons, titles, labels, tabs and nav (827),
with an allowlist of product names and acronyms
- every em dash rewritten (184); "successfully", neutral "!" and
short-toast periods dropped; helper sentences end with a period
- "Are you sure?" confirms now state the consequence; "Danger Zone",
"no going back", "to get started" and "You're all set" gone
- straight quotes, "…", "time zone", unit spacing, "and" for "&"
- Confirm/Cancel and four other hardcoded labels wrapped in t()
scripts/copy-rewrite.mjs applies a {key: English} map at every call
site; the glossary pass reuses it.
en.json drops from 8107 to 6624 keys: repeated UI copy (Cancel x95,
Status x67, Refresh x54, ...) now lives under common.actions /
common.labels / common.loading, and extractor-era suffix duplicates
(refresh2, status3) within a component collapse onto one key.
Trailing ... defaults are normalized to the ellipsis character.
Translations are preserved: all 16 locales were re-keyed, carrying
existing per-component translations onto their new common.* keys
(majority vote where sources disagreed), and stale keys were pruned.
Verified: npm run lint (0 errors), node --test (140 pass), vite build.
edit
Mass conversion of ~8,000 English literals across 320+ files to
t('app.<file>.<key>', 'English default') calls, plus hand-conversion of
the 43 literals the codemod refused (concatenated toasts, module-level
helpers, class components) using bare t() from i18n/t or restructured
{{placeholder}} keys. Marketplace unsigned-release dialog now translates
the Install/Update verb inside the placeholder.
ESLint: 0 errors. Literal checker: 0 remaining.
"Marketplace" reads as a store; the page is where you browse and install
extensions, so call it Extensions.
- Nav label + page/tab title + route /marketplace -> /extensions
(first tab drives the topbar title via TabGroupLayout).
- /marketplace and /marketplace/installed now redirect to /extensions.
- Update command palette, page-context map, NotFound, empty-state copy.
- Keep the internal nav id, CSS classes, component/file names, and the
backend /api/v1/marketplace/registry endpoints unchanged; palette keeps
"marketplace" as a search keyword so the old term still finds it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per docs/plans/FRONTEND_UX_TAILWIND_CLEANUP_PLAN.md Phase 5.
- Add hooks/useLockBodyScroll.js: a ref-counted body-scroll lock that composes
nested locks correctly (a modal over an already-locked drawer no longer
restores scroll prematurely). Replaces the duplicated
document.body.style.overflow toggles in DashboardLayout (mobile nav drawer),
PreviewDrawer (file preview), and ChatDrawer (mobile AI sheet).
- lib/ai/markdown.js: escape quotes in link URLs. The renderer already
HTML-escapes all input and only emits allowlisted tags, but `"`/`'` in a
crafted URL could break out of the href attribute — now percent-encoded.
Verified: npm run build passes; eslint adds no new errors.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per docs/plans/FRONTEND_UX_TAILWIND_CLEANUP_PLAN.md Phase 2. Removes the Tailwind
CSS v4 dependency entirely; the internal SCSS design system is now the single
styling source (aligns with AGENTS.md / project policy).
Build wiring:
- Remove @tailwindcss/vite plugin from vite.config.js.
- Drop tailwindcss, @tailwindcss/vite, tailwind-merge, tailwindcss-animate from
package.json (+ lockfile).
- Delete src/globals.css and its import in main.jsx. --radius was already
redefined in _theme-variables.scss (loaded after globals), so nothing breaks;
repointed the 3 var(--color-primary) refs in _wordpress-pipeline.scss to
var(--accent-primary). Font stack now resolves to IBM Plex (SCSS) — the
Inter/JetBrains globals.css vars were unused.
- lib/utils.js: cn() now uses clsx only (no tailwind-merge).
Primitives (components/ui/*) converted to SCSS-only classes (.ui-*):
- dropdown-menu.jsx, command.jsx → new .ui-dropdown-* / .ui-command-* classes.
- skeleton.jsx → .ui-skeleton; popover.jsx → .ui-popover-panel.
- dialog/alert-dialog/select/sheet → dropped the tailwindcss-animate veneer;
enter/exit animation now handled by SCSS [data-state] keyframes in _ui.scss.
- alert-dialog AlertDialogAction gained a `variant` prop so non-danger confirms
keep their primary (not destructive) button.
- Modal.jsx → .sk-modal*; ConfirmDialog.jsx → .sk-confirm* (icon containers,
colors via theme tokens, layout) — the two heaviest raw-Tailwind components.
SCSS:
- _utilities.scss: extended the existing shim with a "Tailwind-removal
compatibility" layer covering every remaining utility class still referenced
in pages/components (positioning, sizing, spacing, semantic colors mapped to
theme tokens, sr-only, the handful of sm:/lg:/hover: variants actually used).
- _ui.scss: .ui-dropdown-*, .ui-command-*, .ui-skeleton, .ui-popover-panel,
.sk-modal*, .sk-confirm*, and [data-state] enter/exit animations.
Verified:
- npm run build passes; CSS shrank ~16kB (Tailwind utility layer gone).
- Completeness audit (scratchpad script): 0 un-styled Tailwind tokens remain
(only SCSS-nested BEM false positives).
- Visual smoke test (screenshots skill, mock data): dashboard / docker / servers
render correctly with full theming.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
AI is a core ServerKit primitive (not a plugin): an Intercom-style bubble + slide-in drawer on every dashboard page, with a tools+page-context assistant mode and a plain simple chat mode, SSE streaming, conversation persistence, and guarded write actions (the model proposes; the user approves).
Plugins EXTEND the assistant rather than rebuilding it: backend via app.plugins_sdk.ai (reg.tool + register_context_provider, discovered from a plugin.json ai block with install/enable/disable hooks); frontend via useServerkitAI() and a contributions.ai category (suggested_prompts, tool_renderers). The marketplace gains an ai category for discovery.
Backend: ai_service (Prompture Conversation + ProviderEnvironment + guardrails), ai_tool_registry singleton, ai_tools_builtin (core.* tools), the /api/v1/ai blueprint (SSE via a worker-thread + queue bridge, single-gevent-worker safe; in-thread confirmation gate), AiConversation/AiMessage/AiPendingAction models + migration 013, encrypted ai_* settings. Frontend: AIContext + components/ai/*, AI settings tab. Powered by Prompture (installed editable; requirements pinned).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Introduce a local-loopback pairing wizard and related installer/packaging changes.
- Add a new CLI command `setup` (agent/cmd/agent/main.go) that launches a small HTTP server and opens a browser/native window to run a pairing wizard.
- Implement the setup UI server and wizard HTML (agent/internal/setupui/*). The wizard runs a local HTTP API to start pairing, poll status, save credentials, and on Windows attempts to open a native WebView2 window (github.com/jchv/go-webview2) falling back to the system browser. After successful pairing the agent service is switched to auto-start (best-effort on Windows).
- Add platform-specific helpers: WebView2 window on Windows and no-op stubs on other OSes, plus service-start helper for Windows.
- Update go.mod/go.sum to include WebView2/winloader deps.
- MSI changes: add Start Menu shortcuts (Setup/Status), do not auto-start the service on install (start remains demand), add an Icon entry, and adjust build.ps1 to resolve the output directory to an absolute path for stable output paths. Packaged MSI outputs were added under packaging/msi/output/.
- Frontend additions: add shadcn/ui configuration, jsconfig, new globals and UI components used by the wizard (frontend/src/... and assets).
These changes provide an easier desktop pairing flow while keeping CLI pairing available for headless servers, and tweak the installer so the service isn't started before credentials exist.