Skip to content

refactor(ddd-lite): shell layout + kernel contract + base64 reference module#8

Merged
rivodotlove merged 3 commits into
mainfrom
refactor/ddd-lite-step1-shell
Jun 2, 2026
Merged

refactor(ddd-lite): shell layout + kernel contract + base64 reference module#8
rivodotlove merged 3 commits into
mainfrom
refactor/ddd-lite-step1-shell

Conversation

@rivodotlove

@rivodotlove rivodotlove commented Jun 2, 2026

Copy link
Copy Markdown
Owner

Summary

Step 1 of the DDD-lite refactor. Establishes the layered module shape and lands the first tool as the reference template.

  • refactor(structure): collapse shell into app / shared / kernel layout.
  • feat(kernel): add tool loader contract, Result type, and boundary lint rules.
  • feat(base64): implement Base64 as the reference module (domain / ui / store / view-model seam).

Architecture

  • app/ — VS Code-style shell + global state.
  • shared/kernel/registry.ts (tool catalog + loader contract), result.ts (Result type).
  • modules/<tool>/ — self-contained tool; base64 is the reference template.
  • Boundary rules lint-enforced: domain stays pure (no React/IO), modules reachable only through their barrel.

Test plan

  • vp check (format + lint + typecheck)
  • vp test

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Base64 encoding and decoding tool with toggleable URL-safe format option for flexible text transformation
    • Lazy loading system for tools enabling efficient on-demand module instantiation
  • Tests

    • Comprehensive test coverage for Base64 operations including UTF-8 multibyte characters, URL-safe formatting, whitespace handling, and error scenarios

rivodotlove and others added 3 commits May 30, 2026 17:23
Step 1 of DDD-lite restructure. Pure move, no behavior change.

- src/components/shell/*  -> src/app/shell/*
- src/stores/*           -> src/app/stores/*  (app-level state)
- src/tools/registry.ts  -> src/shared/kernel/registry.ts
- src/lib/utils.ts       -> src/shared/utils.ts
- src/lib/{hotkeys,storage,fonts,themes} -> src/shared/lib/*
- shadcn ui -> src/shared/ui, common -> src/shared/components

Delete ghost dirs (features/, tools/<tool> stubs, types/). Add
src/modules/ as canonical tool home. Rewrite @/ imports and
components.json aliases. vp check green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t rules

Step 2 of DDD-lite restructure.

- ToolModule contract + optional ToolDefinition.loader (lazy module barrel)
- Tool route lazy-renders a module when loader is set, else keeps the
  "not implemented" placeholder; Suspense fallback added
- shared/kernel/result.ts: Result/Ok/Err/DomainError + ok/err/domainError
  helpers for total, never-throwing domain functions
- Boundary rules in vite.config.ts lint block (Vite+ ignores .oxlintrc.json):
  * domain/ may not import react/react-dom, app state, storage, or modules
  * modules reachable only via their barrel (@/modules/<tool>)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Step 3 of DDD-lite restructure — first real tool, the template others copy.

Layout (modules/base64/):
- domain/base64.ts        pure, total, Result-returning encode/decode +
                          UTF-8 correctness, url-safe option
- domain/base64.test.ts   12 unit tests, no React (vite-plus/test)
- ui/store.ts             zustand store for tool state, persisted to
                          IndexedDB via the shared idb adapter
- ui/use-base64.ts        view-model seam: reads store, derives output/error
- ui/base64-tool.tsx      presentational entry component (default export)
- index.ts                public barrel (only the entry component)

State is managed with zustand (per request), not the local useReducer
hook from the original Q5 plan. To honor CLAUDE.md (tool IO in IndexedDB),
add shared/lib/storage/idb-zustand.ts: a zustand StateStorage adapter over
the existing idb helper, keyed by tool id. New tool stores reuse it.

Register loader: () => import("@/modules/base64") so the route lazy-loads
the module; build confirms it splits into its own chunk.

Intra-module imports are relative; the @/modules/*/{domain,ui} alias is
lint-banned past the barrel.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
devbox 918675d Commit Preview URL

Branch Preview URL
Jun 02 2026, 06:35 AM

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR adds a complete Base64 encoding/decoding tool module and establishes lazy-loaded tool architecture. It introduces shared domain logic patterns via a Result type, implements Zustand state persistence with IndexedDB, and reorganizes imports under @/shared paths while enforcing module boundaries through ESLint rules.

Changes

Base64 Tool and Lazy-Loaded Tool System

Layer / File(s) Summary
Shared kernel abstractions
src/shared/kernel/result.ts, src/shared/lib/storage/idb-zustand.ts
Result<T> with DomainError, success/failure constructors, and IndexedDB-backed Zustand StateStorage adapter.
Tool registry with lazy-load support
src/shared/kernel/registry.ts
ToolModule contract added; ToolDefinition extended with optional async loader() function; base64 tool includes dynamic module loader.
Base64 domain logic and tests
src/modules/base64/domain/base64.ts, src/modules/base64/domain/base64.test.ts
Pure domain functions encodeBase64, decodeBase64, runBase64 return Result<string>, handle UTF-8 safety via TextEncoder/TextDecoder, support URL-safe mode, and include comprehensive test coverage for encode/decode/round-trip and error cases.
Base64 state and view model
src/modules/base64/ui/store.ts, src/modules/base64/ui/use-base64.ts
Zustand store with IndexedDB persistence; useBase64() hook wires store state to domain logic, exposing input, mode, urlSafe toggle, derived output/error, and action setters.
Base64 UI component and barrel
src/modules/base64/ui/base64-tool.tsx, src/modules/base64/index.ts
Base64Tool React component with mode selection buttons, URL-safe checkbox, editable input textarea, read-only output, and error display; module barrel exports default component.
Route-level lazy loading and Suspense
src/routes/tool.$toolId.tsx
Tool route derives tool.loader, creates lazy component via React.lazy(), renders inside Suspense with ToolLoading fallback; falls back to "Not implemented yet" when loader is absent.
App shell and route integration
src/routes/__root.tsx, src/app/shell/app-shell.tsx, src/app/shell/command-palette.tsx, src/app/shell/shortcuts-cheatsheet.tsx, src/app/stores/use-settings-store.ts
Updated imports for shell stores, registry utilities, and hotkeys constants to use new @/app, @/shared, and @/shared/kernel paths.
Path aliases and lint architecture rules
components.json, vite.config.ts
Alias targets moved from @/components, @/lib, @/hooks to @/shared/* locations; ESLint rules added to enforce barrel-only imports for @/modules/* and restrict **/domain/** files to pure logic without React/app/storage dependencies.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • rivodotlove/devbox#5: Introduces the hotkeys/constants and shell store infrastructure that this PR reorganizes under new @/shared/@/app paths and extends with lazy-loading support.

Poem

🐰 A Base64 bundle hops into the fold,
With lazy lanes and domains of gold—
Result types catch what might slip away,
While ESLint guards the code's new way! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly summarizes the PR's main changes: a DDD-lite refactor reorganizing the project structure (shell layout) and adding foundational infrastructure (kernel contracts) and a reference tool (base64 module).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/ddd-lite-step1-shell

Comment @coderabbitai help to get the list of available commands and usage tips.

@rivodotlove rivodotlove merged commit e24bb35 into main Jun 2, 2026
1 of 2 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