Skip to main content
@craft-ts
LearnLearn with EffectAI agentsGuideReference
@craft-ts/core@craft-ts/component@craft-ts/dev-tools@craft-ts/effect@craft-ts/style@craft-ts/style-testing@craft-ts/i18n@craft-ts/i18n-effect@craft-ts/mcp
ExamplesMigrationEffect compatibility & maturityAdopting CraftTS progressivelyPress kitRoadmapBacklog
Beta
  • Learn
  • Learn with Effect
  • AI agents
  • Guide
  • Reference
  • Packages
  • Resources
  • Guide overview
  • Create a project
i.Core concepts
  • The mental model
  • Which primitive should I use?
  • Anatomy of a primitive
  • Generators and yield*
  • Insertions
  • Typed insertion pipes
  • Exceptions as values
ii.Managing state
  • Local state
  • State machines
  • query
  • Mutations
  • queryParams
  • asyncProcess
  • Selecting
  • Reacting to mutations
  • Collections
  • Collection utilities
  • Persistence
  • GlobalPersisterHandler
  • Pagination placeholders
  • Schema validation
iii.Recommended approaches
  • Inject at the point of use
iv.Structuring the app
  • craftService
  • Service scopes
  • Shaping the public API
  • Abstract services
  • App start
  • Lazy services
  • Server functions
  • craftRegisterFor
  • Target wrapper
v.Routing & type-safe DI
  • Setup
  • CLI automation
  • ESLint rules
  • Route providers
  • Route guards
  • Route exception handling
  • Non-blocking navigation
  • Global error component
  • Route load errors
  • Scaling routes
vi.Components & templates
  • Components
  • Activating the style system
  • Typed styles
  • Defining a design system
  • Tokens and variables
  • Global foundation and fonts
  • Pseudo-elements and animations
  • Axes and the matrix
  • Context obligations
  • Testing visual states
  • Text contrast
  • Visual attestation
  • Template obligations
  • Typed CSS variables
  • Fine-grained reactivity
  • Progressive rendering
  • Directives and .pipe(...)
  • settledValue & pendingNode
  • Accessibility
  • Customization
  • Content projection
  • Styling a component
  • Template migrator
vii.Forms
  • Overview
  • Validators
  • Submitting
  • Nested forms
  • Exception handling
  • Complete examples
viii.Testing
  • Testing services
  • Testing components
  • Type-level tests
  • Browser boundaries
  • Page stability
  • Architecture rules
    • Overview
    • Declarative baseline
    • Unique identities
    • HTTP endpoint ownership
    • Computed purity
    • Dependency cycles
    • Mutation reactions
    • Route DI proofs
    • Route component files
    • Path boundaries
    • Exclusive links
    • Persisted identities
    • insertSelect keys
    • craftEffect and network
    • craftEffect and imperative sync
    • Interactive element names
    • Metric thresholds
    • Server-state loaders
    • Primitive loader requirements
  • Extensible architecture graph
  • Graph insights
  • Craft graph vs Nx
ix.Reactivity utilities
  • craftComputed
  • craftEffect
  • craftMethod
  • source$
  • on$
  • fromEventToSource$
  • sourceFromEvent
  • afterRecomputation
x.Internationalisation
  • Type-safe i18n
  • The catalogue
  • Tokens
  • The runtime
  • With Effect
xi.Deployment (experimental)
  • Overview
  • Manifest reference
  • Diagnostics
  • Providers
  • Alchemy provider
xii.Going further
  • SSR and hydration
  • Effect integration
  • Program operators
  • Pattern matching
  • Observability
  • AI agents
  • Temporal runtime
  1. Create a project

Create a CraftTS project#

Use craft create to generate a framework-independent CraftTS application with routing, a typed API example, linting, tests, and the architecture contract already wired up.

Prerequisites#

The beta toolchain requires Node.js 20.19 or newer. The craft executable is published by @craft-ts/dev-tools; it is not provided by the unrelated npm package named craft.

For a new project, invoke the executable explicitly through npx:

bash
npx --yes --package @craft-ts/dev-tools@beta craft create my-app

The first --yes belongs to npx: it accepts the temporary package installation. The command remains interactive because craft create itself was not given --yes.

The command uses the published beta package. A checkout of CraftTS can contain a newer creation flow than the version currently published on npm; check the resolved version with npm view @craft-ts/dev-tools@beta version if the prompts shown by your terminal do not match this page.

Interactive creation#

Run the command in a real terminal without craft create --yes:

bash
npx --yes --package @craft-ts/dev-tools@beta craft create my-app

