Rewriting PHP codebases to TypeScript with the LEAP Protocol
Here’s how to rewrite PHP to TypeScript with zero guesswork: extract specs → generate tests → implement in parallel → roll out with parity. We start by mining your PHP app (Laravel, Symfony, Slim) for executable specs: routes, middleware, request/response schemas, database constraints, and domain rules implied by code and existing PHPUnit tests. From those, we generate language-agnostic tests and golden fixtures that lock in today’s behavior, including edge cases (nullables, multibyte text, locale-specific decimals, file uploads). Next, we implement a TypeScript service in parallel—typically NestJS or Fastify—driven by those specs and tests. We map data access from Eloquent/Doctrine to Prisma, TypeORM, or Knex, keeping SQL semantics and serialization identical. Finally, we roll out with parity: shadow traffic, response diffs, and feature-flagged cutovers, all test-gated so nothing ships unless it matches. The result is a TypeScript system with the same observable behavior as your PHP app, improved maintainability, and no frozen roadmaps. This is the LEAP Protocol: spec-first, test-gated, agent-agnostic delivery.
Why TypeScript for PHP migrations
- Static types catch boundary errors early: typed DTOs, controllers, and services reduce “stringly-typed” bugs common in PHP arrays and mixed values.
- Event-loop concurrency without PHP-FPM overhead: long-lived Node processes handle I/O efficiently, ideal for websockets, streaming, and high-connection APIs.
- Mature web frameworks: NestJS (decorators, DI, guards) and Fastify (AJV schema validation, high throughput) provide predictable, testable architecture.
- Type-safe data access: Prisma/TypeORM/Knex offer explicit schemas, migrations, and codegen—cleanly replacing Eloquent/Doctrine while keeping SQL under control.
- Shared contracts front-to-back: generate OpenAPI/JSON Schema and share TypeScript types with React/Vue clients, eliminating drift between server and UI.
Our methodology
1) Spec extraction from PHP - Parse routes/middleware from Laravel or Symfony, normalize PSR-7/PSR-15 semantics, and derive OpenAPI/JSON Schema for all public endpoints. - Lift domain invariants from controllers, form requests, and policies; capture serialization rules (dates, enums, casing). - Snapshot data contracts and query shapes from Eloquent/Doctrine, including eager/lazy loading patterns and pivot tables.
2) Test generation and golden fixtures - Convert PHPUnit coverage and sample payloads into LEAP specs with cross-runtime tests. - Autogenerate Jest/Vitest suites and schema validators that exactly match today’s PHP behavior. - Record golden responses for shadow traffic diffs, including headers, cookies, error formats, and pagination.
3) Parallel TypeScript implementation - Build services in NestJS or Fastify with Zod/class-validator and OpenAPI-first routing. - Replace Eloquent/Doctrine with Prisma or Knex; preserve SQL queries, nullability, and cascades; codify transactions and isolation. - Map Artisan commands/queues to ts-node scripts and BullMQ/Cloud queues; replicate cron schedules and failure semantics.
4) Coexistence and data strategy - Strangler pattern via Nginx/Envoy: route selected endpoints to TypeScript while PHP serves the remainder. - Share Redis-based sessions and cache until cutover; mirror writes if needed; maintain consistent cookie names and SameSite/secure flags. - Bridge messaging (SQS/RabbitMQ) so both runtimes interoperate during transition.
5) Rollout with parity and safeguards - Shadow live traffic to the TypeScript service; diff JSON bodies, headers, status codes, and timing envelopes. - Gate releases on passing LEAP tests; add SLO monitors and reversible feature flags. - Phase cutover path-by-path with instant rollback.
Specific PHP concerns we handle
- Eloquent/Doctrine differences: lazy loading vs explicit includes, attribute casting, pivot tables, soft deletes, and Carbon date serialization to ISO 8601 with correct time zones.
- Magic/dynamic behavior: __get/__call, ArrayAccess, and global helpers converted into explicit functions and typed interfaces to avoid hidden coupling.
- Request lifecycle and superglobals: $_POST/$_GET/$_FILES to Fastify/NestJS request objects; multipart streaming; type-converting form fields (booleans, numbers, locale commas) without surprises.
- Sessions and auth: PHP session handlers and Laravel Sanctum/Passport mapped to Fastify secure-session or Nest Passport/JWT; CSRF and cookie attributes preserved during coexistence.
- Autoloading/DI and config: Composer PSR-4/service containers ported to ES modules and NestJS DI; environment config and boot-time differences reconciled for long-lived Node processes.
Proof
- sqlite-leap — one spec, five SQLite engines generated across runtimes: https://github.com/safitudo/sqlite-leap
- semver-leap — semantic versioning spec with 5,632 passing tests across implementations: https://github.com/safitudo/semver-leap
- The LEAP Protocol — spec-first, test-gated, agent-agnostic delivery: https://github.com/safitudo/leap
Pricing & timeline
- Timeline: 4–12 weeks depending on scope, with most mid-sized APIs landing in 6–8 weeks.
- Pricing: fixed-price proposal after a short discovery; typical engagements range from $40k–$120k.
- Structure: week 1 discovery/spec extraction, weeks 2–8 parallel implementation and coexistence, weeks 1–3 rollout/verification depending on traffic and risk tolerance.
- Deliverables: LEAP specs, autogenerated tests, TypeScript service (NestJS or Fastify), data-access layer (Prisma/TypeORM/Knex), migration playbook, and observability dashboards.
Ready to move from PHP to TypeScript without breaking behavior? Request a LEAP discovery and get a fixed-price plan, concrete risks, and an execution calendar.
Leap Agentic is distinct from Legacyleap.ai and Impetus Leap AI.
Leap Agentic is distinct from Legacyleap.ai and Impetus Leap AI.