PicThing 2.0 Dependency Audit

Read-only package-by-package review of the root workspace, three apps, and three packages.

June 4, 2026· 68 direct declarations across 7 manifests· No repo changes made
Bottom line

The repo is mostly disciplined. I found 10 high-confidence removable direct declarations, one dependency ownership correction for convex, one types-only bucket move, and one global CLI reproducibility issue in packages/svix. The active runtime dependencies are generally justified by real imports.

Direct Declarations
68
58 unique package names
Removal Candidates
10
high confidence
Ownership Fixes
1
convex belongs in web
Manifests Reviewed
7
root + apps + packages

Recommended Cleanup

High-confidence removals

These have no required direct role in the current checkout. Remove them in small batches and run the existing package checks after each batch.

ManifestPackageWhy it can go
package.jsonprettierRoot has no formatter script of its own. Every formatter-bearing workspace declares its own copy.
package.jsonprettier-plugin-svelteOnly the web config uses it, and apps/web declares it locally.
package.jsonprettier-plugin-tailwindcssOnly the web config uses it, and apps/web declares it locally.
apps/web@clerk/themesNo imports or config references. Clerk appearance is implemented locally.
apps/web@tailwindcss/typographyNo Tailwind @plugin registration and no source references.
apps/webembla-carouselNo imports or config references.
apps/webembla-carousel-autoplayNo imports or config references.
apps/webkeen-sliderNo imports or config references.
apps/raycasttypescript-eslintNo direct import. @raycast/eslint-config already declares it as a dependency.
packages/convex@types/bunNo Bun globals, Bun types, or types config entry in the package source.
!
Do not simply delete root convex

apps/web imports convex/browser and convex/server directly in three files but does not declare convex. The root install currently masks that. Add convex to apps/web first, then remove the root declaration. packages/convex already owns its separate direct declaration.

Secondary Hygiene

AreaFindingRecommendation
apps/web@types/d3 is required implicitly because d3 ships JavaScript without bundled TypeScript declarations.Keep it, but move it from dependencies to devDependencies.
apps/raycastSource imports react directly, but the manifest does not. Installed @raycast/api@1.104.8 currently supplies react@19.0.0.Treat as an ownership review, not an urgent breakage. Decide whether to follow the Raycast package convention or declare react explicitly.
apps/raycastDirect @types/node@25.4.0 and @types/react@19.2.14 are newer than the optional peers exposed by @raycast/api@1.104.8: 22.13.10 and 19.0.10.Keep the types, but consider aligning versions if Raycast lint or type behavior becomes noisy.
packages/svixThe dev script calls svix listen, but the workspace has no Node dependency or node_modules/.bin/svix. This Mac resolves /opt/homebrew/bin/svix from Homebrew svix-cli/1.86.0.Document the external CLI prerequisite or make setup reproducible through the preferred installation path.

Method

Root Workspace

package.json is primarily a shared toolchain manifest. Four declarations should stay, three formatter declarations are redundant, and convex should move to the web app.

DependencyUseVerdict
@effect/tsgoprepare runs effect-tsgo patch; TS configs opt into @effect/language-service.Keep Intentional compiler augmentation.
@typescript/native-previewProvides tsgo used by workspace checks and the VS Code native-preview setting.Keep
convexCurrently resolves the web app's undeclared direct imports.Relocate Declare in web, then remove from root.
prettierNo root formatter command; child packages declare their own copies.Remove
prettier-plugin-svelteWeb-only config usage with local web declaration.Remove
prettier-plugin-tailwindcssWeb-only config usage with local web declaration.Remove
turboUsed throughout root scripts and turbo.json.Keep
typescriptShared TypeScript peer for svelte-check and Raycast ESLint config; conventional TS tooling anchor.Keep

The root overrides for typescript-eslint, @typescript-eslint/utils, and @clerk/shared are constraints rather than direct dependencies. Keep them until the related compatibility pressure is deliberately re-tested; the Clerk store still contains a shared-version compatibility suppression.

Web App

apps/web carries 41 direct declarations. Most are justified. Five are dead declarations, @types/d3 belongs in the dev bucket, and direct convex ownership is missing.

Runtime Dependencies

DependencyMeasured useVerdict
@clerk/backend2 server-side files: Clerk service and webhook route.Keep
@clerk/clerk-jsClient Clerk store initialization.Keep
@clerk/themesNo references. Appearance is authored locally.Remove
@clerk/uiClient Clerk store passes ui into Clerk initialization.Keep
@lucide/svelteImported across 19 component and route files.Keep
@picthing/billingImported across stores, services, dashboard, and remote billing wrapper.Keep
@picthing/convexGenerated API and model types imported across 14 files.Keep
@types/d3Implicit typings required by d3.Selection annotations.Move to dev
@uploadthing/svelteSvelte UploadThing helper generation.Keep
convex-svelteReactive Convex hooks across providers, stores, components, and routes.Keep
d3SVG background editor helper.Keep Focused but real.
embla-carouselNo references.Remove
embla-carousel-autoplayNo references.Remove
figma-squircleSVG editor helper and SVG background route.Keep
jszipBulk asset download ZIP generation on /app/assets.Keep
keen-sliderNo references.Remove
mode-watcherRoot layout and dashboard navigation theme toggle.Keep
runedSearch params, watchers, and asset-page scroll state.Keep
svelte-awesome-color-pickerImported in three editing routes.Keep
uploadthingUpload service, endpoint, uploader store, and tool routes.Keep
virtuaAsset-list virtualization on /app/assets.Keep
zodAsset-store query params and UploadThing input schemas.Keep

