- This repo is a pnpm + Turborepo monorepo for tom.so, api.tom.so, cms.tom.so and sophie.st.
- Make the smallest correct change, follow local patterns, and verify before handoff.
- Prefer improving existing code over introducing new abstractions.
apps/web— SolidStart app on Cloudflare Workers.apps/api— Hono API on Cloudflare Workers.apps/cms— Payload CMS on Next.js with Open Next.apps/(stores)— Ecommerce stores running on Medusa.js (in progress).packages/@tom/*— shared packages likeui,utils,types,db,arena,payload,schemas,checkout,constants,haptics, and other@tom/*workspaces present in the repo.
- Keep things in one function unless composable or reusable
- AVOID unnecessary destructuring of variables
- AVOID
elsestatements unless necessary - AVOID
try/catch- use Effect for error handling - AVOID using
anytype - AVOID
letstatements - preferconst - PREFER clear, descriptive variable names where possible
- AVOID Node-specific APIs - this runs on Cloudflare Workers
- Improve existing files instead of rewriting patterns arbitrarily.
- All code run on Cloudflare Workers.
- Avoid Node-only APIs unless the runtime boundary already requires them.
- Treat
packages/@tom/*as portable across apps. apps/webuses Wrangler withnodejs_compat, but still prefer web-standard and Worker-safe APIs.
pnpm dev— run all dev tasks through Turbo.pnpm dev:web— run only@tom/web.pnpm dev:api— run only@tom/api.pnpm build— Turbo build.pnpm lint— Turbo lint.pnpm format—oxfmt --check ..pnpm write—oxfmt --write ..pnpm typecheck— Turbo typecheck.pnpm test— run tests via Turbo.pnpm test:update— update snapshots in web and utils.pnpm deploy/pnpm deploy:api— deploy web or api.
apps/web:pnpm run dev|build|typecheck|lint|test|test:ui|test:coverageapps/api:pnpm run dev|build|deploy|cf-typegenapps/cms:pnpm run dev|build|lint|lint:fix|generate:types|previewapps/docs:pnpm run dev|build|previewpackages/@tom/utils:pnpm run test|typecheck
- Root filename filter:
pnpm test -- Nav.test.tsx - Web exact file:
cd apps/web && npx vitest run Nav.test.tsx - Web exact path:
cd apps/web && npx vitest run src/components/__tests__/Nav.test.tsx - Utils exact file:
cd packages/@tom/utils && pnpm vitest run __tests__/telegram.test.ts - CMS integration file:
cd apps/cms && pnpm vitest run tests/int/<name>.int.spec.ts
- Web tests live in
apps/web/src/**/__tests__/*.test.tsx. - Utils tests live in
packages/@tom/utils/__tests__/*. - CMS tests live in
apps/cms/tests/int/**/*.int.spec.ts. - Web Vitest uses
jsdom, globals, andapps/web/src/test/setup.ts. - Web test setup includes
@testing-library/jest-dom, cleanup, and awindow.matchMediamock.
- Use strict TypeScript.
- Important enforced options:
exactOptionalPropertyTypes,noImplicitReturns,noFallthroughCasesInSwitch,noUncheckedIndexedAccess. - Module resolution is bundler-style.
- The Effect language service plugin is enabled.
- Parse unknown input at boundaries; keep internal types trusted.
- Formatter/lint baseline comes from
oxfmtandoxlint. - Use tabs with width 2, target 80 columns, double quotes, semicolons, and trailing commas.
- Order imports with external packages first, then internal modules.
- Use workspace imports for shared code:
@tom/*. - In
apps/web, use the~/*alias for app-local imports. - Keep import blocks tidy; do not scatter equivalent imports.
- Name functions and variables so the code reads like English.
- Prefer descriptive booleans like
isEnabledandhasAccess. - Avoid boolean flags that hide multiple behaviors inside one function.
- Prefer explicit return types when they improve boundary readability.
- Make invalid states hard to represent.
- Prefer
Effect.gen,Effect.succeed,Effect.fail, andEffect.try. - Define shared/custom errors in
@tom/types. - Follow the logging API already used in the touched area; for example, CMS code
uses
payload.logger. - Use
Redacted.make()for secrets and tokens. - Do not swallow errors.
IMPORTANT: Always consult effect-solutions before writing Effect code.
- Run
effect-solutions listto see available guides - Run
effect-solutions show <topic>...for relevant patterns (supports multiple topics) - Search
~/.local/share/effect-solutions/effectfor real implementations
Topics: quick-start, project-setup, tsconfig, basics, services-and-layers, data-modeling, error-handling, config, testing, cli.
Never guess at Effect patterns - check the guide first.
- No
.cursor/rules directory was found. - No
.cursorrulesfile was found. - No
.github/copilot-instructions.mdfile was found. - No
CLAUDE.mdfile was found.
- Components are setup functions, not render loops.
- Access signals as functions:
count(). - Put derivations in
createMemo, not effects that set state. - Use
createEffectonly for side effects. - Call
onCleanupinside effects when needed. - Access props via
props.x; do not destructure component props. - Use
splitPropsfor local vs passthrough props andmergePropsfor defaults. - Use
<For>,<Index>, and<Show>instead of.map()in JSX. - Use
<Suspense>for async UI. - Use
class, notclassName; useclassListfor reactive classes.
- API code uses Hono and Worker runtime constraints.
apps/apiusesjsxImportSource: "hono/jsx"; preserve that pattern.- CMS uses Next.js + Payload + React; do not force Solid patterns into CMS.
- CMS has its own
eslint.config.mjs; follow stronger local app rules when they differ.
- Prefer Vitest across the repo.
- For Solid UI tests, use
@solidjs/testing-library. - Wrap router-dependent components in
Router/Routeas needed. - Assert user-visible behavior first.
- Keep snapshots focused.
- Run the narrowest relevant test first, then broader verification if needed.
- Minimum: run targeted tests for changed code when tests exist.
- For broader changes, also run relevant lint and typecheck commands.
- Good defaults:
pnpm lint,pnpm typecheck, andpnpm test -- <file>or a package-local Vitest command. - If something cannot be verified locally, say so explicitly.
- Use conventional commits because releases depend on them.
- Valid prefixes:
feat(scope):,fix(scope):,chore(scope):,refactor(scope):. - Use
BREAKING CHANGE:in the body, or!, for breaking changes. - PR titles should follow the same format.
- Production site:
https://tom.sofor web,https://api.tom.sofor api, andhttps://cms.tom.sofor cms. - Web deploy target: Cloudflare Workers.
- API deploy target: Cloudflare Workers.
- CMS deploy flow uses OpenNext + Cloudflare plus database migrations on Cloudflare Workers.
- If unsure, read the nearest package or app config before changing patterns.