@foomo/cms-tools
v0.2.0
Published
CMS UI tools for Contentful apps, built on @foomo/ui. Every module is imported by its own subpath; there is no root entry.
Downloads
80
Keywords
Readme
@foomo/cms-tools
CMS UI tools for Contentful apps, built on @foomo/ui.
ESM only. There is no root entry and no barrel files — import each module by its subpath:
import { SomeTool } from "@foomo/cms-tools/tools/some-tool";
import { useSomething } from "@foomo/cms-tools/hooks/use-something";Install
npm install @foomo/cms-tools @foomo/ui @contentful/app-sdk react react-dom tailwindcssStyles
Tools use Tailwind classes and @foomo/ui components, and ship no CSS of their own. Add the package to your Tailwind sources next to the @foomo/ui setup:
@import "tailwindcss";
@import "@foomo/ui/ui.css";
@source "../node_modules/@foomo/cms-tools/dist";Adjust the @source path relative to your CSS file.
Tools also use the semantic color utilities (bg-primary, text-muted-foreground, border-border, …), so the host's @theme inline block must map the @foomo/ui tokens to --color-* the way shadcn does. .storybook/preview.css has a minimal example.
tools/image-crop/image-crop additionally needs the cropper styles:
@import "react-image-crop/dist/ReactCrop.css";Layout
| Subpath | Source | Contents |
| --------- | ------------ | --------------------------------------------- |
| tools/* | src/tools/ | UI tools, each receiving the Contentful sdk |
| hooks/* | src/hooks/ | Shared React hooks |
| lib/* | src/lib/ | Framework-free helpers |
| contentful/* | src/contentful/ | SDK provider and complete app pages built from the tools |
Contentful pages read the SDK from context, so wrap the app once:
import { ContentfulSdkProvider } from "@foomo/cms-tools/contentful/sdk";
import { ImageCropPage } from "@foomo/cms-tools/contentful/image-crop-page/image-crop-page";
<ContentfulSdkProvider>
<ImageCropPage ratios={ratios} publish onImported={({ assets }) => link(assets)} />
</ContentfulSdkProvider>;A tool can be a single file (src/tools/slug-field.tsx → tools/slug-field) or a folder (src/tools/slug-field/slug-field.tsx → tools/slug-field/slug-field).
Conventions
- Import sibling modules relatively with their real extension (
./format.ts,./field.tsx);tscrewrites them to.js. - No
index.tsre-export files. Biome'snoBarrelFileandnoReExportAllrules fail the lint if one appears. @contentful/app-sdk,@foomo/uiand React are peer dependencies — never bundle them.
Playground
bun run playground serves playground/ on http://localhost:5173 as a Contentful app.
- In Contentful: create an app definition with App URL
http://localhost:5173and the Page or Entry field location, and install it. Open it from the Apps menu (page) or assign it to a field's appearance (entry field). It connects to the real SDK and lists the environment's image assets. - Standalone: opened directly in a browser, it falls back to a mock SDK with sample photos.
Scripts
bun run playground # vite dev server for playground/
bun run build # tsc → dist/
bun run typecheck
bun run check # biome lint + format check
bun run format