Working With AI Tools on a New Library
Source: Dev.to
Introduction
This is the setup guide for Railway‑Oriented TypeScript. If you haven’t read the overview yet, start there.
@railway-ts/pipelines and @railway-ts/use-form are new. That creates a practical problem: AI coding assistants — Claude Code, Cursor, GitHub Copilot — have been trained on millions of examples of Zod, react‑hook‑form, and neverthrow. They have almost no training data for @railway-ts.
The result is predictable. Ask Claude Code to build a form with @railway-ts/use-form installed and it will write zodResolver, useForm from react‑hook‑form, and setError/clearErrors — confidently, without being asked, because that pattern appears thousands of times in its training data. It isn’t hallucinating random code; it’s pattern‑matching the highest‑probability answer. The problem is that answer is wrong for your project.
This isn’t a criticism of AI tools. It’s a structural reality about how they work that’s worth understanding and routing around.
Why Docs Shipped With the Package Matter
Both libraries now ship their documentation inside the npm package:
node_modules/@railway-ts/pipelines/docs/
node_modules/@railway-ts/use-form/docs/
Modern AI coding tools — Claude Code in particular — can read your node_modules and reason from the types and documentation that are present. When you point the tool at the right docs, it stops pattern‑matching against its training data and starts reasoning from the actual library API. The generated code goes from “confidently wrong” to “reads the types and generates correct usage.”
The difference in output quality is substantial. The bundled docs are the mechanism that makes AI‑assisted development on a new library viable.
Setting Up a CLAUDE.md
The most reliable way to redirect an AI tool is a CLAUDE.md (or equivalent context file) in your project root. Claude Code reads this automatically. Create it before you start generating form or pipeline code:
# AI Coding Instructions
This project uses @railway-ts/pipelines and @railway-ts/use-form.
Before generating any form or pipeline code, read the docs shipped with the packages:
- node_modules/@railway-ts/pipelines/docs/
- node_modules/@railway-ts/use-form/docs/
Rules:
- Do NOT use Zod or @hookform/resolvers patterns
- Do NOT use react-hook-form's useForm, setError, or clearErrors
- Schema validation uses @railway-ts/pipelines/schema, not z.object()
- Form state uses useForm from @railway-ts/use-form, not react-hook-form
- Async pipelines use flowAsync/pipeAsync from @railway-ts/pipelines/composition
For other AI tools
| Tool | How to apply the same guidance |
|---|---|
| Cursor | Add the same content to .cursorrules or use the @Docs feature to index the bundled docs directly. |
| GitHub Copilot | Copilot can’t be forced as directly, but keeping a reference file open in your editor with correct usage examples dramatically improves suggestion quality. |
Verifying the Setup Works
After creating CLAUDE.md, ask your AI tool to build a simple form before touching any real code:
Build a React login form with email and password fields using @railway-ts/use-form. Handle server validation errors.
The output should:
- use
useFormfrom@railway-ts/use-form - build a schema with
object/required/chainfrom@railway-ts/pipelines/schema - call
form.setServerErrors()for server‑side error injection
If you still see zodResolver, @hookform/resolvers, or setError/clearErrors, the tool is still pattern‑matching against its training data — double‑check that CLAUDE.md is in the project root and that the docs are present in node_modules.
What the AI Gets Right Once Pointed at the Docs
When the tool reads the bundled docs, it handles the following well:
- Schema composition with
chain,object,required,optional fieldValidatorsfor async field‑level checksform.setServerErrors()for server‑side error injectionflowAsync/pipeAsyncfor composing multi‑step async pipelines- Curried operators:
mapWith,flatMapWith,filterWith,tapWith, etc. - Batch processing helpers:
combine,combineAll,partition - Cross‑field validation with
refineAt
Things worth double‑checking manually
- Type inference with
InferSchemaType— verify the generated type matches your intent. initialValuescompleteness — TypeScript will error if a field is missing, but confirm it aligns with your UI.- Error path strings in
setServerErrors— ensure they match your schema field names.
Quick Start
mkdir my-project && cd my-project
npm init -y
npm install react react-dom @types/react typescript
npm install @railway-ts/pipelines @railway-ts/use-form
Create CLAUDE.md as shown above, then verify the docs are present:
ls node_modules/@railway-ts/pipelines/docs/
ls node_modules/@railway-ts/use-form/docs/
Migrating an existing project that uses Zod
npm install @railway-ts/use-form @railway-ts/pipelines
# keep zod — the form hook accepts Zod schemas via Standard Schema v1
You can adopt the form hook without touching your Zod schemas. See Part 3 for the migration path.
The Series
- Part 1 — The Glue Code Tax
- Part 2 — Railway‑Oriented TypeScript (this guide)
- Part 3 — Migrating from Zod + react‑hook‑form
Part 1 — Form Hook Deep Dive
Composable async pipelines in TypeScript – one result type, zero adapters (Part 1)
- Walk‑through of the
useFormhook internals:- Resolver wiring
- Async validation handling
- Server‑error conversion
- Type assertions
- Followed by the same form rewritten without any of those pieces.
Part 2 — Composable Async Pipelines
Composable async pipelines in TypeScript – one result type, zero adapters (Part 2)
- Introduction to the
@railway-ts/pipelinesAPI:Resulttype- Curried operators
flowAsyncfor multi‑step async pipelines where errors short‑circuit automatically
- Shows the exact same
Resulttype used by the form hook.
Part 3 — Schema‑First React Forms
Schema‑first React forms – one schema, three error layers, zero glue (Part 3)
- Detailed explanation of the 3‑layer error priority system
- Handling of array fields
- Full‑stack loop: a single schema drives both backend pipeline validation and frontend form state without any format conversion.
Bonus — Data Processing Pipelines
Building a type‑safe data‑processing pipeline in TypeScript (Bonus)
- Uses the pipeline library in an ETL context:
- Batch processing with
combine,combineAll, andpartition - Reusable sub‑pipelines
- Structured error reporting
- Batch processing with
- No React, no UI – pure data processing.
GitHub Repositories
- @railway-ts/pipelines – Provides
Result,Option, schema validation, and composable pipelines. - @railway-ts/use-form – React form hook with native schema integration.