Development Dependencies

DependencyMeasured useVerdict
@sveltejs/adapter-nodeSvelteKit adapter config.Keep
@sveltejs/kitFramework config, server hooks, routes, and app utilities.Keep
@sveltejs/vite-plugin-sveltevitePreprocess in Svelte config.Keep
@tailwindcss/typographyNo references or plugin registration.Remove
@tailwindcss/viteVite Tailwind plugin.Keep
@types/nodeVite config uses node:path, process, and Buffer.Keep
clsxShared cn() utility.Keep
convex-vite-pluginLocal Convex bridge in Vite config.Keep
prettierPackage format and lint scripts.Keep
prettier-plugin-svelteRegistered in web Prettier config.Keep
prettier-plugin-tailwindcssRegistered in web Prettier config.Keep
svelteCore app framework.Keep
svelte-checkPackage check scripts.Keep
tailwind-mergeShared cn() utility.Keep
tailwind-variantsButton variant construction.Keep
tailwindcssCSS import and Vite integration.Keep
tw-animate-cssImported by app CSS.Keep
viteDev, build, preview scripts and config.Keep
vite-plugin-devtools-jsonRegistered in Vite config.Keep

Raycast App

apps/raycast is lean. One direct lint declaration looks redundant. There is also a direct react import supplied transitively by @raycast/api.

DependencyMeasured useVerdict
@raycast/apiCore extension UI, clipboard, toasts, actions, and ray scripts.Keep
@raycast/utilsuseCachedPromise and useLocalStorage.Keep
@raycast/eslint-configImported by eslint.config.js.Keep
@types/nodeRequired for fs/promises, os, path, process, and Buffer.Keep Consider version alignment.
@types/reactRequired for TSX and React hook typing.Keep Consider version alignment.
eslintRequired by Raycast lint tooling and local ESLint config.Keep
prettierPackage format script and Raycast ESLint config peer.Keep
typescript-eslintNo direct import; already owned by @raycast/eslint-config.Remove Verify lint afterward.

Image Optimizer Worker

apps/image-optimizer-worker has only three declarations and all are active.

DependencyMeasured useVerdict
effectImported by the Worker entry point, background remover, and tagged errors. Drives HTTP, streams, errors, and control flow.Keep
prettierPackage format and lint scripts.Keep
wranglerDeploy, dev, start, type generation scripts, JSON schema, and Worker config.Keep

Convex Package

packages/convex has seven declarations. The legacy migration dependencies are still live: /app/assets triggers the migration mutation, so they are not dead weight yet.

DependencyMeasured useVerdict
@clerk/backendLegacy migration action fetches user and organization data from Clerk.Keep Remove only with migration retirement.
@convex-dev/workpoolConvex component registration and migration queue.Keep Remove only with migration retirement.
@libsql/clientLegacy migration reads old Turso records.Keep Remove only with migration retirement.
convexCore server functions, validators, generated bindings, config, and scripts.Keep
convex-helpersCustom authenticated and bridge function wrappers.Keep
@types/bunNo Bun globals, Bun type imports, or TS config references.Remove
prettierPackage format and lint scripts.Keep

Billing Package

packages/billing is runtime dependency-free and exports constants plus plan-resolution helpers.

DependencyMeasured useVerdict
prettierPackage format and lint scripts.Keep

Svix Package

packages/svix declares no dependencies. Its only script is a convenience wrapper:

svix listen http://localhost:5173/api/webhooks/clerk

That command works on this Mac because /opt/homebrew/bin/svix points to ../Cellar/svix-cli/1.86.0/bin/svix. A clean bun install does not install it.

Conservative Execution Order

  1. Add convex to apps/web, remove root convex, then run bun run check:web and bun run check:convex.
  2. Remove the five unused web declarations and move @types/d3 to web dev dependencies, then run bun run check:web and bun run format:web.
  3. Remove the three root formatter duplicates, then run bun run check:all and bun run format:all.
  4. Remove Raycast's direct typescript-eslint, then run bun run check:raycast and the Raycast lint script.
  5. Remove Convex's @types/bun, then run bun run check:convex.
  6. Decide whether packages/svix intentionally depends on a Homebrew-installed CLI and document that choice.