The generator presents menus in this order:

  • the application type: frontend-only or full-stack;

  • for a full-stack app, the backend runtime: promise or effect (EffectTS v4 is recommended);

  • the frontend runtime: plain or effect;

  • type-safe i18n, its locales, and its default locale;

  • the design system;

  • typed CSS;

  • a standalone or Nx workspace;

  • integrations for Codex, Cursor, or Claude Code.

The frontend and backend choices are independent. The frontend choice controls whether CraftTS's Effect adapter is installed in the browser; the backend choice controls only the server functions. To use EffectTS v4 on the backend while keeping the browser on base CraftTS, choose plain for the frontend and effect for the backend. This generates no Effect adapter or Effect imports in the browser app.

Frontend choiceBackend choiceEffect adapter in browser
plaineffectNo
effecteffectYes

Use ↑/↓ to move and Enter to confirm a single choice. For locales and agent integrations, use Space to select or deselect several items, then Enter to confirm. The project directory remains a text field because it is a free-form path. If the directory is omitted, the generator asks for it too:

bash
npx --yes --package @craft-ts/dev-tools@beta craft create

The agent question is a multi-selection list. Use ↑/↓ to move, Space to select or deselect an integration, and Enter to confirm. Codex starts selected, preserving the default used by scripted creation. Every starter receives an AGENTS.md project guide describing its selected runtimes and features; selected integrations additionally receive their editor-specific project instructions and skills. Claude Code receives CLAUDE.md and skills under .claude/skills/.

Agent-assisted creation#

When an agent starts a new project, it should first ask what kind of application is being built and what its main features are, without collecting detailed requirements yet. If those features imply a backend, it should propose EffectTS v4 for the backend and explain that its typed services, Layers and errors fit CraftTS's typed server boundary. The user can confirm that stack, reject it, or name another backend; the agent must not add an EffectTS backend after an explicit rejection.

The agent should create a domain-ready but empty starter with the design system, typed CSS and strict i18n enabled, and without the explanatory demo pages:

bash
npx --yes --package @craft-ts/dev-tools@beta craft create my-app \
  --yes --no-demos --domain app \
  --frontend-runtime=plain --backend-runtime=effect \
  --i18n=strict --design-system=basic \
  --references=all --agents=codex

Use --backend-runtime=none when the user declines a backend, or the explicit requested backend when it is supported. When no Effect runtime is selected, use --references=craft-ts instead of --references=all. The --no-demos starter still contains the architecture/tooling baseline and a domain boundary, but no prefilled product pages or demo content.

Creating inside an existing Git repository#

An existing .git directory makes the destination non-empty. Generate into the current repository with --force:

bash
cd pet-foster-family
npx --yes --package @craft-ts/dev-tools@beta craft create . --force

--force only permits writing into a non-empty destination; it does not turn off the configuration prompts. Review generated file changes before committing when the repository already contains application code.

During the interactive flow, reference sources are vendored automatically with git subtree:

  • CraftTS sources go into .references/craft-ts;

  • EffectTS sources are also vendored when an Effect frontend or backend is selected;

  • the sources are committed in the project repository for agents without replacing the installed npm packages.

There is no reference confirmation prompt. The same defaults apply in non-interactive mode: CraftTS is vendored, and EffectTS is vendored whenever an Effect frontend or backend is selected. Use --references=none to opt out, or --references=craft-ts / --references=all to choose explicitly.

The vendored repositories are read-only reference material for coding agents only. The generated application always imports the published CraftTS and EffectTS npm packages from package.json; it does not use file: dependencies or TypeScript/Vite aliases to the references. Use npm run update:references to run git subtree pull and refresh the recorded source SHA.

Non-interactive creation#

Pass --yes after create to use defaults and disable all prompts. Combine it with explicit options when the generated configuration must be reproducible:

bash
npx --yes --package @craft-ts/dev-tools@beta craft create my-app \
  --yes --effect=none --agents=codex

For a minimal plain starter:

bash
npx --yes --package @craft-ts/dev-tools@beta craft create my-app \
  --yes --effect=none --i18n=none --design-system=none \
  --agents=none

To create a backend-only Effect project and vendor both reference sources:

bash
npx --yes --package @craft-ts/dev-tools@beta craft create my-app \
  --yes --frontend-runtime=plain --backend-runtime=effect \
  --references=all

The main configuration options are:

OptionValuesPurpose
--effectv4, noneSelect the Effect v4 or plain starter
--frontend-runtimeplain, effectChoose whether to install the Effect adapter in the browser
--backend-runtimenone, promise, effectChoose server functions independently of the frontend
--effect-scopenone, frontend, backend, bothSet Effect placement
--agentscomma-separated names or noneAdd editor-specific agent integrations; AGENTS.md is always generated
--i18nstrict, loose, noneConfigure type-safe i18n
--design-systembasic, noneInclude the design-system starter
--workspacestandalone, nxChoose the workspace layout
--referencesnone, craft-ts, allInclude source references (default: CraftTS, plus EffectTS when selected)
--no-demosflagGenerate a domain feature without explanatory demo pages
--domainslugName the first domain feature when using --no-demos
--forceflagAllow an existing non-empty destination
--jsonflagPrint the effective configuration as JSON

Every project styles through @craft-ts/style, whatever the options: there is no plain-CSS starter and no src/styles.css. The element defaults and the app shell live in src/app/app.style.ts; --design-system=basic adds the starter design system in src/app/ui/ui.style.ts. --no-typed-css is no longer accepted.

Use craft create --help to see the complete list:

bash
npx --yes --package @craft-ts/dev-tools@beta craft create --help

For a domain-first starting point, omit the explanatory home/services/about pages and name the feature explicitly:

bash
npx --yes --package @craft-ts/dev-tools@beta craft create pet-foster \
  --yes --no-demos --domain animal --frontend-runtime=effect \
  --backend-runtime=effect

The generated feature lives under src/app/features/animal/. Add a form to that feature with the existing primitives and its unit/submission test:

bash
craft add form animal
# advanced nested/schema variant:
craft add form animal --advanced

After generation#

The generator creates a Git repository when the destination is not already inside another repository. When references are enabled, it adds them as tracked Git subtrees and creates the minimal Git history required by git subtree when the destination is a new repository. The generated .gitignore excludes node_modules/, build outputs, and test reports.

Install dependencies and start the generated application:

bash
cd my-app
npm install
npm run dev

The generated project also includes the following checks:

bash
npm run lint
npm run typecheck
npm test
npm run architecture
npm run build

npm run style:check#

With typed CSS enabled, the project gets one more, and it is the only one that needs explaining:

bash
npm run style:check

It builds once — which is how the style plugin writes .craft/style-graph.json — then proves WCAG 2.2 AA text contrast for every element the graph can show holds text, in every state your axes can produce, with no browser involved. It is in the generated CI workflow.

The starter is set up to pass it out of the box: the palette is named, so a failure can say ui.accent.dangerHover rather than a hexadecimal string, and the generated link writes its hovered colour through interaction.hover rather than a hand-written selector, so the hovered state is a state the check can actually measure.

Two things to know before your first failure:

  • A result the analysis cannot prove fails the run. --allow-indeterminate turns those into warnings and you have to type it. A check whose default treats "I could not tell" as "fine" reports a clean bill on the part of the application it did not understand.

  • A clean run is a contrast proof, not an accessibility audit.

Text contrast has the full coverage contract: what is proven, what comes back as indeterminate, and how to close a gap honestly.

Generated architecture rules#

The generated eslint.config.mjs imports @craft-ts/dev-tools/eslint-rules and activates the selected recommended or effect preset. These presets enforce the same architecture as the generated project guide:

  • remote reads and writes stay directly in query or mutation loaders; they must not be hidden in craftMethod;

  • query, mutation and asyncProcess loaders are generator functions; express asynchronous work with yield*, never with async or a native Promise return;

  • resource loaders infer their result instead of using casts such as as PromiseLike<...>;

  • route-visible filters, search, sort and pagination use route-level queryParams, not component-local state;

  • template event handlers emit one source$; query, mutation and state react through on$ instead of chaining imperative method calls.

The generated agent skill repeats these boundaries so new features follow the same rules. Run npm run lint after generation to verify the project.

With a backend, src/server/application.ts owns the registry and runtime Layer, while src/server/node-http.ts is only the Node stream adapter. server.ts re-exports both for compatibility. In the backend-only Effect profile, the browser remains plain CraftTS; Effect services, middleware and error projections stay under the server boundary.

Troubleshooting#

could not determine executable to run#

If the error mentions craft@0.1.0, npx resolved the unrelated public npm package named craft. Use the explicit --package @craft-ts/dev-tools@beta form shown above.

If @craft-ts/dev-tools is already installed in the project, its local binary can also be called with:

bash
npx craft create my-app

The explicit form is still the safest command when bootstrapping a project that has no package.json yet.

←Guide overviewThe mental model→

On this page

  • Prerequisites
  • Interactive creation
  • Agent-assisted creation
  • Creating inside an existing Git repository
  • Non-interactive creation
  • After generation
  • npm run style:check
  • Generated architecture rules
  • Troubleshooting
  • could not determine executable to run

@craft-ts · MIT licensed

GitHubnpm

Search