[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-encore-encore-migrate":3,"mdc-yrv36f-key":37,"related-repo-encore-encore-migrate":4173,"related-org-encore-encore-migrate":4270},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":24,"repoUrl":25,"updatedAt":26,"license":27,"forks":28,"topics":29,"repo":32,"sourceUrl":35,"mdContent":36},"encore-migrate","migrate backend applications to Encore","Migrate an existing backend application to Encore. Supports any source framework, targets Encore.ts or Encore Go. Drives a structured DISCOVER → PLAN → MIGRATE workflow with `migration-plan.md` tracking.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"encore","Encore","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fencore.png","encoredev",[13,15,18,21],{"name":9,"slug":8,"type":14},"tag",{"name":16,"slug":17,"type":14},"Migration","migration",{"name":19,"slug":20,"type":14},"Engineering","engineering",{"name":22,"slug":23,"type":14},"API Development","api-development",26,"https:\u002F\u002Fgithub.com\u002Fencoredev\u002Fskills","2026-04-06T18:09:49.840129",null,5,[30,31],"claude-code","skills",{"repoUrl":25,"stars":24,"forks":28,"topics":33,"description":34},[30,31],"Agent Skills for development with Encore.","https:\u002F\u002Fgithub.com\u002Fencoredev\u002Fskills\u002Ftree\u002FHEAD\u002Fencore\u002Fmigrate","---\nname: encore-migrate\ndescription: Migrate an existing backend application to Encore. Supports any source framework, targets Encore.ts or Encore Go. Drives a structured DISCOVER → PLAN → MIGRATE workflow with `migration-plan.md` tracking.\nwhen_to_use: >-\n  User wants to convert an existing app from Express, Fastify, Hono, Koa, NestJS, Restify, gin, Echo, Chi, Fiber, FastAPI, Flask, Django, Rails, Spring Boot, or vanilla Node.js \u002F Go to Encore. Trigger phrases: \"convert from Express\", \"port to Encore\", \"migrate this Fastify app\", \"rewrite my Hono backend\", \"switch from FastAPI to Encore\", \"I have an existing X app I'd like to convert\".\n---\n\n# Migrate to Encore\n\nThis skill guides migrating any existing backend application to Encore, one migration unit at a time. It supports any source language or framework and targets both Encore.ts and Encore Go. A `migration-plan.md` summary file and `migration-plan\u002F` directory of per-unit detail files are created at the Encore project root to track progress across sessions. This skill contains no Encore code examples — it delegates all Encore-specific implementation to the appropriate language-specific skills.\n\n## Phase Detection\n\nBefore doing anything, determine which phase to enter:\n\n- **No `migration-plan.md` exists** in the Encore project directory → Start at **Phase 1: DISCOVER**\n- **`migration-plan.md` exists but no `migration-plan\u002F` directory** → Resume at **Phase 2: PLAN** (discovery done, detail files not yet written)\n- **`migration-plan\u002F` directory exists with pending units** (any unit in the summary with status `pending` or `in progress`) → Resume at **Phase 3: MIGRATE**\n- **All units in the summary are `migrated`, `skipped`, or `manual validation needed`** → Go to **Phase 4: COMPLETE**\n\n### Resuming a Migration (Phase 3)\n\nWhen `migration-plan.md` and `migration-plan\u002F` exist with pending units:\n\n1. Read `migration-plan.md` (summary only — do NOT read all detail files)\n2. Report current status to the user — for example: \"3 of 7 units migrated, next suggested: billing (all its dependencies are migrated)\"\n3. Ask the user what they would like to work on next, offering a suggestion based on the dependency order in the plan\n\n## Phase 1 — Discover\n\n### 1. Gather Information\n\nAsk the user for:\n\n- **Path to the source system** (the existing codebase being migrated)\n- **Local URL where the source system runs** (if applicable — needed for HTTP comparison validation later)\n- **Target language:** Encore.ts or Encore Go\n\n### 2. Analyze the Source Codebase\n\nRead the source codebase and inventory all entities:\n\n| Category | What to look for |\n|----------|-----------------|\n| Services \u002F modules \u002F domains | Distinct bounded contexts, separate deployable units, route groupings |\n| API endpoints | Method, path, handler function, request\u002Fresponse shapes |\n| Databases | Type (Postgres, MySQL, etc.), tables, schemas, migration files |\n| Pub\u002FSub topics and subscriptions | Topic names, publishers, subscribers, message shapes |\n| Cron jobs \u002F scheduled tasks | Schedule expressions, handler functions |\n| Auth middleware \u002F handlers | Authentication strategies, token validation, session management |\n| Secrets \u002F environment variables | All referenced env vars and secrets, noting which are sensitive |\n| Existing tests | Test files, which entities they cover, test framework used |\n| Frontend code | React\u002FVue\u002FAngular components, static HTML, CSS, client-side JS — these are out of scope |\n\n### 3. Identify Frontend Code\n\nFull-stack repos and monorepos often mix backend and frontend code. The migration targets backend only — frontend code is out of scope.\n\n**Detect frontend directories and mark them as out of scope.** Common indicators:\n\n| Pattern | Examples |\n|---------|----------|\n| Dedicated frontend directories | `frontend\u002F`, `client\u002F`, `web\u002F`, `app\u002F` (when it contains React\u002FVue\u002FAngular), `src\u002Fcomponents\u002F`, `public\u002F` |\n| Frontend config files | `next.config.js`, `vite.config.ts`, `nuxt.config.ts`, `angular.json`, `.svelte-kit\u002F`, `remix.config.js` |\n| Package dependencies | `react`, `vue`, `@angular\u002Fcore`, `svelte` in `package.json` |\n\n**Flag framework server-side code that *should* be migrated.** Some frontend frameworks embed backend logic that contains API endpoints, database queries, or server-side business logic:\n\n| Framework | Server-side locations | What to look for |\n|-----------|----------------------|-----------------|\n| Next.js | `pages\u002Fapi\u002F`, `app\u002F*\u002Froute.ts` | API route handlers — these are backend endpoints |\n| Remix | `app\u002Froutes\u002F*.tsx` (loader\u002Faction exports) | `loader` and `action` functions contain server logic |\n| Nuxt | `server\u002Fapi\u002F`, `server\u002Froutes\u002F` | Server API routes |\n| SvelteKit | `src\u002Froutes\u002F+server.ts`, `+page.server.ts` | Server endpoints and load functions |\n| Astro | `src\u002Fpages\u002F*.ts` (non-`.astro`) | API endpoints |\n\nWhen framework server-side code is found, **ask the user what to do with it.** Not all server-side code should move to Encore — sometimes a thin backend layer (BFF, auth proxy, SSR data fetching) should stay in the frontend framework alongside an Encore backend.\n\nPresent the user with what was found and ask:\n\n> \"I found \u003CN> server-side routes in your \u003Cframework> app (e.g., `pages\u002Fapi\u002Fusers.ts`, `app\u002Fbilling\u002Froute.ts`). These contain backend logic that *could* be migrated to Encore, but some teams prefer to keep a thin server layer in their frontend framework for things like SSR data fetching or BFF proxying. Would you like to:\n> 1. **Migrate all** server-side routes to Encore\n> 2. **Migrate some** — I'll list them and you pick which ones move\n> 3. **Keep all in \u003Cframework>** — only migrate the standalone backend code\"\n\nBased on the user's choice:\n\n- **Migrate all:** Extract the backend logic into migration units. Leave frontend rendering code out of scope. Note in the migration plan which source files contain mixed frontend\u002Fbackend code.\n- **Migrate some:** Present the list of server-side routes and let the user select. Include selected routes in migration units, mark the rest as out of scope.\n- **Keep all:** Mark all framework server-side code as out of scope alongside the frontend. Only standalone backend code (Express routes, standalone API servers, etc.) enters migration units.\n\n**Report to the user:** List all detected frontend directories and the decision made about framework server-side code. Example: \"I found a Next.js frontend in `app\u002F` — the React components are out of scope. You chose to migrate 8 of the 12 API routes from `pages\u002Fapi\u002F` to Encore and keep 4 thin proxy routes in Next.js.\"\n\n### 4. Group Entities into Migration Units\n\nGroup the discovered entities into migration units using these heuristics in priority order:\n\n1. **Existing service boundaries** — If the source app already has services, modules, or packages, use those as the starting point for chunks\n2. **URL path prefixes** — Group endpoints sharing a path prefix (e.g., `\u002Fusers\u002F*`, `\u002Fbilling\u002F*`)\n3. **Shared database tables** — Endpoints that read\u002Fwrite the same tables belong together\n4. **Shared types\u002Fmodels** — Endpoints that share request\u002Fresponse types or domain models\n\n**Chunk sizing:** Aim for 5-15 endpoints per migration unit. If a group exceeds ~15 endpoints, suggest splitting it further (e.g., `users-crud` and `users-admin`). If a group has fewer than 3 endpoints, consider merging it with a related chunk.\n\n**Cross-cutting concerns** get their own migration units: auth, secrets, and standalone infrastructure (pub\u002Fsub topics, cron jobs not tightly coupled to one service) are separate units since they follow different dependency tiers.\n\n**For monoliths with no clear boundaries:** Fall back to URL path prefix grouping, then ask: \"These groupings are based on URL paths — would you like to reorganize them by domain?\"\n\n### 5. Present the Migration Units\n\nPresent the migration units to the user as a summary table:\n\n| Unit | Endpoints | DB Tables | Other | Complexity |\n|------|-----------|-----------|-------|------------|\n\nInclude total counts (e.g., \"7 migration units covering 42 endpoints, 3 databases\"). For each unit, assess overall migration complexity:\n\n- **Low** — direct Encore equivalents exist, straightforward mapping\n- **Medium** — requires restructuring or has partial Encore equivalents\n- **High** — no direct equivalent, needs redesign or custom solution\n\nOffer to show the detail of any unit if the user wants to inspect what's inside before confirming.\n\n### 6. Show Code Previews\n\nFor 2-3 representative entities (pick a mix of simple and complex from different units), show a short \"before and after\" preview of what the source code looks like now and what the Encore version will look like. Use the appropriate language-specific skill to inform the preview. Keep previews brief — one endpoint, one query, or one topic declaration is enough per preview.\n\n### 7. Confirm with the User\n\nAsk the user to confirm the migration units are correct. Specifically ask:\n\n- \"Are there any services, endpoints, or other entities I missed?\"\n- \"Would you like to split, merge, or rename any of these migration units?\"\n- \"Is there anything you want to exclude from the migration?\"\n\n### 8. Iterate if Needed\n\nIf the user identifies missing entities or wants to adjust chunk boundaries, update the units and re-present the summary table. Repeat until the user confirms the migration units are accurate.\n\n## Phase 2 — Plan\n\n### 1. Check for Existing Encore Project\n\nCheck if an Encore project already exists at the target path (look for `encore.app` file). If yes, confirm with the user that this is the correct project. If no, help create one by invoking the `encore-getting-started` skill (or `encore-go-getting-started` for Go).\n\n### 2. Gather Target Information\n\nAsk the user for:\n\n- **Path to the Encore project** (where the migrated code will live)\n- **Local URL where the Encore app will run** (default: `http:\u002F\u002Flocalhost:4000`)\n\n### 3. Determine Dependency Order\n\nOrder migration units based on dependencies. Follow this tier order:\n\n1. **Secrets \u002F config** — no dependencies, needed by everything\n2. **Databases** — schema and migrations must exist before services can use them\n3. **Auth** — auth handlers are needed before protected endpoints\n4. **Leaf units** — units with no cross-service dependencies\n5. **Dependent units** — units that depend on already-migrated units\n6. **Pub\u002FSub topics and subscriptions** — often depend on services being in place\n7. **Cron jobs** — typically depend on service endpoints\n\nWithin each tier, suggest the simplest unit first (fewest endpoints, smallest schema, least complexity).\n\n### 4. Write migration-plan.md (Summary)\n\nWrite the `migration-plan.md` summary file to the Encore project root using the template in the \"migration-plan.md Format\" section below. Fill in all migration units with status `pending`.\n\n### 5. Write Detail Files\n\nCreate a `migration-plan\u002F` directory at the Encore project root. Write one detail file per migration unit using the template in the \"Detail File Format\" section below. Each file is named `migration-plan\u002F\u003Cunit-name>.md`.\n\n### 6. Propose First Unit\n\nPropose the first migration unit, explaining why it should go first based on the dependency order. Wait for user approval before proceeding to Phase 3.\n\n## Phase 3 — Migrate (Loop)\n\n### 1. Identify Next Unit\n\nRead `migration-plan.md` (summary only) and identify the next pending migration unit based on the dependency order.\n\n### 2. Suggest and Confirm\n\nSuggest the next unit to migrate and explain why this one is next (e.g., \"This unit has no dependencies on unmigrated units\" or \"The database must exist before we can migrate the service that uses it\"). Ask the user if they want to proceed with this unit or pick a different one.\n\n### 3. Load the Unit Detail\n\nRead the detail file for the chosen unit (`migration-plan\u002F\u003Cunit-name>.md`). Do NOT read detail files for other units.\n\n### 4. Migrate Each Entity\n\nFor each entity in the unit:\n\n#### a. Implement\n\nInvoke the appropriate language-specific skill based on the entity type and target language:\n\n| Migrating... | Encore.ts skill | Encore Go skill |\n|---|---|---|\n| Service structure | `encore-service` | `encore-go-service` |\n| API endpoints | `encore-api` | `encore-go-api` |\n| Auth | `encore-auth` | `encore-go-auth` |\n| Database + migrations | `encore-database` | `encore-go-database` |\n| Pub\u002FSub topics & subscriptions | `encore-pubsub` | `encore-go-pubsub` |\n| Cron jobs \u002F scheduled tasks | `encore-cron` | `encore-go-cron` |\n| Object storage \u002F file uploads | `encore-bucket` | `encore-go-bucket` |\n| Caching (Redis) | `encore-cache` | `encore-go-cache` |\n| Secrets \u002F API keys \u002F credentials | `encore-secret` | `encore-go-secret` |\n| Webhooks (Stripe, GitHub, etc.) | `encore-webhook` | `encore-go-webhook` |\n| Tests | `encore-testing` | `encore-go-testing` |\n\n#### b. Migrate Tests\n\nIf the source entity has associated tests, migrate them using the appropriate testing skill (`encore-testing` or `encore-go-testing`). Adapt test assertions to match Encore API patterns. If the source entity has no tests, note this in the detail file.\n\n#### c. Validate\n\nThree validation layers are applied to each entity before it can be marked as `migrated`. Every entity must go through all applicable layers.\n\n##### Layer 1: Test Migration (Primary)\n\n- When migrating an entity, also migrate its associated tests\n- Use the `encore-testing` skill (or `encore-go-testing` for Go) to implement the tests\n- Run the tests — they must pass before the entity can be marked as `migrated`\n- If the source entity had no tests, note \"no source tests\" in the plan and rely on the other layers\n\n##### Layer 2: HTTP Comparison (Endpoints Only, Best-Effort)\n\nWhen both systems are running locally, call the same endpoint on both the source system and the Encore app, then compare:\n\n- **HTTP status code** — must match\n- **Response body structure** — keys and shape must match (values may differ for dynamic data like timestamps or IDs)\n\n**Skip this layer when:**\n\n- The endpoint requires auth credentials the agent cannot obtain (ask the user — allow skip)\n\n**If a request to either system fails to connect**, ask the user to start the app before retrying. Do not silently skip — the user may have simply forgotten to start it.\n\n**Always ask the user before making any HTTP call that could have side effects.**\n\n##### Layer 3: Verification-Before-Completion Gate\n\nBefore marking ANY entity as `migrated`, the agent MUST have fresh evidence from the current session:\n\n- Test command output showing pass count and exit code, OR\n- HTTP comparison results showing a match, OR\n- Explicit user approval to skip validation\n\n**Rules:**\n\n- No \"should work\", \"looks correct\", or \"seems fine\" — only evidence-backed claims\n- The agent must state exactly what it verified and what the output was\n- If evidence is insufficient, mark the entity as `manual validation needed`, not `migrated`\n- Stale evidence from a previous session does not count — re-run validation if resuming\n\n#### d. Update the Detail File\n\nUpdate the entity's status in the unit's detail file (`migration-plan\u002F\u003Cunit-name>.md`) and record validation evidence in that file's Validation Log table.\n\n#### e. Update the Summary\n\nWhen all entities in a unit are complete, update the unit's status in `migration-plan.md` to `migrated`. If some entities are pending, set the unit status to `in progress`.\n\n### 5. Continue or Pause\n\nAfter completing a unit, ask \"What would you like to migrate next?\" and suggest the next unit based on dependency order.\n\n### 6. Batching\n\nThe default is one unit at a time. If the user says \"keep going\", \"do them all\", or similar, batch multiple units but still validate each entity individually before marking it as migrated.\n\n## Phase 4 — Complete\n\nWhen all units in `migration-plan.md` are `migrated`, `skipped`, or `manual validation needed`:\n\n1. **Present a final summary** from `migration-plan.md`:\n   - Total units migrated\n   - Units marked as `manual validation needed` — read those specific detail files and list the entities that need attention with reasons\n   - Units skipped (list them with reasons)\n2. **Suggest running the full test suite** one final time to catch any integration issues\n3. **Note any manual validation items** that still need human attention\n4. **If the source system had frontend code**, suggest using the `encore-frontend` skill to reconnect the frontend to the new Encore backend (generate a typed API client, configure CORS, update base URLs)\n5. **Suggest removing `migration-plan.md` and `migration-plan\u002F`** from the project once the user is satisfied with the migration\n\n## Asking Questions\n\nAsk the user before acting when:\n\n- **Service boundaries are unclear** — e.g., \"These route files could be 1 service or 3 — how would you like to split them?\"\n- **No clean Encore equivalent exists** — e.g., Redis caching layer, custom middleware chains, WebSocket handlers\n- **Multiple valid migration strategies exist** — present the options with tradeoffs\n- **Before making any HTTP call that could have side effects** — always ask first\n- **Source code is ambiguous** — when the agent is not confident about what the code does, ask rather than guess\n- **Source system appears to have changed** — if files referenced in a detail file no longer exist or have changed significantly\n\n## Source System Protection\n\nThe source system must never be modified during migration. Follow these rules:\n\n- **Never modify source files** — read them, don't edit them\n- **Never delete source files** — even after migration is complete\n- **Never write to the source directory** — all output goes to the Encore project\n- **Never run destructive commands against the source system** (drop tables, delete queues, etc.)\n- **Ask before any HTTP call that mutates state** on the source system (POST, PUT, DELETE)\n\nIf the user asks to \"clean up\" or \"remove\" the old system, confirm explicitly before taking any action. The source system may still be serving production traffic.\n\n## Edge Cases\n\n### Moving Endpoints Between Units\n\nIf the user realizes an endpoint belongs in a different migration unit:\n\n1. Remove the endpoint row from the source unit's detail file\n2. Add it to the target unit's detail file\n3. Update endpoint counts in `migration-plan.md`\n\n### Splitting a Unit Mid-Migration\n\nIf a unit turns out to be too large while working on it:\n\n1. Create a new detail file for the split-off portion (`migration-plan\u002F\u003Cnew-unit>.md`)\n2. Move pending entities to the new file (already-migrated entities stay in the original)\n3. Add the new unit to the `migration-plan.md` summary table\n4. Insert it in the dependency order (same tier, after the original)\n\n### Monolith to Multiple Encore Services\n\nA single migration unit might map to multiple Encore services. The detail file tracks the source grouping, but the \"Notes\" column can indicate the target Encore service. Ask during migration if the unit maps to one service or should be split across Encore services.\n\n### Source Code Changed Since Discovery\n\nIf files referenced in a detail file no longer exist or have changed significantly since discovery:\n\n1. Flag the discrepancy to the user\n2. Ask whether to update the detail file with the new state or skip the affected entities\n3. If updating, re-assess complexity and adjust the plan accordingly\n\n## Troubleshooting\n\nCommon issues during migration and how to resolve them:\n\n| Problem | Cause | Resolution |\n|---------|-------|------------|\n| Import errors across services | Direct imports between services | Use `~encore\u002Fclients` (TS) or service client packages (Go) instead |\n| Database migration fails | Incompatible SQL syntax | Check Encore uses PostgreSQL — adapt MySQL\u002FSQLite syntax |\n| Pub\u002FSub messages not received | Subscription not registered | Ensure subscription is declared at package level, not inside a function |\n| Cron job not firing | Invalid schedule expression | Encore uses standard cron expressions — verify syntax |\n| `encore run` errors on infrastructure | Infrastructure declared inside functions | Move all infrastructure declarations to package level |\n| Source and Encore responses differ | Missing business logic or different error handling | Compare response shapes carefully, check edge cases |\n| Cannot validate endpoint | Auth required or side effects | Ask user for test credentials, or mark as `manual validation needed` |\n\n## migration-plan.md Format\n\nUse this exact template for the summary plan file. Fill in values from the discovery phase.\n\n```markdown\n# Migration Plan\n\n## Source System\n- **Path:** \u003Csource system path>\n- **URL:** \u003Csource system local URL>\n- **Framework:** \u003Cdetected framework>\n- **Language:** \u003Cdetected language>\n\n## Frontend (Out of Scope)\n- **Detected:** \u003CYes\u002FNo>\n- **Directories:** \u003Clist of frontend directories, or \"None\">\n- **Framework:** \u003Cfrontend framework if detected, or \"N\u002FA\">\n- **Note:** \u003Cany framework server-side code that WAS included in migration units>\n\n## Target System\n- **Path:** \u003Cencore project path>\n- **URL:** \u003Cencore local URL>\n- **Type:** Encore.ts | Encore Go\n\n## Migration Units\n\n| Unit | Endpoints | DB Tables | Other | Complexity | Status |\n|------|-----------|-----------|-------|------------|--------|\n\n## Dependency Order\n1. \u003Cordered list of migration units>\n```\n\n**Status values:** `pending`, `in progress`, `migrated`, `skipped`, `manual validation needed`\n\n**Complexity values:** `Low` (direct equivalent), `Medium` (requires restructuring), `High` (needs redesign)\n\n## Detail File Format\n\nCreate one file per migration unit at `migration-plan\u002F\u003Cunit-name>.md`. Use this exact template:\n\n```markdown\n# Migration Unit: \u003Cunit-name>\n\n## Source\n- **Files:** \u003Clist of source files in this unit>\n- **Depends on:** \u003Cother migration units, with their current status>\n\n## Endpoints\n| Endpoint | Method | Path | Status | Notes |\n|----------|--------|------|--------|-------|\n\n## Database\n| Table | Complexity | Status | Notes |\n|-------|------------|--------|-------|\n\n## Tests\n- **Source tests:** \u003Ctest files and count>\n- **Migrated:** \u003Ccount of migrated tests>\n\n## Validation Log\n| Entity | Tests | HTTP Match | Evidence | Status |\n|--------|-------|------------|----------|--------|\n```\n\nNot all sections are required — omit sections that don't apply to a given unit (e.g., a secrets unit won't have Endpoints or Database sections).\n",{"data":38,"body":40},{"name":4,"description":6,"when_to_use":39},"User wants to convert an existing app from Express, Fastify, Hono, Koa, NestJS, Restify, gin, Echo, Chi, Fiber, FastAPI, Flask, Django, Rails, Spring Boot, or vanilla Node.js \u002F Go to Encore. Trigger phrases: \"convert from Express\", \"port to Encore\", \"migrate this Fastify app\", \"rewrite my Hono backend\", \"switch from FastAPI to Encore\", \"I have an existing X app I'd like to convert\".",{"type":41,"children":42},"root",[43,52,75,82,87,217,224,243,269,275,281,286,319,325,330,475,481,486,496,669,687,868,880,885,964,969,1002,1026,1032,1037,1094,1119,1129,1139,1145,1150,1184,1189,1222,1227,1233,1238,1244,1249,1267,1273,1278,1284,1290,1319,1325,1329,1359,1365,1370,1441,1446,1452,1471,1477,1496,1502,1507,1513,1519,1530,1536,1541,1547,1559,1565,1570,1577,1582,1892,1898,1916,1922,1934,1941,1982,1988,1993,2016,2024,2032,2042,2050,2056,2068,2086,2094,2129,2135,2147,2153,2178,2184,2189,2195,2200,2206,2237,2341,2347,2352,2415,2421,2426,2479,2484,2490,2496,2501,2524,2530,2535,2572,2578,2583,2589,2594,2612,2618,2623,2795,2801,2806,3565,3604,3634,3640,3652,4162,4167],{"type":44,"tag":45,"props":46,"children":48},"element","h1",{"id":47},"migrate-to-encore",[49],{"type":50,"value":51},"text","Migrate to Encore",{"type":44,"tag":53,"props":54,"children":55},"p",{},[56,58,65,67,73],{"type":50,"value":57},"This skill guides migrating any existing backend application to Encore, one migration unit at a time. It supports any source language or framework and targets both Encore.ts and Encore Go. A ",{"type":44,"tag":59,"props":60,"children":62},"code",{"className":61},[],[63],{"type":50,"value":64},"migration-plan.md",{"type":50,"value":66}," summary file and ",{"type":44,"tag":59,"props":68,"children":70},{"className":69},[],[71],{"type":50,"value":72},"migration-plan\u002F",{"type":50,"value":74}," directory of per-unit detail files are created at the Encore project root to track progress across sessions. This skill contains no Encore code examples — it delegates all Encore-specific implementation to the appropriate language-specific skills.",{"type":44,"tag":76,"props":77,"children":79},"h2",{"id":78},"phase-detection",[80],{"type":50,"value":81},"Phase Detection",{"type":44,"tag":53,"props":83,"children":84},{},[85],{"type":50,"value":86},"Before doing anything, determine which phase to enter:",{"type":44,"tag":88,"props":89,"children":90},"ul",{},[91,115,144,180],{"type":44,"tag":92,"props":93,"children":94},"li",{},[95,108,110],{"type":44,"tag":96,"props":97,"children":98},"strong",{},[99,101,106],{"type":50,"value":100},"No ",{"type":44,"tag":59,"props":102,"children":104},{"className":103},[],[105],{"type":50,"value":64},{"type":50,"value":107}," exists",{"type":50,"value":109}," in the Encore project directory → Start at ",{"type":44,"tag":96,"props":111,"children":112},{},[113],{"type":50,"value":114},"Phase 1: DISCOVER",{"type":44,"tag":92,"props":116,"children":117},{},[118,135,137,142],{"type":44,"tag":96,"props":119,"children":120},{},[121,126,128,133],{"type":44,"tag":59,"props":122,"children":124},{"className":123},[],[125],{"type":50,"value":64},{"type":50,"value":127}," exists but no ",{"type":44,"tag":59,"props":129,"children":131},{"className":130},[],[132],{"type":50,"value":72},{"type":50,"value":134}," directory",{"type":50,"value":136}," → Resume at ",{"type":44,"tag":96,"props":138,"children":139},{},[140],{"type":50,"value":141},"Phase 2: PLAN",{"type":50,"value":143}," (discovery done, detail files not yet written)",{"type":44,"tag":92,"props":145,"children":146},{},[147,157,159,165,167,173,175],{"type":44,"tag":96,"props":148,"children":149},{},[150,155],{"type":44,"tag":59,"props":151,"children":153},{"className":152},[],[154],{"type":50,"value":72},{"type":50,"value":156}," directory exists with pending units",{"type":50,"value":158}," (any unit in the summary with status ",{"type":44,"tag":59,"props":160,"children":162},{"className":161},[],[163],{"type":50,"value":164},"pending",{"type":50,"value":166}," or ",{"type":44,"tag":59,"props":168,"children":170},{"className":169},[],[171],{"type":50,"value":172},"in progress",{"type":50,"value":174},") → Resume at ",{"type":44,"tag":96,"props":176,"children":177},{},[178],{"type":50,"value":179},"Phase 3: MIGRATE",{"type":44,"tag":92,"props":181,"children":182},{},[183,210,212],{"type":44,"tag":96,"props":184,"children":185},{},[186,188,194,196,202,204],{"type":50,"value":187},"All units in the summary are ",{"type":44,"tag":59,"props":189,"children":191},{"className":190},[],[192],{"type":50,"value":193},"migrated",{"type":50,"value":195},", ",{"type":44,"tag":59,"props":197,"children":199},{"className":198},[],[200],{"type":50,"value":201},"skipped",{"type":50,"value":203},", or ",{"type":44,"tag":59,"props":205,"children":207},{"className":206},[],[208],{"type":50,"value":209},"manual validation needed",{"type":50,"value":211}," → Go to ",{"type":44,"tag":96,"props":213,"children":214},{},[215],{"type":50,"value":216},"Phase 4: COMPLETE",{"type":44,"tag":218,"props":219,"children":221},"h3",{"id":220},"resuming-a-migration-phase-3",[222],{"type":50,"value":223},"Resuming a Migration (Phase 3)",{"type":44,"tag":53,"props":225,"children":226},{},[227,229,234,236,241],{"type":50,"value":228},"When ",{"type":44,"tag":59,"props":230,"children":232},{"className":231},[],[233],{"type":50,"value":64},{"type":50,"value":235}," and ",{"type":44,"tag":59,"props":237,"children":239},{"className":238},[],[240],{"type":50,"value":72},{"type":50,"value":242}," exist with pending units:",{"type":44,"tag":244,"props":245,"children":246},"ol",{},[247,259,264],{"type":44,"tag":92,"props":248,"children":249},{},[250,252,257],{"type":50,"value":251},"Read ",{"type":44,"tag":59,"props":253,"children":255},{"className":254},[],[256],{"type":50,"value":64},{"type":50,"value":258}," (summary only — do NOT read all detail files)",{"type":44,"tag":92,"props":260,"children":261},{},[262],{"type":50,"value":263},"Report current status to the user — for example: \"3 of 7 units migrated, next suggested: billing (all its dependencies are migrated)\"",{"type":44,"tag":92,"props":265,"children":266},{},[267],{"type":50,"value":268},"Ask the user what they would like to work on next, offering a suggestion based on the dependency order in the plan",{"type":44,"tag":76,"props":270,"children":272},{"id":271},"phase-1-discover",[273],{"type":50,"value":274},"Phase 1 — Discover",{"type":44,"tag":218,"props":276,"children":278},{"id":277},"_1-gather-information",[279],{"type":50,"value":280},"1. Gather Information",{"type":44,"tag":53,"props":282,"children":283},{},[284],{"type":50,"value":285},"Ask the user for:",{"type":44,"tag":88,"props":287,"children":288},{},[289,299,309],{"type":44,"tag":92,"props":290,"children":291},{},[292,297],{"type":44,"tag":96,"props":293,"children":294},{},[295],{"type":50,"value":296},"Path to the source system",{"type":50,"value":298}," (the existing codebase being migrated)",{"type":44,"tag":92,"props":300,"children":301},{},[302,307],{"type":44,"tag":96,"props":303,"children":304},{},[305],{"type":50,"value":306},"Local URL where the source system runs",{"type":50,"value":308}," (if applicable — needed for HTTP comparison validation later)",{"type":44,"tag":92,"props":310,"children":311},{},[312,317],{"type":44,"tag":96,"props":313,"children":314},{},[315],{"type":50,"value":316},"Target language:",{"type":50,"value":318}," Encore.ts or Encore Go",{"type":44,"tag":218,"props":320,"children":322},{"id":321},"_2-analyze-the-source-codebase",[323],{"type":50,"value":324},"2. Analyze the Source Codebase",{"type":44,"tag":53,"props":326,"children":327},{},[328],{"type":50,"value":329},"Read the source codebase and inventory all entities:",{"type":44,"tag":331,"props":332,"children":333},"table",{},[334,353],{"type":44,"tag":335,"props":336,"children":337},"thead",{},[338],{"type":44,"tag":339,"props":340,"children":341},"tr",{},[342,348],{"type":44,"tag":343,"props":344,"children":345},"th",{},[346],{"type":50,"value":347},"Category",{"type":44,"tag":343,"props":349,"children":350},{},[351],{"type":50,"value":352},"What to look for",{"type":44,"tag":354,"props":355,"children":356},"tbody",{},[357,371,384,397,410,423,436,449,462],{"type":44,"tag":339,"props":358,"children":359},{},[360,366],{"type":44,"tag":361,"props":362,"children":363},"td",{},[364],{"type":50,"value":365},"Services \u002F modules \u002F domains",{"type":44,"tag":361,"props":367,"children":368},{},[369],{"type":50,"value":370},"Distinct bounded contexts, separate deployable units, route groupings",{"type":44,"tag":339,"props":372,"children":373},{},[374,379],{"type":44,"tag":361,"props":375,"children":376},{},[377],{"type":50,"value":378},"API endpoints",{"type":44,"tag":361,"props":380,"children":381},{},[382],{"type":50,"value":383},"Method, path, handler function, request\u002Fresponse shapes",{"type":44,"tag":339,"props":385,"children":386},{},[387,392],{"type":44,"tag":361,"props":388,"children":389},{},[390],{"type":50,"value":391},"Databases",{"type":44,"tag":361,"props":393,"children":394},{},[395],{"type":50,"value":396},"Type (Postgres, MySQL, etc.), tables, schemas, migration files",{"type":44,"tag":339,"props":398,"children":399},{},[400,405],{"type":44,"tag":361,"props":401,"children":402},{},[403],{"type":50,"value":404},"Pub\u002FSub topics and subscriptions",{"type":44,"tag":361,"props":406,"children":407},{},[408],{"type":50,"value":409},"Topic names, publishers, subscribers, message shapes",{"type":44,"tag":339,"props":411,"children":412},{},[413,418],{"type":44,"tag":361,"props":414,"children":415},{},[416],{"type":50,"value":417},"Cron jobs \u002F scheduled tasks",{"type":44,"tag":361,"props":419,"children":420},{},[421],{"type":50,"value":422},"Schedule expressions, handler functions",{"type":44,"tag":339,"props":424,"children":425},{},[426,431],{"type":44,"tag":361,"props":427,"children":428},{},[429],{"type":50,"value":430},"Auth middleware \u002F handlers",{"type":44,"tag":361,"props":432,"children":433},{},[434],{"type":50,"value":435},"Authentication strategies, token validation, session management",{"type":44,"tag":339,"props":437,"children":438},{},[439,444],{"type":44,"tag":361,"props":440,"children":441},{},[442],{"type":50,"value":443},"Secrets \u002F environment variables",{"type":44,"tag":361,"props":445,"children":446},{},[447],{"type":50,"value":448},"All referenced env vars and secrets, noting which are sensitive",{"type":44,"tag":339,"props":450,"children":451},{},[452,457],{"type":44,"tag":361,"props":453,"children":454},{},[455],{"type":50,"value":456},"Existing tests",{"type":44,"tag":361,"props":458,"children":459},{},[460],{"type":50,"value":461},"Test files, which entities they cover, test framework used",{"type":44,"tag":339,"props":463,"children":464},{},[465,470],{"type":44,"tag":361,"props":466,"children":467},{},[468],{"type":50,"value":469},"Frontend code",{"type":44,"tag":361,"props":471,"children":472},{},[473],{"type":50,"value":474},"React\u002FVue\u002FAngular components, static HTML, CSS, client-side JS — these are out of scope",{"type":44,"tag":218,"props":476,"children":478},{"id":477},"_3-identify-frontend-code",[479],{"type":50,"value":480},"3. Identify Frontend Code",{"type":44,"tag":53,"props":482,"children":483},{},[484],{"type":50,"value":485},"Full-stack repos and monorepos often mix backend and frontend code. The migration targets backend only — frontend code is out of scope.",{"type":44,"tag":53,"props":487,"children":488},{},[489,494],{"type":44,"tag":96,"props":490,"children":491},{},[492],{"type":50,"value":493},"Detect frontend directories and mark them as out of scope.",{"type":50,"value":495}," Common indicators:",{"type":44,"tag":331,"props":497,"children":498},{},[499,515],{"type":44,"tag":335,"props":500,"children":501},{},[502],{"type":44,"tag":339,"props":503,"children":504},{},[505,510],{"type":44,"tag":343,"props":506,"children":507},{},[508],{"type":50,"value":509},"Pattern",{"type":44,"tag":343,"props":511,"children":512},{},[513],{"type":50,"value":514},"Examples",{"type":44,"tag":354,"props":516,"children":517},{},[518,571,623],{"type":44,"tag":339,"props":519,"children":520},{},[521,526],{"type":44,"tag":361,"props":522,"children":523},{},[524],{"type":50,"value":525},"Dedicated frontend directories",{"type":44,"tag":361,"props":527,"children":528},{},[529,535,536,542,543,549,550,556,558,564,565],{"type":44,"tag":59,"props":530,"children":532},{"className":531},[],[533],{"type":50,"value":534},"frontend\u002F",{"type":50,"value":195},{"type":44,"tag":59,"props":537,"children":539},{"className":538},[],[540],{"type":50,"value":541},"client\u002F",{"type":50,"value":195},{"type":44,"tag":59,"props":544,"children":546},{"className":545},[],[547],{"type":50,"value":548},"web\u002F",{"type":50,"value":195},{"type":44,"tag":59,"props":551,"children":553},{"className":552},[],[554],{"type":50,"value":555},"app\u002F",{"type":50,"value":557}," (when it contains React\u002FVue\u002FAngular), ",{"type":44,"tag":59,"props":559,"children":561},{"className":560},[],[562],{"type":50,"value":563},"src\u002Fcomponents\u002F",{"type":50,"value":195},{"type":44,"tag":59,"props":566,"children":568},{"className":567},[],[569],{"type":50,"value":570},"public\u002F",{"type":44,"tag":339,"props":572,"children":573},{},[574,579],{"type":44,"tag":361,"props":575,"children":576},{},[577],{"type":50,"value":578},"Frontend config files",{"type":44,"tag":361,"props":580,"children":581},{},[582,588,589,595,596,602,603,609,610,616,617],{"type":44,"tag":59,"props":583,"children":585},{"className":584},[],[586],{"type":50,"value":587},"next.config.js",{"type":50,"value":195},{"type":44,"tag":59,"props":590,"children":592},{"className":591},[],[593],{"type":50,"value":594},"vite.config.ts",{"type":50,"value":195},{"type":44,"tag":59,"props":597,"children":599},{"className":598},[],[600],{"type":50,"value":601},"nuxt.config.ts",{"type":50,"value":195},{"type":44,"tag":59,"props":604,"children":606},{"className":605},[],[607],{"type":50,"value":608},"angular.json",{"type":50,"value":195},{"type":44,"tag":59,"props":611,"children":613},{"className":612},[],[614],{"type":50,"value":615},".svelte-kit\u002F",{"type":50,"value":195},{"type":44,"tag":59,"props":618,"children":620},{"className":619},[],[621],{"type":50,"value":622},"remix.config.js",{"type":44,"tag":339,"props":624,"children":625},{},[626,631],{"type":44,"tag":361,"props":627,"children":628},{},[629],{"type":50,"value":630},"Package dependencies",{"type":44,"tag":361,"props":632,"children":633},{},[634,640,641,647,648,654,655,661,663],{"type":44,"tag":59,"props":635,"children":637},{"className":636},[],[638],{"type":50,"value":639},"react",{"type":50,"value":195},{"type":44,"tag":59,"props":642,"children":644},{"className":643},[],[645],{"type":50,"value":646},"vue",{"type":50,"value":195},{"type":44,"tag":59,"props":649,"children":651},{"className":650},[],[652],{"type":50,"value":653},"@angular\u002Fcore",{"type":50,"value":195},{"type":44,"tag":59,"props":656,"children":658},{"className":657},[],[659],{"type":50,"value":660},"svelte",{"type":50,"value":662}," in ",{"type":44,"tag":59,"props":664,"children":666},{"className":665},[],[667],{"type":50,"value":668},"package.json",{"type":44,"tag":53,"props":670,"children":671},{},[672,685],{"type":44,"tag":96,"props":673,"children":674},{},[675,677,683],{"type":50,"value":676},"Flag framework server-side code that ",{"type":44,"tag":678,"props":679,"children":680},"em",{},[681],{"type":50,"value":682},"should",{"type":50,"value":684}," be migrated.",{"type":50,"value":686}," Some frontend frameworks embed backend logic that contains API endpoints, database queries, or server-side business logic:",{"type":44,"tag":331,"props":688,"children":689},{},[690,710],{"type":44,"tag":335,"props":691,"children":692},{},[693],{"type":44,"tag":339,"props":694,"children":695},{},[696,701,706],{"type":44,"tag":343,"props":697,"children":698},{},[699],{"type":50,"value":700},"Framework",{"type":44,"tag":343,"props":702,"children":703},{},[704],{"type":50,"value":705},"Server-side locations",{"type":44,"tag":343,"props":707,"children":708},{},[709],{"type":50,"value":352},{"type":44,"tag":354,"props":711,"children":712},{},[713,742,779,808,837],{"type":44,"tag":339,"props":714,"children":715},{},[716,721,737],{"type":44,"tag":361,"props":717,"children":718},{},[719],{"type":50,"value":720},"Next.js",{"type":44,"tag":361,"props":722,"children":723},{},[724,730,731],{"type":44,"tag":59,"props":725,"children":727},{"className":726},[],[728],{"type":50,"value":729},"pages\u002Fapi\u002F",{"type":50,"value":195},{"type":44,"tag":59,"props":732,"children":734},{"className":733},[],[735],{"type":50,"value":736},"app\u002F*\u002Froute.ts",{"type":44,"tag":361,"props":738,"children":739},{},[740],{"type":50,"value":741},"API route handlers — these are backend endpoints",{"type":44,"tag":339,"props":743,"children":744},{},[745,750,761],{"type":44,"tag":361,"props":746,"children":747},{},[748],{"type":50,"value":749},"Remix",{"type":44,"tag":361,"props":751,"children":752},{},[753,759],{"type":44,"tag":59,"props":754,"children":756},{"className":755},[],[757],{"type":50,"value":758},"app\u002Froutes\u002F*.tsx",{"type":50,"value":760}," (loader\u002Faction exports)",{"type":44,"tag":361,"props":762,"children":763},{},[764,770,771,777],{"type":44,"tag":59,"props":765,"children":767},{"className":766},[],[768],{"type":50,"value":769},"loader",{"type":50,"value":235},{"type":44,"tag":59,"props":772,"children":774},{"className":773},[],[775],{"type":50,"value":776},"action",{"type":50,"value":778}," functions contain server logic",{"type":44,"tag":339,"props":780,"children":781},{},[782,787,803],{"type":44,"tag":361,"props":783,"children":784},{},[785],{"type":50,"value":786},"Nuxt",{"type":44,"tag":361,"props":788,"children":789},{},[790,796,797],{"type":44,"tag":59,"props":791,"children":793},{"className":792},[],[794],{"type":50,"value":795},"server\u002Fapi\u002F",{"type":50,"value":195},{"type":44,"tag":59,"props":798,"children":800},{"className":799},[],[801],{"type":50,"value":802},"server\u002Froutes\u002F",{"type":44,"tag":361,"props":804,"children":805},{},[806],{"type":50,"value":807},"Server API routes",{"type":44,"tag":339,"props":809,"children":810},{},[811,816,832],{"type":44,"tag":361,"props":812,"children":813},{},[814],{"type":50,"value":815},"SvelteKit",{"type":44,"tag":361,"props":817,"children":818},{},[819,825,826],{"type":44,"tag":59,"props":820,"children":822},{"className":821},[],[823],{"type":50,"value":824},"src\u002Froutes\u002F+server.ts",{"type":50,"value":195},{"type":44,"tag":59,"props":827,"children":829},{"className":828},[],[830],{"type":50,"value":831},"+page.server.ts",{"type":44,"tag":361,"props":833,"children":834},{},[835],{"type":50,"value":836},"Server endpoints and load functions",{"type":44,"tag":339,"props":838,"children":839},{},[840,845,864],{"type":44,"tag":361,"props":841,"children":842},{},[843],{"type":50,"value":844},"Astro",{"type":44,"tag":361,"props":846,"children":847},{},[848,854,856,862],{"type":44,"tag":59,"props":849,"children":851},{"className":850},[],[852],{"type":50,"value":853},"src\u002Fpages\u002F*.ts",{"type":50,"value":855}," (non-",{"type":44,"tag":59,"props":857,"children":859},{"className":858},[],[860],{"type":50,"value":861},".astro",{"type":50,"value":863},")",{"type":44,"tag":361,"props":865,"children":866},{},[867],{"type":50,"value":378},{"type":44,"tag":53,"props":869,"children":870},{},[871,873,878],{"type":50,"value":872},"When framework server-side code is found, ",{"type":44,"tag":96,"props":874,"children":875},{},[876],{"type":50,"value":877},"ask the user what to do with it.",{"type":50,"value":879}," Not all server-side code should move to Encore — sometimes a thin backend layer (BFF, auth proxy, SSR data fetching) should stay in the frontend framework alongside an Encore backend.",{"type":44,"tag":53,"props":881,"children":882},{},[883],{"type":50,"value":884},"Present the user with what was found and ask:",{"type":44,"tag":886,"props":887,"children":888},"blockquote",{},[889,928],{"type":44,"tag":53,"props":890,"children":891},{},[892,894],{"type":50,"value":893},"\"I found ",{"type":44,"tag":895,"props":896,"children":897},"n",{},[898,900],{"type":50,"value":899}," server-side routes in your ",{"type":44,"tag":901,"props":902,"children":903},"framework",{},[904,906,912,913,919,921,926],{"type":50,"value":905}," app (e.g., ",{"type":44,"tag":59,"props":907,"children":909},{"className":908},[],[910],{"type":50,"value":911},"pages\u002Fapi\u002Fusers.ts",{"type":50,"value":195},{"type":44,"tag":59,"props":914,"children":916},{"className":915},[],[917],{"type":50,"value":918},"app\u002Fbilling\u002Froute.ts",{"type":50,"value":920},"). These contain backend logic that ",{"type":44,"tag":678,"props":922,"children":923},{},[924],{"type":50,"value":925},"could",{"type":50,"value":927}," be migrated to Encore, but some teams prefer to keep a thin server layer in their frontend framework for things like SSR data fetching or BFF proxying. Would you like to:",{"type":44,"tag":244,"props":929,"children":930},{},[931,941,951],{"type":44,"tag":92,"props":932,"children":933},{},[934,939],{"type":44,"tag":96,"props":935,"children":936},{},[937],{"type":50,"value":938},"Migrate all",{"type":50,"value":940}," server-side routes to Encore",{"type":44,"tag":92,"props":942,"children":943},{},[944,949],{"type":44,"tag":96,"props":945,"children":946},{},[947],{"type":50,"value":948},"Migrate some",{"type":50,"value":950}," — I'll list them and you pick which ones move",{"type":44,"tag":92,"props":952,"children":953},{},[954,962],{"type":44,"tag":96,"props":955,"children":956},{},[957,959],{"type":50,"value":958},"Keep all in ",{"type":44,"tag":901,"props":960,"children":961},{},[],{"type":50,"value":963}," — only migrate the standalone backend code\"",{"type":44,"tag":53,"props":965,"children":966},{},[967],{"type":50,"value":968},"Based on the user's choice:",{"type":44,"tag":88,"props":970,"children":971},{},[972,982,992],{"type":44,"tag":92,"props":973,"children":974},{},[975,980],{"type":44,"tag":96,"props":976,"children":977},{},[978],{"type":50,"value":979},"Migrate all:",{"type":50,"value":981}," Extract the backend logic into migration units. Leave frontend rendering code out of scope. Note in the migration plan which source files contain mixed frontend\u002Fbackend code.",{"type":44,"tag":92,"props":983,"children":984},{},[985,990],{"type":44,"tag":96,"props":986,"children":987},{},[988],{"type":50,"value":989},"Migrate some:",{"type":50,"value":991}," Present the list of server-side routes and let the user select. Include selected routes in migration units, mark the rest as out of scope.",{"type":44,"tag":92,"props":993,"children":994},{},[995,1000],{"type":44,"tag":96,"props":996,"children":997},{},[998],{"type":50,"value":999},"Keep all:",{"type":50,"value":1001}," Mark all framework server-side code as out of scope alongside the frontend. Only standalone backend code (Express routes, standalone API servers, etc.) enters migration units.",{"type":44,"tag":53,"props":1003,"children":1004},{},[1005,1010,1012,1017,1019,1024],{"type":44,"tag":96,"props":1006,"children":1007},{},[1008],{"type":50,"value":1009},"Report to the user:",{"type":50,"value":1011}," List all detected frontend directories and the decision made about framework server-side code. Example: \"I found a Next.js frontend in ",{"type":44,"tag":59,"props":1013,"children":1015},{"className":1014},[],[1016],{"type":50,"value":555},{"type":50,"value":1018}," — the React components are out of scope. You chose to migrate 8 of the 12 API routes from ",{"type":44,"tag":59,"props":1020,"children":1022},{"className":1021},[],[1023],{"type":50,"value":729},{"type":50,"value":1025}," to Encore and keep 4 thin proxy routes in Next.js.\"",{"type":44,"tag":218,"props":1027,"children":1029},{"id":1028},"_4-group-entities-into-migration-units",[1030],{"type":50,"value":1031},"4. Group Entities into Migration Units",{"type":44,"tag":53,"props":1033,"children":1034},{},[1035],{"type":50,"value":1036},"Group the discovered entities into migration units using these heuristics in priority order:",{"type":44,"tag":244,"props":1038,"children":1039},{},[1040,1050,1074,1084],{"type":44,"tag":92,"props":1041,"children":1042},{},[1043,1048],{"type":44,"tag":96,"props":1044,"children":1045},{},[1046],{"type":50,"value":1047},"Existing service boundaries",{"type":50,"value":1049}," — If the source app already has services, modules, or packages, use those as the starting point for chunks",{"type":44,"tag":92,"props":1051,"children":1052},{},[1053,1058,1060,1066,1067,1073],{"type":44,"tag":96,"props":1054,"children":1055},{},[1056],{"type":50,"value":1057},"URL path prefixes",{"type":50,"value":1059}," — Group endpoints sharing a path prefix (e.g., ",{"type":44,"tag":59,"props":1061,"children":1063},{"className":1062},[],[1064],{"type":50,"value":1065},"\u002Fusers\u002F*",{"type":50,"value":195},{"type":44,"tag":59,"props":1068,"children":1070},{"className":1069},[],[1071],{"type":50,"value":1072},"\u002Fbilling\u002F*",{"type":50,"value":863},{"type":44,"tag":92,"props":1075,"children":1076},{},[1077,1082],{"type":44,"tag":96,"props":1078,"children":1079},{},[1080],{"type":50,"value":1081},"Shared database tables",{"type":50,"value":1083}," — Endpoints that read\u002Fwrite the same tables belong together",{"type":44,"tag":92,"props":1085,"children":1086},{},[1087,1092],{"type":44,"tag":96,"props":1088,"children":1089},{},[1090],{"type":50,"value":1091},"Shared types\u002Fmodels",{"type":50,"value":1093}," — Endpoints that share request\u002Fresponse types or domain models",{"type":44,"tag":53,"props":1095,"children":1096},{},[1097,1102,1104,1110,1111,1117],{"type":44,"tag":96,"props":1098,"children":1099},{},[1100],{"type":50,"value":1101},"Chunk sizing:",{"type":50,"value":1103}," Aim for 5-15 endpoints per migration unit. If a group exceeds ~15 endpoints, suggest splitting it further (e.g., ",{"type":44,"tag":59,"props":1105,"children":1107},{"className":1106},[],[1108],{"type":50,"value":1109},"users-crud",{"type":50,"value":235},{"type":44,"tag":59,"props":1112,"children":1114},{"className":1113},[],[1115],{"type":50,"value":1116},"users-admin",{"type":50,"value":1118},"). If a group has fewer than 3 endpoints, consider merging it with a related chunk.",{"type":44,"tag":53,"props":1120,"children":1121},{},[1122,1127],{"type":44,"tag":96,"props":1123,"children":1124},{},[1125],{"type":50,"value":1126},"Cross-cutting concerns",{"type":50,"value":1128}," get their own migration units: auth, secrets, and standalone infrastructure (pub\u002Fsub topics, cron jobs not tightly coupled to one service) are separate units since they follow different dependency tiers.",{"type":44,"tag":53,"props":1130,"children":1131},{},[1132,1137],{"type":44,"tag":96,"props":1133,"children":1134},{},[1135],{"type":50,"value":1136},"For monoliths with no clear boundaries:",{"type":50,"value":1138}," Fall back to URL path prefix grouping, then ask: \"These groupings are based on URL paths — would you like to reorganize them by domain?\"",{"type":44,"tag":218,"props":1140,"children":1142},{"id":1141},"_5-present-the-migration-units",[1143],{"type":50,"value":1144},"5. Present the Migration Units",{"type":44,"tag":53,"props":1146,"children":1147},{},[1148],{"type":50,"value":1149},"Present the migration units to the user as a summary table:",{"type":44,"tag":331,"props":1151,"children":1152},{},[1153],{"type":44,"tag":335,"props":1154,"children":1155},{},[1156],{"type":44,"tag":339,"props":1157,"children":1158},{},[1159,1164,1169,1174,1179],{"type":44,"tag":343,"props":1160,"children":1161},{},[1162],{"type":50,"value":1163},"Unit",{"type":44,"tag":343,"props":1165,"children":1166},{},[1167],{"type":50,"value":1168},"Endpoints",{"type":44,"tag":343,"props":1170,"children":1171},{},[1172],{"type":50,"value":1173},"DB Tables",{"type":44,"tag":343,"props":1175,"children":1176},{},[1177],{"type":50,"value":1178},"Other",{"type":44,"tag":343,"props":1180,"children":1181},{},[1182],{"type":50,"value":1183},"Complexity",{"type":44,"tag":53,"props":1185,"children":1186},{},[1187],{"type":50,"value":1188},"Include total counts (e.g., \"7 migration units covering 42 endpoints, 3 databases\"). For each unit, assess overall migration complexity:",{"type":44,"tag":88,"props":1190,"children":1191},{},[1192,1202,1212],{"type":44,"tag":92,"props":1193,"children":1194},{},[1195,1200],{"type":44,"tag":96,"props":1196,"children":1197},{},[1198],{"type":50,"value":1199},"Low",{"type":50,"value":1201}," — direct Encore equivalents exist, straightforward mapping",{"type":44,"tag":92,"props":1203,"children":1204},{},[1205,1210],{"type":44,"tag":96,"props":1206,"children":1207},{},[1208],{"type":50,"value":1209},"Medium",{"type":50,"value":1211}," — requires restructuring or has partial Encore equivalents",{"type":44,"tag":92,"props":1213,"children":1214},{},[1215,1220],{"type":44,"tag":96,"props":1216,"children":1217},{},[1218],{"type":50,"value":1219},"High",{"type":50,"value":1221}," — no direct equivalent, needs redesign or custom solution",{"type":44,"tag":53,"props":1223,"children":1224},{},[1225],{"type":50,"value":1226},"Offer to show the detail of any unit if the user wants to inspect what's inside before confirming.",{"type":44,"tag":218,"props":1228,"children":1230},{"id":1229},"_6-show-code-previews",[1231],{"type":50,"value":1232},"6. Show Code Previews",{"type":44,"tag":53,"props":1234,"children":1235},{},[1236],{"type":50,"value":1237},"For 2-3 representative entities (pick a mix of simple and complex from different units), show a short \"before and after\" preview of what the source code looks like now and what the Encore version will look like. Use the appropriate language-specific skill to inform the preview. Keep previews brief — one endpoint, one query, or one topic declaration is enough per preview.",{"type":44,"tag":218,"props":1239,"children":1241},{"id":1240},"_7-confirm-with-the-user",[1242],{"type":50,"value":1243},"7. Confirm with the User",{"type":44,"tag":53,"props":1245,"children":1246},{},[1247],{"type":50,"value":1248},"Ask the user to confirm the migration units are correct. Specifically ask:",{"type":44,"tag":88,"props":1250,"children":1251},{},[1252,1257,1262],{"type":44,"tag":92,"props":1253,"children":1254},{},[1255],{"type":50,"value":1256},"\"Are there any services, endpoints, or other entities I missed?\"",{"type":44,"tag":92,"props":1258,"children":1259},{},[1260],{"type":50,"value":1261},"\"Would you like to split, merge, or rename any of these migration units?\"",{"type":44,"tag":92,"props":1263,"children":1264},{},[1265],{"type":50,"value":1266},"\"Is there anything you want to exclude from the migration?\"",{"type":44,"tag":218,"props":1268,"children":1270},{"id":1269},"_8-iterate-if-needed",[1271],{"type":50,"value":1272},"8. Iterate if Needed",{"type":44,"tag":53,"props":1274,"children":1275},{},[1276],{"type":50,"value":1277},"If the user identifies missing entities or wants to adjust chunk boundaries, update the units and re-present the summary table. Repeat until the user confirms the migration units are accurate.",{"type":44,"tag":76,"props":1279,"children":1281},{"id":1280},"phase-2-plan",[1282],{"type":50,"value":1283},"Phase 2 — Plan",{"type":44,"tag":218,"props":1285,"children":1287},{"id":1286},"_1-check-for-existing-encore-project",[1288],{"type":50,"value":1289},"1. Check for Existing Encore Project",{"type":44,"tag":53,"props":1291,"children":1292},{},[1293,1295,1301,1303,1309,1311,1317],{"type":50,"value":1294},"Check if an Encore project already exists at the target path (look for ",{"type":44,"tag":59,"props":1296,"children":1298},{"className":1297},[],[1299],{"type":50,"value":1300},"encore.app",{"type":50,"value":1302}," file). If yes, confirm with the user that this is the correct project. If no, help create one by invoking the ",{"type":44,"tag":59,"props":1304,"children":1306},{"className":1305},[],[1307],{"type":50,"value":1308},"encore-getting-started",{"type":50,"value":1310}," skill (or ",{"type":44,"tag":59,"props":1312,"children":1314},{"className":1313},[],[1315],{"type":50,"value":1316},"encore-go-getting-started",{"type":50,"value":1318}," for Go).",{"type":44,"tag":218,"props":1320,"children":1322},{"id":1321},"_2-gather-target-information",[1323],{"type":50,"value":1324},"2. Gather Target Information",{"type":44,"tag":53,"props":1326,"children":1327},{},[1328],{"type":50,"value":285},{"type":44,"tag":88,"props":1330,"children":1331},{},[1332,1342],{"type":44,"tag":92,"props":1333,"children":1334},{},[1335,1340],{"type":44,"tag":96,"props":1336,"children":1337},{},[1338],{"type":50,"value":1339},"Path to the Encore project",{"type":50,"value":1341}," (where the migrated code will live)",{"type":44,"tag":92,"props":1343,"children":1344},{},[1345,1350,1352,1358],{"type":44,"tag":96,"props":1346,"children":1347},{},[1348],{"type":50,"value":1349},"Local URL where the Encore app will run",{"type":50,"value":1351}," (default: ",{"type":44,"tag":59,"props":1353,"children":1355},{"className":1354},[],[1356],{"type":50,"value":1357},"http:\u002F\u002Flocalhost:4000",{"type":50,"value":863},{"type":44,"tag":218,"props":1360,"children":1362},{"id":1361},"_3-determine-dependency-order",[1363],{"type":50,"value":1364},"3. Determine Dependency Order",{"type":44,"tag":53,"props":1366,"children":1367},{},[1368],{"type":50,"value":1369},"Order migration units based on dependencies. Follow this tier order:",{"type":44,"tag":244,"props":1371,"children":1372},{},[1373,1383,1392,1402,1412,1422,1431],{"type":44,"tag":92,"props":1374,"children":1375},{},[1376,1381],{"type":44,"tag":96,"props":1377,"children":1378},{},[1379],{"type":50,"value":1380},"Secrets \u002F config",{"type":50,"value":1382}," — no dependencies, needed by everything",{"type":44,"tag":92,"props":1384,"children":1385},{},[1386,1390],{"type":44,"tag":96,"props":1387,"children":1388},{},[1389],{"type":50,"value":391},{"type":50,"value":1391}," — schema and migrations must exist before services can use them",{"type":44,"tag":92,"props":1393,"children":1394},{},[1395,1400],{"type":44,"tag":96,"props":1396,"children":1397},{},[1398],{"type":50,"value":1399},"Auth",{"type":50,"value":1401}," — auth handlers are needed before protected endpoints",{"type":44,"tag":92,"props":1403,"children":1404},{},[1405,1410],{"type":44,"tag":96,"props":1406,"children":1407},{},[1408],{"type":50,"value":1409},"Leaf units",{"type":50,"value":1411}," — units with no cross-service dependencies",{"type":44,"tag":92,"props":1413,"children":1414},{},[1415,1420],{"type":44,"tag":96,"props":1416,"children":1417},{},[1418],{"type":50,"value":1419},"Dependent units",{"type":50,"value":1421}," — units that depend on already-migrated units",{"type":44,"tag":92,"props":1423,"children":1424},{},[1425,1429],{"type":44,"tag":96,"props":1426,"children":1427},{},[1428],{"type":50,"value":404},{"type":50,"value":1430}," — often depend on services being in place",{"type":44,"tag":92,"props":1432,"children":1433},{},[1434,1439],{"type":44,"tag":96,"props":1435,"children":1436},{},[1437],{"type":50,"value":1438},"Cron jobs",{"type":50,"value":1440}," — typically depend on service endpoints",{"type":44,"tag":53,"props":1442,"children":1443},{},[1444],{"type":50,"value":1445},"Within each tier, suggest the simplest unit first (fewest endpoints, smallest schema, least complexity).",{"type":44,"tag":218,"props":1447,"children":1449},{"id":1448},"_4-write-migration-planmd-summary",[1450],{"type":50,"value":1451},"4. Write migration-plan.md (Summary)",{"type":44,"tag":53,"props":1453,"children":1454},{},[1455,1457,1462,1464,1469],{"type":50,"value":1456},"Write the ",{"type":44,"tag":59,"props":1458,"children":1460},{"className":1459},[],[1461],{"type":50,"value":64},{"type":50,"value":1463}," summary file to the Encore project root using the template in the \"migration-plan.md Format\" section below. Fill in all migration units with status ",{"type":44,"tag":59,"props":1465,"children":1467},{"className":1466},[],[1468],{"type":50,"value":164},{"type":50,"value":1470},".",{"type":44,"tag":218,"props":1472,"children":1474},{"id":1473},"_5-write-detail-files",[1475],{"type":50,"value":1476},"5. Write Detail Files",{"type":44,"tag":53,"props":1478,"children":1479},{},[1480,1482,1487,1489,1495],{"type":50,"value":1481},"Create a ",{"type":44,"tag":59,"props":1483,"children":1485},{"className":1484},[],[1486],{"type":50,"value":72},{"type":50,"value":1488}," directory at the Encore project root. Write one detail file per migration unit using the template in the \"Detail File Format\" section below. Each file is named ",{"type":44,"tag":59,"props":1490,"children":1492},{"className":1491},[],[1493],{"type":50,"value":1494},"migration-plan\u002F\u003Cunit-name>.md",{"type":50,"value":1470},{"type":44,"tag":218,"props":1497,"children":1499},{"id":1498},"_6-propose-first-unit",[1500],{"type":50,"value":1501},"6. Propose First Unit",{"type":44,"tag":53,"props":1503,"children":1504},{},[1505],{"type":50,"value":1506},"Propose the first migration unit, explaining why it should go first based on the dependency order. Wait for user approval before proceeding to Phase 3.",{"type":44,"tag":76,"props":1508,"children":1510},{"id":1509},"phase-3-migrate-loop",[1511],{"type":50,"value":1512},"Phase 3 — Migrate (Loop)",{"type":44,"tag":218,"props":1514,"children":1516},{"id":1515},"_1-identify-next-unit",[1517],{"type":50,"value":1518},"1. Identify Next Unit",{"type":44,"tag":53,"props":1520,"children":1521},{},[1522,1523,1528],{"type":50,"value":251},{"type":44,"tag":59,"props":1524,"children":1526},{"className":1525},[],[1527],{"type":50,"value":64},{"type":50,"value":1529}," (summary only) and identify the next pending migration unit based on the dependency order.",{"type":44,"tag":218,"props":1531,"children":1533},{"id":1532},"_2-suggest-and-confirm",[1534],{"type":50,"value":1535},"2. Suggest and Confirm",{"type":44,"tag":53,"props":1537,"children":1538},{},[1539],{"type":50,"value":1540},"Suggest the next unit to migrate and explain why this one is next (e.g., \"This unit has no dependencies on unmigrated units\" or \"The database must exist before we can migrate the service that uses it\"). Ask the user if they want to proceed with this unit or pick a different one.",{"type":44,"tag":218,"props":1542,"children":1544},{"id":1543},"_3-load-the-unit-detail",[1545],{"type":50,"value":1546},"3. Load the Unit Detail",{"type":44,"tag":53,"props":1548,"children":1549},{},[1550,1552,1557],{"type":50,"value":1551},"Read the detail file for the chosen unit (",{"type":44,"tag":59,"props":1553,"children":1555},{"className":1554},[],[1556],{"type":50,"value":1494},{"type":50,"value":1558},"). Do NOT read detail files for other units.",{"type":44,"tag":218,"props":1560,"children":1562},{"id":1561},"_4-migrate-each-entity",[1563],{"type":50,"value":1564},"4. Migrate Each Entity",{"type":44,"tag":53,"props":1566,"children":1567},{},[1568],{"type":50,"value":1569},"For each entity in the unit:",{"type":44,"tag":1571,"props":1572,"children":1574},"h4",{"id":1573},"a-implement",[1575],{"type":50,"value":1576},"a. Implement",{"type":44,"tag":53,"props":1578,"children":1579},{},[1580],{"type":50,"value":1581},"Invoke the appropriate language-specific skill based on the entity type and target language:",{"type":44,"tag":331,"props":1583,"children":1584},{},[1585,1606],{"type":44,"tag":335,"props":1586,"children":1587},{},[1588],{"type":44,"tag":339,"props":1589,"children":1590},{},[1591,1596,1601],{"type":44,"tag":343,"props":1592,"children":1593},{},[1594],{"type":50,"value":1595},"Migrating...",{"type":44,"tag":343,"props":1597,"children":1598},{},[1599],{"type":50,"value":1600},"Encore.ts skill",{"type":44,"tag":343,"props":1602,"children":1603},{},[1604],{"type":50,"value":1605},"Encore Go skill",{"type":44,"tag":354,"props":1607,"children":1608},{},[1609,1635,1660,1685,1711,1737,1762,1788,1814,1840,1866],{"type":44,"tag":339,"props":1610,"children":1611},{},[1612,1617,1626],{"type":44,"tag":361,"props":1613,"children":1614},{},[1615],{"type":50,"value":1616},"Service structure",{"type":44,"tag":361,"props":1618,"children":1619},{},[1620],{"type":44,"tag":59,"props":1621,"children":1623},{"className":1622},[],[1624],{"type":50,"value":1625},"encore-service",{"type":44,"tag":361,"props":1627,"children":1628},{},[1629],{"type":44,"tag":59,"props":1630,"children":1632},{"className":1631},[],[1633],{"type":50,"value":1634},"encore-go-service",{"type":44,"tag":339,"props":1636,"children":1637},{},[1638,1642,1651],{"type":44,"tag":361,"props":1639,"children":1640},{},[1641],{"type":50,"value":378},{"type":44,"tag":361,"props":1643,"children":1644},{},[1645],{"type":44,"tag":59,"props":1646,"children":1648},{"className":1647},[],[1649],{"type":50,"value":1650},"encore-api",{"type":44,"tag":361,"props":1652,"children":1653},{},[1654],{"type":44,"tag":59,"props":1655,"children":1657},{"className":1656},[],[1658],{"type":50,"value":1659},"encore-go-api",{"type":44,"tag":339,"props":1661,"children":1662},{},[1663,1667,1676],{"type":44,"tag":361,"props":1664,"children":1665},{},[1666],{"type":50,"value":1399},{"type":44,"tag":361,"props":1668,"children":1669},{},[1670],{"type":44,"tag":59,"props":1671,"children":1673},{"className":1672},[],[1674],{"type":50,"value":1675},"encore-auth",{"type":44,"tag":361,"props":1677,"children":1678},{},[1679],{"type":44,"tag":59,"props":1680,"children":1682},{"className":1681},[],[1683],{"type":50,"value":1684},"encore-go-auth",{"type":44,"tag":339,"props":1686,"children":1687},{},[1688,1693,1702],{"type":44,"tag":361,"props":1689,"children":1690},{},[1691],{"type":50,"value":1692},"Database + migrations",{"type":44,"tag":361,"props":1694,"children":1695},{},[1696],{"type":44,"tag":59,"props":1697,"children":1699},{"className":1698},[],[1700],{"type":50,"value":1701},"encore-database",{"type":44,"tag":361,"props":1703,"children":1704},{},[1705],{"type":44,"tag":59,"props":1706,"children":1708},{"className":1707},[],[1709],{"type":50,"value":1710},"encore-go-database",{"type":44,"tag":339,"props":1712,"children":1713},{},[1714,1719,1728],{"type":44,"tag":361,"props":1715,"children":1716},{},[1717],{"type":50,"value":1718},"Pub\u002FSub topics & subscriptions",{"type":44,"tag":361,"props":1720,"children":1721},{},[1722],{"type":44,"tag":59,"props":1723,"children":1725},{"className":1724},[],[1726],{"type":50,"value":1727},"encore-pubsub",{"type":44,"tag":361,"props":1729,"children":1730},{},[1731],{"type":44,"tag":59,"props":1732,"children":1734},{"className":1733},[],[1735],{"type":50,"value":1736},"encore-go-pubsub",{"type":44,"tag":339,"props":1738,"children":1739},{},[1740,1744,1753],{"type":44,"tag":361,"props":1741,"children":1742},{},[1743],{"type":50,"value":417},{"type":44,"tag":361,"props":1745,"children":1746},{},[1747],{"type":44,"tag":59,"props":1748,"children":1750},{"className":1749},[],[1751],{"type":50,"value":1752},"encore-cron",{"type":44,"tag":361,"props":1754,"children":1755},{},[1756],{"type":44,"tag":59,"props":1757,"children":1759},{"className":1758},[],[1760],{"type":50,"value":1761},"encore-go-cron",{"type":44,"tag":339,"props":1763,"children":1764},{},[1765,1770,1779],{"type":44,"tag":361,"props":1766,"children":1767},{},[1768],{"type":50,"value":1769},"Object storage \u002F file uploads",{"type":44,"tag":361,"props":1771,"children":1772},{},[1773],{"type":44,"tag":59,"props":1774,"children":1776},{"className":1775},[],[1777],{"type":50,"value":1778},"encore-bucket",{"type":44,"tag":361,"props":1780,"children":1781},{},[1782],{"type":44,"tag":59,"props":1783,"children":1785},{"className":1784},[],[1786],{"type":50,"value":1787},"encore-go-bucket",{"type":44,"tag":339,"props":1789,"children":1790},{},[1791,1796,1805],{"type":44,"tag":361,"props":1792,"children":1793},{},[1794],{"type":50,"value":1795},"Caching (Redis)",{"type":44,"tag":361,"props":1797,"children":1798},{},[1799],{"type":44,"tag":59,"props":1800,"children":1802},{"className":1801},[],[1803],{"type":50,"value":1804},"encore-cache",{"type":44,"tag":361,"props":1806,"children":1807},{},[1808],{"type":44,"tag":59,"props":1809,"children":1811},{"className":1810},[],[1812],{"type":50,"value":1813},"encore-go-cache",{"type":44,"tag":339,"props":1815,"children":1816},{},[1817,1822,1831],{"type":44,"tag":361,"props":1818,"children":1819},{},[1820],{"type":50,"value":1821},"Secrets \u002F API keys \u002F credentials",{"type":44,"tag":361,"props":1823,"children":1824},{},[1825],{"type":44,"tag":59,"props":1826,"children":1828},{"className":1827},[],[1829],{"type":50,"value":1830},"encore-secret",{"type":44,"tag":361,"props":1832,"children":1833},{},[1834],{"type":44,"tag":59,"props":1835,"children":1837},{"className":1836},[],[1838],{"type":50,"value":1839},"encore-go-secret",{"type":44,"tag":339,"props":1841,"children":1842},{},[1843,1848,1857],{"type":44,"tag":361,"props":1844,"children":1845},{},[1846],{"type":50,"value":1847},"Webhooks (Stripe, GitHub, etc.)",{"type":44,"tag":361,"props":1849,"children":1850},{},[1851],{"type":44,"tag":59,"props":1852,"children":1854},{"className":1853},[],[1855],{"type":50,"value":1856},"encore-webhook",{"type":44,"tag":361,"props":1858,"children":1859},{},[1860],{"type":44,"tag":59,"props":1861,"children":1863},{"className":1862},[],[1864],{"type":50,"value":1865},"encore-go-webhook",{"type":44,"tag":339,"props":1867,"children":1868},{},[1869,1874,1883],{"type":44,"tag":361,"props":1870,"children":1871},{},[1872],{"type":50,"value":1873},"Tests",{"type":44,"tag":361,"props":1875,"children":1876},{},[1877],{"type":44,"tag":59,"props":1878,"children":1880},{"className":1879},[],[1881],{"type":50,"value":1882},"encore-testing",{"type":44,"tag":361,"props":1884,"children":1885},{},[1886],{"type":44,"tag":59,"props":1887,"children":1889},{"className":1888},[],[1890],{"type":50,"value":1891},"encore-go-testing",{"type":44,"tag":1571,"props":1893,"children":1895},{"id":1894},"b-migrate-tests",[1896],{"type":50,"value":1897},"b. Migrate Tests",{"type":44,"tag":53,"props":1899,"children":1900},{},[1901,1903,1908,1909,1914],{"type":50,"value":1902},"If the source entity has associated tests, migrate them using the appropriate testing skill (",{"type":44,"tag":59,"props":1904,"children":1906},{"className":1905},[],[1907],{"type":50,"value":1882},{"type":50,"value":166},{"type":44,"tag":59,"props":1910,"children":1912},{"className":1911},[],[1913],{"type":50,"value":1891},{"type":50,"value":1915},"). Adapt test assertions to match Encore API patterns. If the source entity has no tests, note this in the detail file.",{"type":44,"tag":1571,"props":1917,"children":1919},{"id":1918},"c-validate",[1920],{"type":50,"value":1921},"c. Validate",{"type":44,"tag":53,"props":1923,"children":1924},{},[1925,1927,1932],{"type":50,"value":1926},"Three validation layers are applied to each entity before it can be marked as ",{"type":44,"tag":59,"props":1928,"children":1930},{"className":1929},[],[1931],{"type":50,"value":193},{"type":50,"value":1933},". Every entity must go through all applicable layers.",{"type":44,"tag":1935,"props":1936,"children":1938},"h5",{"id":1937},"layer-1-test-migration-primary",[1939],{"type":50,"value":1940},"Layer 1: Test Migration (Primary)",{"type":44,"tag":88,"props":1942,"children":1943},{},[1944,1949,1967,1977],{"type":44,"tag":92,"props":1945,"children":1946},{},[1947],{"type":50,"value":1948},"When migrating an entity, also migrate its associated tests",{"type":44,"tag":92,"props":1950,"children":1951},{},[1952,1954,1959,1960,1965],{"type":50,"value":1953},"Use the ",{"type":44,"tag":59,"props":1955,"children":1957},{"className":1956},[],[1958],{"type":50,"value":1882},{"type":50,"value":1310},{"type":44,"tag":59,"props":1961,"children":1963},{"className":1962},[],[1964],{"type":50,"value":1891},{"type":50,"value":1966}," for Go) to implement the tests",{"type":44,"tag":92,"props":1968,"children":1969},{},[1970,1972],{"type":50,"value":1971},"Run the tests — they must pass before the entity can be marked as ",{"type":44,"tag":59,"props":1973,"children":1975},{"className":1974},[],[1976],{"type":50,"value":193},{"type":44,"tag":92,"props":1978,"children":1979},{},[1980],{"type":50,"value":1981},"If the source entity had no tests, note \"no source tests\" in the plan and rely on the other layers",{"type":44,"tag":1935,"props":1983,"children":1985},{"id":1984},"layer-2-http-comparison-endpoints-only-best-effort",[1986],{"type":50,"value":1987},"Layer 2: HTTP Comparison (Endpoints Only, Best-Effort)",{"type":44,"tag":53,"props":1989,"children":1990},{},[1991],{"type":50,"value":1992},"When both systems are running locally, call the same endpoint on both the source system and the Encore app, then compare:",{"type":44,"tag":88,"props":1994,"children":1995},{},[1996,2006],{"type":44,"tag":92,"props":1997,"children":1998},{},[1999,2004],{"type":44,"tag":96,"props":2000,"children":2001},{},[2002],{"type":50,"value":2003},"HTTP status code",{"type":50,"value":2005}," — must match",{"type":44,"tag":92,"props":2007,"children":2008},{},[2009,2014],{"type":44,"tag":96,"props":2010,"children":2011},{},[2012],{"type":50,"value":2013},"Response body structure",{"type":50,"value":2015}," — keys and shape must match (values may differ for dynamic data like timestamps or IDs)",{"type":44,"tag":53,"props":2017,"children":2018},{},[2019],{"type":44,"tag":96,"props":2020,"children":2021},{},[2022],{"type":50,"value":2023},"Skip this layer when:",{"type":44,"tag":88,"props":2025,"children":2026},{},[2027],{"type":44,"tag":92,"props":2028,"children":2029},{},[2030],{"type":50,"value":2031},"The endpoint requires auth credentials the agent cannot obtain (ask the user — allow skip)",{"type":44,"tag":53,"props":2033,"children":2034},{},[2035,2040],{"type":44,"tag":96,"props":2036,"children":2037},{},[2038],{"type":50,"value":2039},"If a request to either system fails to connect",{"type":50,"value":2041},", ask the user to start the app before retrying. Do not silently skip — the user may have simply forgotten to start it.",{"type":44,"tag":53,"props":2043,"children":2044},{},[2045],{"type":44,"tag":96,"props":2046,"children":2047},{},[2048],{"type":50,"value":2049},"Always ask the user before making any HTTP call that could have side effects.",{"type":44,"tag":1935,"props":2051,"children":2053},{"id":2052},"layer-3-verification-before-completion-gate",[2054],{"type":50,"value":2055},"Layer 3: Verification-Before-Completion Gate",{"type":44,"tag":53,"props":2057,"children":2058},{},[2059,2061,2066],{"type":50,"value":2060},"Before marking ANY entity as ",{"type":44,"tag":59,"props":2062,"children":2064},{"className":2063},[],[2065],{"type":50,"value":193},{"type":50,"value":2067},", the agent MUST have fresh evidence from the current session:",{"type":44,"tag":88,"props":2069,"children":2070},{},[2071,2076,2081],{"type":44,"tag":92,"props":2072,"children":2073},{},[2074],{"type":50,"value":2075},"Test command output showing pass count and exit code, OR",{"type":44,"tag":92,"props":2077,"children":2078},{},[2079],{"type":50,"value":2080},"HTTP comparison results showing a match, OR",{"type":44,"tag":92,"props":2082,"children":2083},{},[2084],{"type":50,"value":2085},"Explicit user approval to skip validation",{"type":44,"tag":53,"props":2087,"children":2088},{},[2089],{"type":44,"tag":96,"props":2090,"children":2091},{},[2092],{"type":50,"value":2093},"Rules:",{"type":44,"tag":88,"props":2095,"children":2096},{},[2097,2102,2107,2124],{"type":44,"tag":92,"props":2098,"children":2099},{},[2100],{"type":50,"value":2101},"No \"should work\", \"looks correct\", or \"seems fine\" — only evidence-backed claims",{"type":44,"tag":92,"props":2103,"children":2104},{},[2105],{"type":50,"value":2106},"The agent must state exactly what it verified and what the output was",{"type":44,"tag":92,"props":2108,"children":2109},{},[2110,2112,2117,2119],{"type":50,"value":2111},"If evidence is insufficient, mark the entity as ",{"type":44,"tag":59,"props":2113,"children":2115},{"className":2114},[],[2116],{"type":50,"value":209},{"type":50,"value":2118},", not ",{"type":44,"tag":59,"props":2120,"children":2122},{"className":2121},[],[2123],{"type":50,"value":193},{"type":44,"tag":92,"props":2125,"children":2126},{},[2127],{"type":50,"value":2128},"Stale evidence from a previous session does not count — re-run validation if resuming",{"type":44,"tag":1571,"props":2130,"children":2132},{"id":2131},"d-update-the-detail-file",[2133],{"type":50,"value":2134},"d. Update the Detail File",{"type":44,"tag":53,"props":2136,"children":2137},{},[2138,2140,2145],{"type":50,"value":2139},"Update the entity's status in the unit's detail file (",{"type":44,"tag":59,"props":2141,"children":2143},{"className":2142},[],[2144],{"type":50,"value":1494},{"type":50,"value":2146},") and record validation evidence in that file's Validation Log table.",{"type":44,"tag":1571,"props":2148,"children":2150},{"id":2149},"e-update-the-summary",[2151],{"type":50,"value":2152},"e. Update the Summary",{"type":44,"tag":53,"props":2154,"children":2155},{},[2156,2158,2163,2165,2170,2172,2177],{"type":50,"value":2157},"When all entities in a unit are complete, update the unit's status in ",{"type":44,"tag":59,"props":2159,"children":2161},{"className":2160},[],[2162],{"type":50,"value":64},{"type":50,"value":2164}," to ",{"type":44,"tag":59,"props":2166,"children":2168},{"className":2167},[],[2169],{"type":50,"value":193},{"type":50,"value":2171},". If some entities are pending, set the unit status to ",{"type":44,"tag":59,"props":2173,"children":2175},{"className":2174},[],[2176],{"type":50,"value":172},{"type":50,"value":1470},{"type":44,"tag":218,"props":2179,"children":2181},{"id":2180},"_5-continue-or-pause",[2182],{"type":50,"value":2183},"5. Continue or Pause",{"type":44,"tag":53,"props":2185,"children":2186},{},[2187],{"type":50,"value":2188},"After completing a unit, ask \"What would you like to migrate next?\" and suggest the next unit based on dependency order.",{"type":44,"tag":218,"props":2190,"children":2192},{"id":2191},"_6-batching",[2193],{"type":50,"value":2194},"6. Batching",{"type":44,"tag":53,"props":2196,"children":2197},{},[2198],{"type":50,"value":2199},"The default is one unit at a time. If the user says \"keep going\", \"do them all\", or similar, batch multiple units but still validate each entity individually before marking it as migrated.",{"type":44,"tag":76,"props":2201,"children":2203},{"id":2202},"phase-4-complete",[2204],{"type":50,"value":2205},"Phase 4 — Complete",{"type":44,"tag":53,"props":2207,"children":2208},{},[2209,2211,2216,2218,2223,2224,2229,2230,2235],{"type":50,"value":2210},"When all units in ",{"type":44,"tag":59,"props":2212,"children":2214},{"className":2213},[],[2215],{"type":50,"value":64},{"type":50,"value":2217}," are ",{"type":44,"tag":59,"props":2219,"children":2221},{"className":2220},[],[2222],{"type":50,"value":193},{"type":50,"value":195},{"type":44,"tag":59,"props":2225,"children":2227},{"className":2226},[],[2228],{"type":50,"value":201},{"type":50,"value":203},{"type":44,"tag":59,"props":2231,"children":2233},{"className":2232},[],[2234],{"type":50,"value":209},{"type":50,"value":2236},":",{"type":44,"tag":244,"props":2238,"children":2239},{},[2240,2282,2292,2302,2320],{"type":44,"tag":92,"props":2241,"children":2242},{},[2243,2248,2250,2255,2257],{"type":44,"tag":96,"props":2244,"children":2245},{},[2246],{"type":50,"value":2247},"Present a final summary",{"type":50,"value":2249}," from ",{"type":44,"tag":59,"props":2251,"children":2253},{"className":2252},[],[2254],{"type":50,"value":64},{"type":50,"value":2256},":\n",{"type":44,"tag":88,"props":2258,"children":2259},{},[2260,2265,2277],{"type":44,"tag":92,"props":2261,"children":2262},{},[2263],{"type":50,"value":2264},"Total units migrated",{"type":44,"tag":92,"props":2266,"children":2267},{},[2268,2270,2275],{"type":50,"value":2269},"Units marked as ",{"type":44,"tag":59,"props":2271,"children":2273},{"className":2272},[],[2274],{"type":50,"value":209},{"type":50,"value":2276}," — read those specific detail files and list the entities that need attention with reasons",{"type":44,"tag":92,"props":2278,"children":2279},{},[2280],{"type":50,"value":2281},"Units skipped (list them with reasons)",{"type":44,"tag":92,"props":2283,"children":2284},{},[2285,2290],{"type":44,"tag":96,"props":2286,"children":2287},{},[2288],{"type":50,"value":2289},"Suggest running the full test suite",{"type":50,"value":2291}," one final time to catch any integration issues",{"type":44,"tag":92,"props":2293,"children":2294},{},[2295,2300],{"type":44,"tag":96,"props":2296,"children":2297},{},[2298],{"type":50,"value":2299},"Note any manual validation items",{"type":50,"value":2301}," that still need human attention",{"type":44,"tag":92,"props":2303,"children":2304},{},[2305,2310,2312,2318],{"type":44,"tag":96,"props":2306,"children":2307},{},[2308],{"type":50,"value":2309},"If the source system had frontend code",{"type":50,"value":2311},", suggest using the ",{"type":44,"tag":59,"props":2313,"children":2315},{"className":2314},[],[2316],{"type":50,"value":2317},"encore-frontend",{"type":50,"value":2319}," skill to reconnect the frontend to the new Encore backend (generate a typed API client, configure CORS, update base URLs)",{"type":44,"tag":92,"props":2321,"children":2322},{},[2323,2339],{"type":44,"tag":96,"props":2324,"children":2325},{},[2326,2328,2333,2334],{"type":50,"value":2327},"Suggest removing ",{"type":44,"tag":59,"props":2329,"children":2331},{"className":2330},[],[2332],{"type":50,"value":64},{"type":50,"value":235},{"type":44,"tag":59,"props":2335,"children":2337},{"className":2336},[],[2338],{"type":50,"value":72},{"type":50,"value":2340}," from the project once the user is satisfied with the migration",{"type":44,"tag":76,"props":2342,"children":2344},{"id":2343},"asking-questions",[2345],{"type":50,"value":2346},"Asking Questions",{"type":44,"tag":53,"props":2348,"children":2349},{},[2350],{"type":50,"value":2351},"Ask the user before acting when:",{"type":44,"tag":88,"props":2353,"children":2354},{},[2355,2365,2375,2385,2395,2405],{"type":44,"tag":92,"props":2356,"children":2357},{},[2358,2363],{"type":44,"tag":96,"props":2359,"children":2360},{},[2361],{"type":50,"value":2362},"Service boundaries are unclear",{"type":50,"value":2364}," — e.g., \"These route files could be 1 service or 3 — how would you like to split them?\"",{"type":44,"tag":92,"props":2366,"children":2367},{},[2368,2373],{"type":44,"tag":96,"props":2369,"children":2370},{},[2371],{"type":50,"value":2372},"No clean Encore equivalent exists",{"type":50,"value":2374}," — e.g., Redis caching layer, custom middleware chains, WebSocket handlers",{"type":44,"tag":92,"props":2376,"children":2377},{},[2378,2383],{"type":44,"tag":96,"props":2379,"children":2380},{},[2381],{"type":50,"value":2382},"Multiple valid migration strategies exist",{"type":50,"value":2384}," — present the options with tradeoffs",{"type":44,"tag":92,"props":2386,"children":2387},{},[2388,2393],{"type":44,"tag":96,"props":2389,"children":2390},{},[2391],{"type":50,"value":2392},"Before making any HTTP call that could have side effects",{"type":50,"value":2394}," — always ask first",{"type":44,"tag":92,"props":2396,"children":2397},{},[2398,2403],{"type":44,"tag":96,"props":2399,"children":2400},{},[2401],{"type":50,"value":2402},"Source code is ambiguous",{"type":50,"value":2404}," — when the agent is not confident about what the code does, ask rather than guess",{"type":44,"tag":92,"props":2406,"children":2407},{},[2408,2413],{"type":44,"tag":96,"props":2409,"children":2410},{},[2411],{"type":50,"value":2412},"Source system appears to have changed",{"type":50,"value":2414}," — if files referenced in a detail file no longer exist or have changed significantly",{"type":44,"tag":76,"props":2416,"children":2418},{"id":2417},"source-system-protection",[2419],{"type":50,"value":2420},"Source System Protection",{"type":44,"tag":53,"props":2422,"children":2423},{},[2424],{"type":50,"value":2425},"The source system must never be modified during migration. Follow these rules:",{"type":44,"tag":88,"props":2427,"children":2428},{},[2429,2439,2449,2459,2469],{"type":44,"tag":92,"props":2430,"children":2431},{},[2432,2437],{"type":44,"tag":96,"props":2433,"children":2434},{},[2435],{"type":50,"value":2436},"Never modify source files",{"type":50,"value":2438}," — read them, don't edit them",{"type":44,"tag":92,"props":2440,"children":2441},{},[2442,2447],{"type":44,"tag":96,"props":2443,"children":2444},{},[2445],{"type":50,"value":2446},"Never delete source files",{"type":50,"value":2448}," — even after migration is complete",{"type":44,"tag":92,"props":2450,"children":2451},{},[2452,2457],{"type":44,"tag":96,"props":2453,"children":2454},{},[2455],{"type":50,"value":2456},"Never write to the source directory",{"type":50,"value":2458}," — all output goes to the Encore project",{"type":44,"tag":92,"props":2460,"children":2461},{},[2462,2467],{"type":44,"tag":96,"props":2463,"children":2464},{},[2465],{"type":50,"value":2466},"Never run destructive commands against the source system",{"type":50,"value":2468}," (drop tables, delete queues, etc.)",{"type":44,"tag":92,"props":2470,"children":2471},{},[2472,2477],{"type":44,"tag":96,"props":2473,"children":2474},{},[2475],{"type":50,"value":2476},"Ask before any HTTP call that mutates state",{"type":50,"value":2478}," on the source system (POST, PUT, DELETE)",{"type":44,"tag":53,"props":2480,"children":2481},{},[2482],{"type":50,"value":2483},"If the user asks to \"clean up\" or \"remove\" the old system, confirm explicitly before taking any action. The source system may still be serving production traffic.",{"type":44,"tag":76,"props":2485,"children":2487},{"id":2486},"edge-cases",[2488],{"type":50,"value":2489},"Edge Cases",{"type":44,"tag":218,"props":2491,"children":2493},{"id":2492},"moving-endpoints-between-units",[2494],{"type":50,"value":2495},"Moving Endpoints Between Units",{"type":44,"tag":53,"props":2497,"children":2498},{},[2499],{"type":50,"value":2500},"If the user realizes an endpoint belongs in a different migration unit:",{"type":44,"tag":244,"props":2502,"children":2503},{},[2504,2509,2514],{"type":44,"tag":92,"props":2505,"children":2506},{},[2507],{"type":50,"value":2508},"Remove the endpoint row from the source unit's detail file",{"type":44,"tag":92,"props":2510,"children":2511},{},[2512],{"type":50,"value":2513},"Add it to the target unit's detail file",{"type":44,"tag":92,"props":2515,"children":2516},{},[2517,2519],{"type":50,"value":2518},"Update endpoint counts in ",{"type":44,"tag":59,"props":2520,"children":2522},{"className":2521},[],[2523],{"type":50,"value":64},{"type":44,"tag":218,"props":2525,"children":2527},{"id":2526},"splitting-a-unit-mid-migration",[2528],{"type":50,"value":2529},"Splitting a Unit Mid-Migration",{"type":44,"tag":53,"props":2531,"children":2532},{},[2533],{"type":50,"value":2534},"If a unit turns out to be too large while working on it:",{"type":44,"tag":244,"props":2536,"children":2537},{},[2538,2550,2555,2567],{"type":44,"tag":92,"props":2539,"children":2540},{},[2541,2543,2549],{"type":50,"value":2542},"Create a new detail file for the split-off portion (",{"type":44,"tag":59,"props":2544,"children":2546},{"className":2545},[],[2547],{"type":50,"value":2548},"migration-plan\u002F\u003Cnew-unit>.md",{"type":50,"value":863},{"type":44,"tag":92,"props":2551,"children":2552},{},[2553],{"type":50,"value":2554},"Move pending entities to the new file (already-migrated entities stay in the original)",{"type":44,"tag":92,"props":2556,"children":2557},{},[2558,2560,2565],{"type":50,"value":2559},"Add the new unit to the ",{"type":44,"tag":59,"props":2561,"children":2563},{"className":2562},[],[2564],{"type":50,"value":64},{"type":50,"value":2566}," summary table",{"type":44,"tag":92,"props":2568,"children":2569},{},[2570],{"type":50,"value":2571},"Insert it in the dependency order (same tier, after the original)",{"type":44,"tag":218,"props":2573,"children":2575},{"id":2574},"monolith-to-multiple-encore-services",[2576],{"type":50,"value":2577},"Monolith to Multiple Encore Services",{"type":44,"tag":53,"props":2579,"children":2580},{},[2581],{"type":50,"value":2582},"A single migration unit might map to multiple Encore services. The detail file tracks the source grouping, but the \"Notes\" column can indicate the target Encore service. Ask during migration if the unit maps to one service or should be split across Encore services.",{"type":44,"tag":218,"props":2584,"children":2586},{"id":2585},"source-code-changed-since-discovery",[2587],{"type":50,"value":2588},"Source Code Changed Since Discovery",{"type":44,"tag":53,"props":2590,"children":2591},{},[2592],{"type":50,"value":2593},"If files referenced in a detail file no longer exist or have changed significantly since discovery:",{"type":44,"tag":244,"props":2595,"children":2596},{},[2597,2602,2607],{"type":44,"tag":92,"props":2598,"children":2599},{},[2600],{"type":50,"value":2601},"Flag the discrepancy to the user",{"type":44,"tag":92,"props":2603,"children":2604},{},[2605],{"type":50,"value":2606},"Ask whether to update the detail file with the new state or skip the affected entities",{"type":44,"tag":92,"props":2608,"children":2609},{},[2610],{"type":50,"value":2611},"If updating, re-assess complexity and adjust the plan accordingly",{"type":44,"tag":76,"props":2613,"children":2615},{"id":2614},"troubleshooting",[2616],{"type":50,"value":2617},"Troubleshooting",{"type":44,"tag":53,"props":2619,"children":2620},{},[2621],{"type":50,"value":2622},"Common issues during migration and how to resolve them:",{"type":44,"tag":331,"props":2624,"children":2625},{},[2626,2647],{"type":44,"tag":335,"props":2627,"children":2628},{},[2629],{"type":44,"tag":339,"props":2630,"children":2631},{},[2632,2637,2642],{"type":44,"tag":343,"props":2633,"children":2634},{},[2635],{"type":50,"value":2636},"Problem",{"type":44,"tag":343,"props":2638,"children":2639},{},[2640],{"type":50,"value":2641},"Cause",{"type":44,"tag":343,"props":2643,"children":2644},{},[2645],{"type":50,"value":2646},"Resolution",{"type":44,"tag":354,"props":2648,"children":2649},{},[2650,2676,2694,2712,2730,2754,2772],{"type":44,"tag":339,"props":2651,"children":2652},{},[2653,2658,2663],{"type":44,"tag":361,"props":2654,"children":2655},{},[2656],{"type":50,"value":2657},"Import errors across services",{"type":44,"tag":361,"props":2659,"children":2660},{},[2661],{"type":50,"value":2662},"Direct imports between services",{"type":44,"tag":361,"props":2664,"children":2665},{},[2666,2668,2674],{"type":50,"value":2667},"Use ",{"type":44,"tag":59,"props":2669,"children":2671},{"className":2670},[],[2672],{"type":50,"value":2673},"~encore\u002Fclients",{"type":50,"value":2675}," (TS) or service client packages (Go) instead",{"type":44,"tag":339,"props":2677,"children":2678},{},[2679,2684,2689],{"type":44,"tag":361,"props":2680,"children":2681},{},[2682],{"type":50,"value":2683},"Database migration fails",{"type":44,"tag":361,"props":2685,"children":2686},{},[2687],{"type":50,"value":2688},"Incompatible SQL syntax",{"type":44,"tag":361,"props":2690,"children":2691},{},[2692],{"type":50,"value":2693},"Check Encore uses PostgreSQL — adapt MySQL\u002FSQLite syntax",{"type":44,"tag":339,"props":2695,"children":2696},{},[2697,2702,2707],{"type":44,"tag":361,"props":2698,"children":2699},{},[2700],{"type":50,"value":2701},"Pub\u002FSub messages not received",{"type":44,"tag":361,"props":2703,"children":2704},{},[2705],{"type":50,"value":2706},"Subscription not registered",{"type":44,"tag":361,"props":2708,"children":2709},{},[2710],{"type":50,"value":2711},"Ensure subscription is declared at package level, not inside a function",{"type":44,"tag":339,"props":2713,"children":2714},{},[2715,2720,2725],{"type":44,"tag":361,"props":2716,"children":2717},{},[2718],{"type":50,"value":2719},"Cron job not firing",{"type":44,"tag":361,"props":2721,"children":2722},{},[2723],{"type":50,"value":2724},"Invalid schedule expression",{"type":44,"tag":361,"props":2726,"children":2727},{},[2728],{"type":50,"value":2729},"Encore uses standard cron expressions — verify syntax",{"type":44,"tag":339,"props":2731,"children":2732},{},[2733,2744,2749],{"type":44,"tag":361,"props":2734,"children":2735},{},[2736,2742],{"type":44,"tag":59,"props":2737,"children":2739},{"className":2738},[],[2740],{"type":50,"value":2741},"encore run",{"type":50,"value":2743}," errors on infrastructure",{"type":44,"tag":361,"props":2745,"children":2746},{},[2747],{"type":50,"value":2748},"Infrastructure declared inside functions",{"type":44,"tag":361,"props":2750,"children":2751},{},[2752],{"type":50,"value":2753},"Move all infrastructure declarations to package level",{"type":44,"tag":339,"props":2755,"children":2756},{},[2757,2762,2767],{"type":44,"tag":361,"props":2758,"children":2759},{},[2760],{"type":50,"value":2761},"Source and Encore responses differ",{"type":44,"tag":361,"props":2763,"children":2764},{},[2765],{"type":50,"value":2766},"Missing business logic or different error handling",{"type":44,"tag":361,"props":2768,"children":2769},{},[2770],{"type":50,"value":2771},"Compare response shapes carefully, check edge cases",{"type":44,"tag":339,"props":2773,"children":2774},{},[2775,2780,2785],{"type":44,"tag":361,"props":2776,"children":2777},{},[2778],{"type":50,"value":2779},"Cannot validate endpoint",{"type":44,"tag":361,"props":2781,"children":2782},{},[2783],{"type":50,"value":2784},"Auth required or side effects",{"type":44,"tag":361,"props":2786,"children":2787},{},[2788,2790],{"type":50,"value":2789},"Ask user for test credentials, or mark as ",{"type":44,"tag":59,"props":2791,"children":2793},{"className":2792},[],[2794],{"type":50,"value":209},{"type":44,"tag":76,"props":2796,"children":2798},{"id":2797},"migration-planmd-format",[2799],{"type":50,"value":2800},"migration-plan.md Format",{"type":44,"tag":53,"props":2802,"children":2803},{},[2804],{"type":50,"value":2805},"Use this exact template for the summary plan file. Fill in values from the discovery phase.",{"type":44,"tag":2807,"props":2808,"children":2813},"pre",{"className":2809,"code":2810,"language":2811,"meta":2812,"style":2812},"language-markdown shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Migration Plan\n\n## Source System\n- **Path:** \u003Csource system path>\n- **URL:** \u003Csource system local URL>\n- **Framework:** \u003Cdetected framework>\n- **Language:** \u003Cdetected language>\n\n## Frontend (Out of Scope)\n- **Detected:** \u003CYes\u002FNo>\n- **Directories:** \u003Clist of frontend directories, or \"None\">\n- **Framework:** \u003Cfrontend framework if detected, or \"N\u002FA\">\n- **Note:** \u003Cany framework server-side code that WAS included in migration units>\n\n## Target System\n- **Path:** \u003Cencore project path>\n- **URL:** \u003Cencore local URL>\n- **Type:** Encore.ts | Encore Go\n\n## Migration Units\n\n| Unit | Endpoints | DB Tables | Other | Complexity | Status |\n|------|-----------|-----------|-------|------------|--------|\n\n## Dependency Order\n1. \u003Cordered list of migration units>\n","markdown","",[2814],{"type":44,"tag":59,"props":2815,"children":2816},{"__ignoreMap":2812},[2817,2835,2845,2859,2912,2958,2997,3035,3043,3056,3090,3145,3197,3275,3283,3296,3337,3377,3404,3412,3425,3433,3497,3506,3514,3527],{"type":44,"tag":2818,"props":2819,"children":2822},"span",{"class":2820,"line":2821},"line",1,[2823,2829],{"type":44,"tag":2818,"props":2824,"children":2826},{"style":2825},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[2827],{"type":50,"value":2828},"# ",{"type":44,"tag":2818,"props":2830,"children":2832},{"style":2831},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[2833],{"type":50,"value":2834},"Migration Plan\n",{"type":44,"tag":2818,"props":2836,"children":2838},{"class":2820,"line":2837},2,[2839],{"type":44,"tag":2818,"props":2840,"children":2842},{"emptyLinePlaceholder":2841},true,[2843],{"type":50,"value":2844},"\n",{"type":44,"tag":2818,"props":2846,"children":2848},{"class":2820,"line":2847},3,[2849,2854],{"type":44,"tag":2818,"props":2850,"children":2851},{"style":2825},[2852],{"type":50,"value":2853},"## ",{"type":44,"tag":2818,"props":2855,"children":2856},{"style":2831},[2857],{"type":50,"value":2858},"Source System\n",{"type":44,"tag":2818,"props":2860,"children":2862},{"class":2820,"line":2861},4,[2863,2868,2874,2880,2885,2890,2896,2902,2907],{"type":44,"tag":2818,"props":2864,"children":2865},{"style":2825},[2866],{"type":50,"value":2867},"-",{"type":44,"tag":2818,"props":2869,"children":2871},{"style":2870},"--shiki-light:#39ADB5;--shiki-light-font-weight:bold;--shiki-default:#89DDFF;--shiki-default-font-weight:bold;--shiki-dark:#89DDFF;--shiki-dark-font-weight:bold",[2872],{"type":50,"value":2873}," **",{"type":44,"tag":2818,"props":2875,"children":2877},{"style":2876},"--shiki-light:#E53935;--shiki-light-font-weight:bold;--shiki-default:#F07178;--shiki-default-font-weight:bold;--shiki-dark:#F07178;--shiki-dark-font-weight:bold",[2878],{"type":50,"value":2879},"Path:",{"type":44,"tag":2818,"props":2881,"children":2882},{"style":2870},[2883],{"type":50,"value":2884},"**",{"type":44,"tag":2818,"props":2886,"children":2887},{"style":2825},[2888],{"type":50,"value":2889}," \u003C",{"type":44,"tag":2818,"props":2891,"children":2893},{"style":2892},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[2894],{"type":50,"value":2895},"source",{"type":44,"tag":2818,"props":2897,"children":2899},{"style":2898},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[2900],{"type":50,"value":2901}," system",{"type":44,"tag":2818,"props":2903,"children":2904},{"style":2898},[2905],{"type":50,"value":2906}," path",{"type":44,"tag":2818,"props":2908,"children":2909},{"style":2825},[2910],{"type":50,"value":2911},">\n",{"type":44,"tag":2818,"props":2913,"children":2914},{"class":2820,"line":28},[2915,2919,2923,2928,2932,2936,2940,2944,2949,2954],{"type":44,"tag":2818,"props":2916,"children":2917},{"style":2825},[2918],{"type":50,"value":2867},{"type":44,"tag":2818,"props":2920,"children":2921},{"style":2870},[2922],{"type":50,"value":2873},{"type":44,"tag":2818,"props":2924,"children":2925},{"style":2876},[2926],{"type":50,"value":2927},"URL:",{"type":44,"tag":2818,"props":2929,"children":2930},{"style":2870},[2931],{"type":50,"value":2884},{"type":44,"tag":2818,"props":2933,"children":2934},{"style":2825},[2935],{"type":50,"value":2889},{"type":44,"tag":2818,"props":2937,"children":2938},{"style":2892},[2939],{"type":50,"value":2895},{"type":44,"tag":2818,"props":2941,"children":2942},{"style":2898},[2943],{"type":50,"value":2901},{"type":44,"tag":2818,"props":2945,"children":2946},{"style":2898},[2947],{"type":50,"value":2948}," local",{"type":44,"tag":2818,"props":2950,"children":2951},{"style":2898},[2952],{"type":50,"value":2953}," URL",{"type":44,"tag":2818,"props":2955,"children":2956},{"style":2825},[2957],{"type":50,"value":2911},{"type":44,"tag":2818,"props":2959,"children":2961},{"class":2820,"line":2960},6,[2962,2966,2970,2975,2979,2983,2988,2993],{"type":44,"tag":2818,"props":2963,"children":2964},{"style":2825},[2965],{"type":50,"value":2867},{"type":44,"tag":2818,"props":2967,"children":2968},{"style":2870},[2969],{"type":50,"value":2873},{"type":44,"tag":2818,"props":2971,"children":2972},{"style":2876},[2973],{"type":50,"value":2974},"Framework:",{"type":44,"tag":2818,"props":2976,"children":2977},{"style":2870},[2978],{"type":50,"value":2884},{"type":44,"tag":2818,"props":2980,"children":2981},{"style":2825},[2982],{"type":50,"value":2889},{"type":44,"tag":2818,"props":2984,"children":2985},{"style":2892},[2986],{"type":50,"value":2987},"detected",{"type":44,"tag":2818,"props":2989,"children":2990},{"style":2898},[2991],{"type":50,"value":2992}," framework",{"type":44,"tag":2818,"props":2994,"children":2995},{"style":2825},[2996],{"type":50,"value":2911},{"type":44,"tag":2818,"props":2998,"children":3000},{"class":2820,"line":2999},7,[3001,3005,3009,3014,3018,3022,3026,3031],{"type":44,"tag":2818,"props":3002,"children":3003},{"style":2825},[3004],{"type":50,"value":2867},{"type":44,"tag":2818,"props":3006,"children":3007},{"style":2870},[3008],{"type":50,"value":2873},{"type":44,"tag":2818,"props":3010,"children":3011},{"style":2876},[3012],{"type":50,"value":3013},"Language:",{"type":44,"tag":2818,"props":3015,"children":3016},{"style":2870},[3017],{"type":50,"value":2884},{"type":44,"tag":2818,"props":3019,"children":3020},{"style":2825},[3021],{"type":50,"value":2889},{"type":44,"tag":2818,"props":3023,"children":3024},{"style":2892},[3025],{"type":50,"value":2987},{"type":44,"tag":2818,"props":3027,"children":3028},{"style":2898},[3029],{"type":50,"value":3030}," language",{"type":44,"tag":2818,"props":3032,"children":3033},{"style":2825},[3034],{"type":50,"value":2911},{"type":44,"tag":2818,"props":3036,"children":3038},{"class":2820,"line":3037},8,[3039],{"type":44,"tag":2818,"props":3040,"children":3041},{"emptyLinePlaceholder":2841},[3042],{"type":50,"value":2844},{"type":44,"tag":2818,"props":3044,"children":3046},{"class":2820,"line":3045},9,[3047,3051],{"type":44,"tag":2818,"props":3048,"children":3049},{"style":2825},[3050],{"type":50,"value":2853},{"type":44,"tag":2818,"props":3052,"children":3053},{"style":2831},[3054],{"type":50,"value":3055},"Frontend (Out of Scope)\n",{"type":44,"tag":2818,"props":3057,"children":3059},{"class":2820,"line":3058},10,[3060,3064,3068,3073,3077,3081,3086],{"type":44,"tag":2818,"props":3061,"children":3062},{"style":2825},[3063],{"type":50,"value":2867},{"type":44,"tag":2818,"props":3065,"children":3066},{"style":2870},[3067],{"type":50,"value":2873},{"type":44,"tag":2818,"props":3069,"children":3070},{"style":2876},[3071],{"type":50,"value":3072},"Detected:",{"type":44,"tag":2818,"props":3074,"children":3075},{"style":2870},[3076],{"type":50,"value":2884},{"type":44,"tag":2818,"props":3078,"children":3079},{"style":2825},[3080],{"type":50,"value":2889},{"type":44,"tag":2818,"props":3082,"children":3083},{"style":2892},[3084],{"type":50,"value":3085},"Yes\u002FNo",{"type":44,"tag":2818,"props":3087,"children":3088},{"style":2825},[3089],{"type":50,"value":2911},{"type":44,"tag":2818,"props":3091,"children":3093},{"class":2820,"line":3092},11,[3094,3098,3102,3107,3111,3115,3120,3125,3130,3135,3140],{"type":44,"tag":2818,"props":3095,"children":3096},{"style":2825},[3097],{"type":50,"value":2867},{"type":44,"tag":2818,"props":3099,"children":3100},{"style":2870},[3101],{"type":50,"value":2873},{"type":44,"tag":2818,"props":3103,"children":3104},{"style":2876},[3105],{"type":50,"value":3106},"Directories:",{"type":44,"tag":2818,"props":3108,"children":3109},{"style":2870},[3110],{"type":50,"value":2884},{"type":44,"tag":2818,"props":3112,"children":3113},{"style":2825},[3114],{"type":50,"value":2889},{"type":44,"tag":2818,"props":3116,"children":3117},{"style":2892},[3118],{"type":50,"value":3119},"list",{"type":44,"tag":2818,"props":3121,"children":3122},{"style":2898},[3123],{"type":50,"value":3124}," of",{"type":44,"tag":2818,"props":3126,"children":3127},{"style":2898},[3128],{"type":50,"value":3129}," frontend",{"type":44,"tag":2818,"props":3131,"children":3132},{"style":2898},[3133],{"type":50,"value":3134}," directories,",{"type":44,"tag":2818,"props":3136,"children":3137},{"style":2898},[3138],{"type":50,"value":3139}," or",{"type":44,"tag":2818,"props":3141,"children":3142},{"style":2825},[3143],{"type":50,"value":3144}," \"None\">\n",{"type":44,"tag":2818,"props":3146,"children":3148},{"class":2820,"line":3147},12,[3149,3153,3157,3161,3165,3169,3174,3178,3183,3188,3192],{"type":44,"tag":2818,"props":3150,"children":3151},{"style":2825},[3152],{"type":50,"value":2867},{"type":44,"tag":2818,"props":3154,"children":3155},{"style":2870},[3156],{"type":50,"value":2873},{"type":44,"tag":2818,"props":3158,"children":3159},{"style":2876},[3160],{"type":50,"value":2974},{"type":44,"tag":2818,"props":3162,"children":3163},{"style":2870},[3164],{"type":50,"value":2884},{"type":44,"tag":2818,"props":3166,"children":3167},{"style":2825},[3168],{"type":50,"value":2889},{"type":44,"tag":2818,"props":3170,"children":3171},{"style":2892},[3172],{"type":50,"value":3173},"frontend",{"type":44,"tag":2818,"props":3175,"children":3176},{"style":2898},[3177],{"type":50,"value":2992},{"type":44,"tag":2818,"props":3179,"children":3180},{"style":2898},[3181],{"type":50,"value":3182}," if",{"type":44,"tag":2818,"props":3184,"children":3185},{"style":2898},[3186],{"type":50,"value":3187}," detected,",{"type":44,"tag":2818,"props":3189,"children":3190},{"style":2898},[3191],{"type":50,"value":3139},{"type":44,"tag":2818,"props":3193,"children":3194},{"style":2825},[3195],{"type":50,"value":3196}," \"N\u002FA\">\n",{"type":44,"tag":2818,"props":3198,"children":3200},{"class":2820,"line":3199},13,[3201,3205,3209,3214,3218,3222,3227,3231,3236,3241,3246,3251,3256,3261,3266,3271],{"type":44,"tag":2818,"props":3202,"children":3203},{"style":2825},[3204],{"type":50,"value":2867},{"type":44,"tag":2818,"props":3206,"children":3207},{"style":2870},[3208],{"type":50,"value":2873},{"type":44,"tag":2818,"props":3210,"children":3211},{"style":2876},[3212],{"type":50,"value":3213},"Note:",{"type":44,"tag":2818,"props":3215,"children":3216},{"style":2870},[3217],{"type":50,"value":2884},{"type":44,"tag":2818,"props":3219,"children":3220},{"style":2825},[3221],{"type":50,"value":2889},{"type":44,"tag":2818,"props":3223,"children":3224},{"style":2892},[3225],{"type":50,"value":3226},"any",{"type":44,"tag":2818,"props":3228,"children":3229},{"style":2898},[3230],{"type":50,"value":2992},{"type":44,"tag":2818,"props":3232,"children":3233},{"style":2898},[3234],{"type":50,"value":3235}," server-side",{"type":44,"tag":2818,"props":3237,"children":3238},{"style":2898},[3239],{"type":50,"value":3240}," code",{"type":44,"tag":2818,"props":3242,"children":3243},{"style":2898},[3244],{"type":50,"value":3245}," that",{"type":44,"tag":2818,"props":3247,"children":3248},{"style":2898},[3249],{"type":50,"value":3250}," WAS",{"type":44,"tag":2818,"props":3252,"children":3253},{"style":2898},[3254],{"type":50,"value":3255}," included",{"type":44,"tag":2818,"props":3257,"children":3258},{"style":2898},[3259],{"type":50,"value":3260}," in",{"type":44,"tag":2818,"props":3262,"children":3263},{"style":2898},[3264],{"type":50,"value":3265}," migration",{"type":44,"tag":2818,"props":3267,"children":3268},{"style":2898},[3269],{"type":50,"value":3270}," units",{"type":44,"tag":2818,"props":3272,"children":3273},{"style":2825},[3274],{"type":50,"value":2911},{"type":44,"tag":2818,"props":3276,"children":3278},{"class":2820,"line":3277},14,[3279],{"type":44,"tag":2818,"props":3280,"children":3281},{"emptyLinePlaceholder":2841},[3282],{"type":50,"value":2844},{"type":44,"tag":2818,"props":3284,"children":3286},{"class":2820,"line":3285},15,[3287,3291],{"type":44,"tag":2818,"props":3288,"children":3289},{"style":2825},[3290],{"type":50,"value":2853},{"type":44,"tag":2818,"props":3292,"children":3293},{"style":2831},[3294],{"type":50,"value":3295},"Target System\n",{"type":44,"tag":2818,"props":3297,"children":3299},{"class":2820,"line":3298},16,[3300,3304,3308,3312,3316,3320,3324,3329,3333],{"type":44,"tag":2818,"props":3301,"children":3302},{"style":2825},[3303],{"type":50,"value":2867},{"type":44,"tag":2818,"props":3305,"children":3306},{"style":2870},[3307],{"type":50,"value":2873},{"type":44,"tag":2818,"props":3309,"children":3310},{"style":2876},[3311],{"type":50,"value":2879},{"type":44,"tag":2818,"props":3313,"children":3314},{"style":2870},[3315],{"type":50,"value":2884},{"type":44,"tag":2818,"props":3317,"children":3318},{"style":2825},[3319],{"type":50,"value":2889},{"type":44,"tag":2818,"props":3321,"children":3322},{"style":2892},[3323],{"type":50,"value":8},{"type":44,"tag":2818,"props":3325,"children":3326},{"style":2898},[3327],{"type":50,"value":3328}," project",{"type":44,"tag":2818,"props":3330,"children":3331},{"style":2898},[3332],{"type":50,"value":2906},{"type":44,"tag":2818,"props":3334,"children":3335},{"style":2825},[3336],{"type":50,"value":2911},{"type":44,"tag":2818,"props":3338,"children":3340},{"class":2820,"line":3339},17,[3341,3345,3349,3353,3357,3361,3365,3369,3373],{"type":44,"tag":2818,"props":3342,"children":3343},{"style":2825},[3344],{"type":50,"value":2867},{"type":44,"tag":2818,"props":3346,"children":3347},{"style":2870},[3348],{"type":50,"value":2873},{"type":44,"tag":2818,"props":3350,"children":3351},{"style":2876},[3352],{"type":50,"value":2927},{"type":44,"tag":2818,"props":3354,"children":3355},{"style":2870},[3356],{"type":50,"value":2884},{"type":44,"tag":2818,"props":3358,"children":3359},{"style":2825},[3360],{"type":50,"value":2889},{"type":44,"tag":2818,"props":3362,"children":3363},{"style":2892},[3364],{"type":50,"value":8},{"type":44,"tag":2818,"props":3366,"children":3367},{"style":2898},[3368],{"type":50,"value":2948},{"type":44,"tag":2818,"props":3370,"children":3371},{"style":2898},[3372],{"type":50,"value":2953},{"type":44,"tag":2818,"props":3374,"children":3375},{"style":2825},[3376],{"type":50,"value":2911},{"type":44,"tag":2818,"props":3378,"children":3380},{"class":2820,"line":3379},18,[3381,3385,3389,3394,3398],{"type":44,"tag":2818,"props":3382,"children":3383},{"style":2825},[3384],{"type":50,"value":2867},{"type":44,"tag":2818,"props":3386,"children":3387},{"style":2870},[3388],{"type":50,"value":2873},{"type":44,"tag":2818,"props":3390,"children":3391},{"style":2876},[3392],{"type":50,"value":3393},"Type:",{"type":44,"tag":2818,"props":3395,"children":3396},{"style":2870},[3397],{"type":50,"value":2884},{"type":44,"tag":2818,"props":3399,"children":3401},{"style":3400},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[3402],{"type":50,"value":3403}," Encore.ts | Encore Go\n",{"type":44,"tag":2818,"props":3405,"children":3407},{"class":2820,"line":3406},19,[3408],{"type":44,"tag":2818,"props":3409,"children":3410},{"emptyLinePlaceholder":2841},[3411],{"type":50,"value":2844},{"type":44,"tag":2818,"props":3413,"children":3415},{"class":2820,"line":3414},20,[3416,3420],{"type":44,"tag":2818,"props":3417,"children":3418},{"style":2825},[3419],{"type":50,"value":2853},{"type":44,"tag":2818,"props":3421,"children":3422},{"style":2831},[3423],{"type":50,"value":3424},"Migration Units\n",{"type":44,"tag":2818,"props":3426,"children":3428},{"class":2820,"line":3427},21,[3429],{"type":44,"tag":2818,"props":3430,"children":3431},{"emptyLinePlaceholder":2841},[3432],{"type":50,"value":2844},{"type":44,"tag":2818,"props":3434,"children":3436},{"class":2820,"line":3435},22,[3437,3442,3447,3451,3456,3460,3465,3469,3474,3478,3483,3487,3492],{"type":44,"tag":2818,"props":3438,"children":3439},{"style":2825},[3440],{"type":50,"value":3441},"|",{"type":44,"tag":2818,"props":3443,"children":3444},{"style":3400},[3445],{"type":50,"value":3446}," Unit ",{"type":44,"tag":2818,"props":3448,"children":3449},{"style":2825},[3450],{"type":50,"value":3441},{"type":44,"tag":2818,"props":3452,"children":3453},{"style":3400},[3454],{"type":50,"value":3455}," Endpoints ",{"type":44,"tag":2818,"props":3457,"children":3458},{"style":2825},[3459],{"type":50,"value":3441},{"type":44,"tag":2818,"props":3461,"children":3462},{"style":3400},[3463],{"type":50,"value":3464}," DB Tables ",{"type":44,"tag":2818,"props":3466,"children":3467},{"style":2825},[3468],{"type":50,"value":3441},{"type":44,"tag":2818,"props":3470,"children":3471},{"style":3400},[3472],{"type":50,"value":3473}," Other ",{"type":44,"tag":2818,"props":3475,"children":3476},{"style":2825},[3477],{"type":50,"value":3441},{"type":44,"tag":2818,"props":3479,"children":3480},{"style":3400},[3481],{"type":50,"value":3482}," Complexity ",{"type":44,"tag":2818,"props":3484,"children":3485},{"style":2825},[3486],{"type":50,"value":3441},{"type":44,"tag":2818,"props":3488,"children":3489},{"style":3400},[3490],{"type":50,"value":3491}," Status ",{"type":44,"tag":2818,"props":3493,"children":3494},{"style":2825},[3495],{"type":50,"value":3496},"|\n",{"type":44,"tag":2818,"props":3498,"children":3500},{"class":2820,"line":3499},23,[3501],{"type":44,"tag":2818,"props":3502,"children":3503},{"style":2825},[3504],{"type":50,"value":3505},"|------|-----------|-----------|-------|------------|--------|\n",{"type":44,"tag":2818,"props":3507,"children":3509},{"class":2820,"line":3508},24,[3510],{"type":44,"tag":2818,"props":3511,"children":3512},{"emptyLinePlaceholder":2841},[3513],{"type":50,"value":2844},{"type":44,"tag":2818,"props":3515,"children":3517},{"class":2820,"line":3516},25,[3518,3522],{"type":44,"tag":2818,"props":3519,"children":3520},{"style":2825},[3521],{"type":50,"value":2853},{"type":44,"tag":2818,"props":3523,"children":3524},{"style":2831},[3525],{"type":50,"value":3526},"Dependency Order\n",{"type":44,"tag":2818,"props":3528,"children":3529},{"class":2820,"line":24},[3530,3535,3539,3544,3549,3553,3557,3561],{"type":44,"tag":2818,"props":3531,"children":3532},{"style":2825},[3533],{"type":50,"value":3534},"1.",{"type":44,"tag":2818,"props":3536,"children":3537},{"style":2825},[3538],{"type":50,"value":2889},{"type":44,"tag":2818,"props":3540,"children":3541},{"style":2892},[3542],{"type":50,"value":3543},"ordered",{"type":44,"tag":2818,"props":3545,"children":3546},{"style":2898},[3547],{"type":50,"value":3548}," list",{"type":44,"tag":2818,"props":3550,"children":3551},{"style":2898},[3552],{"type":50,"value":3124},{"type":44,"tag":2818,"props":3554,"children":3555},{"style":2898},[3556],{"type":50,"value":3265},{"type":44,"tag":2818,"props":3558,"children":3559},{"style":2898},[3560],{"type":50,"value":3270},{"type":44,"tag":2818,"props":3562,"children":3563},{"style":2825},[3564],{"type":50,"value":2911},{"type":44,"tag":53,"props":3566,"children":3567},{},[3568,3573,3575,3580,3581,3586,3587,3592,3593,3598,3599],{"type":44,"tag":96,"props":3569,"children":3570},{},[3571],{"type":50,"value":3572},"Status values:",{"type":50,"value":3574}," ",{"type":44,"tag":59,"props":3576,"children":3578},{"className":3577},[],[3579],{"type":50,"value":164},{"type":50,"value":195},{"type":44,"tag":59,"props":3582,"children":3584},{"className":3583},[],[3585],{"type":50,"value":172},{"type":50,"value":195},{"type":44,"tag":59,"props":3588,"children":3590},{"className":3589},[],[3591],{"type":50,"value":193},{"type":50,"value":195},{"type":44,"tag":59,"props":3594,"children":3596},{"className":3595},[],[3597],{"type":50,"value":201},{"type":50,"value":195},{"type":44,"tag":59,"props":3600,"children":3602},{"className":3601},[],[3603],{"type":50,"value":209},{"type":44,"tag":53,"props":3605,"children":3606},{},[3607,3612,3613,3618,3620,3625,3627,3632],{"type":44,"tag":96,"props":3608,"children":3609},{},[3610],{"type":50,"value":3611},"Complexity values:",{"type":50,"value":3574},{"type":44,"tag":59,"props":3614,"children":3616},{"className":3615},[],[3617],{"type":50,"value":1199},{"type":50,"value":3619}," (direct equivalent), ",{"type":44,"tag":59,"props":3621,"children":3623},{"className":3622},[],[3624],{"type":50,"value":1209},{"type":50,"value":3626}," (requires restructuring), ",{"type":44,"tag":59,"props":3628,"children":3630},{"className":3629},[],[3631],{"type":50,"value":1219},{"type":50,"value":3633}," (needs redesign)",{"type":44,"tag":76,"props":3635,"children":3637},{"id":3636},"detail-file-format",[3638],{"type":50,"value":3639},"Detail File Format",{"type":44,"tag":53,"props":3641,"children":3642},{},[3643,3645,3650],{"type":50,"value":3644},"Create one file per migration unit at ",{"type":44,"tag":59,"props":3646,"children":3648},{"className":3647},[],[3649],{"type":50,"value":1494},{"type":50,"value":3651},". Use this exact template:",{"type":44,"tag":2807,"props":3653,"children":3655},{"className":2809,"code":3654,"language":2811,"meta":2812,"style":2812},"# Migration Unit: \u003Cunit-name>\n\n## Source\n- **Files:** \u003Clist of source files in this unit>\n- **Depends on:** \u003Cother migration units, with their current status>\n\n## Endpoints\n| Endpoint | Method | Path | Status | Notes |\n|----------|--------|------|--------|-------|\n\n## Database\n| Table | Complexity | Status | Notes |\n|-------|------------|--------|-------|\n\n## Tests\n- **Source tests:** \u003Ctest files and count>\n- **Migrated:** \u003Ccount of migrated tests>\n\n## Validation Log\n| Entity | Tests | HTTP Match | Evidence | Status |\n|--------|-------|------------|----------|--------|\n",[3656],{"type":44,"tag":59,"props":3657,"children":3658},{"__ignoreMap":2812},[3659,3685,3692,3704,3764,3826,3833,3845,3896,3904,3911,3923,3963,3971,3978,3990,4037,4084,4091,4103,4154],{"type":44,"tag":2818,"props":3660,"children":3661},{"class":2820,"line":2821},[3662,3666,3671,3676,3681],{"type":44,"tag":2818,"props":3663,"children":3664},{"style":2825},[3665],{"type":50,"value":2828},{"type":44,"tag":2818,"props":3667,"children":3668},{"style":2831},[3669],{"type":50,"value":3670},"Migration Unit: ",{"type":44,"tag":2818,"props":3672,"children":3673},{"style":2825},[3674],{"type":50,"value":3675},"\u003C",{"type":44,"tag":2818,"props":3677,"children":3678},{"style":2892},[3679],{"type":50,"value":3680},"unit-name",{"type":44,"tag":2818,"props":3682,"children":3683},{"style":2825},[3684],{"type":50,"value":2911},{"type":44,"tag":2818,"props":3686,"children":3687},{"class":2820,"line":2837},[3688],{"type":44,"tag":2818,"props":3689,"children":3690},{"emptyLinePlaceholder":2841},[3691],{"type":50,"value":2844},{"type":44,"tag":2818,"props":3693,"children":3694},{"class":2820,"line":2847},[3695,3699],{"type":44,"tag":2818,"props":3696,"children":3697},{"style":2825},[3698],{"type":50,"value":2853},{"type":44,"tag":2818,"props":3700,"children":3701},{"style":2831},[3702],{"type":50,"value":3703},"Source\n",{"type":44,"tag":2818,"props":3705,"children":3706},{"class":2820,"line":2861},[3707,3711,3715,3720,3724,3728,3732,3736,3741,3746,3750,3755,3760],{"type":44,"tag":2818,"props":3708,"children":3709},{"style":2825},[3710],{"type":50,"value":2867},{"type":44,"tag":2818,"props":3712,"children":3713},{"style":2870},[3714],{"type":50,"value":2873},{"type":44,"tag":2818,"props":3716,"children":3717},{"style":2876},[3718],{"type":50,"value":3719},"Files:",{"type":44,"tag":2818,"props":3721,"children":3722},{"style":2870},[3723],{"type":50,"value":2884},{"type":44,"tag":2818,"props":3725,"children":3726},{"style":2825},[3727],{"type":50,"value":2889},{"type":44,"tag":2818,"props":3729,"children":3730},{"style":2892},[3731],{"type":50,"value":3119},{"type":44,"tag":2818,"props":3733,"children":3734},{"style":2898},[3735],{"type":50,"value":3124},{"type":44,"tag":2818,"props":3737,"children":3738},{"style":2898},[3739],{"type":50,"value":3740}," source",{"type":44,"tag":2818,"props":3742,"children":3743},{"style":2898},[3744],{"type":50,"value":3745}," files",{"type":44,"tag":2818,"props":3747,"children":3748},{"style":2898},[3749],{"type":50,"value":3260},{"type":44,"tag":2818,"props":3751,"children":3752},{"style":2898},[3753],{"type":50,"value":3754}," this",{"type":44,"tag":2818,"props":3756,"children":3757},{"style":2898},[3758],{"type":50,"value":3759}," unit",{"type":44,"tag":2818,"props":3761,"children":3762},{"style":2825},[3763],{"type":50,"value":2911},{"type":44,"tag":2818,"props":3765,"children":3766},{"class":2820,"line":28},[3767,3771,3775,3780,3784,3788,3793,3797,3802,3807,3812,3817,3822],{"type":44,"tag":2818,"props":3768,"children":3769},{"style":2825},[3770],{"type":50,"value":2867},{"type":44,"tag":2818,"props":3772,"children":3773},{"style":2870},[3774],{"type":50,"value":2873},{"type":44,"tag":2818,"props":3776,"children":3777},{"style":2876},[3778],{"type":50,"value":3779},"Depends on:",{"type":44,"tag":2818,"props":3781,"children":3782},{"style":2870},[3783],{"type":50,"value":2884},{"type":44,"tag":2818,"props":3785,"children":3786},{"style":2825},[3787],{"type":50,"value":2889},{"type":44,"tag":2818,"props":3789,"children":3790},{"style":2892},[3791],{"type":50,"value":3792},"other",{"type":44,"tag":2818,"props":3794,"children":3795},{"style":2898},[3796],{"type":50,"value":3265},{"type":44,"tag":2818,"props":3798,"children":3799},{"style":2898},[3800],{"type":50,"value":3801}," units,",{"type":44,"tag":2818,"props":3803,"children":3804},{"style":2898},[3805],{"type":50,"value":3806}," with",{"type":44,"tag":2818,"props":3808,"children":3809},{"style":2898},[3810],{"type":50,"value":3811}," their",{"type":44,"tag":2818,"props":3813,"children":3814},{"style":2898},[3815],{"type":50,"value":3816}," current",{"type":44,"tag":2818,"props":3818,"children":3819},{"style":2898},[3820],{"type":50,"value":3821}," status",{"type":44,"tag":2818,"props":3823,"children":3824},{"style":2825},[3825],{"type":50,"value":2911},{"type":44,"tag":2818,"props":3827,"children":3828},{"class":2820,"line":2960},[3829],{"type":44,"tag":2818,"props":3830,"children":3831},{"emptyLinePlaceholder":2841},[3832],{"type":50,"value":2844},{"type":44,"tag":2818,"props":3834,"children":3835},{"class":2820,"line":2999},[3836,3840],{"type":44,"tag":2818,"props":3837,"children":3838},{"style":2825},[3839],{"type":50,"value":2853},{"type":44,"tag":2818,"props":3841,"children":3842},{"style":2831},[3843],{"type":50,"value":3844},"Endpoints\n",{"type":44,"tag":2818,"props":3846,"children":3847},{"class":2820,"line":3037},[3848,3852,3857,3861,3866,3870,3875,3879,3883,3887,3892],{"type":44,"tag":2818,"props":3849,"children":3850},{"style":2825},[3851],{"type":50,"value":3441},{"type":44,"tag":2818,"props":3853,"children":3854},{"style":3400},[3855],{"type":50,"value":3856}," Endpoint ",{"type":44,"tag":2818,"props":3858,"children":3859},{"style":2825},[3860],{"type":50,"value":3441},{"type":44,"tag":2818,"props":3862,"children":3863},{"style":3400},[3864],{"type":50,"value":3865}," Method ",{"type":44,"tag":2818,"props":3867,"children":3868},{"style":2825},[3869],{"type":50,"value":3441},{"type":44,"tag":2818,"props":3871,"children":3872},{"style":3400},[3873],{"type":50,"value":3874}," Path ",{"type":44,"tag":2818,"props":3876,"children":3877},{"style":2825},[3878],{"type":50,"value":3441},{"type":44,"tag":2818,"props":3880,"children":3881},{"style":3400},[3882],{"type":50,"value":3491},{"type":44,"tag":2818,"props":3884,"children":3885},{"style":2825},[3886],{"type":50,"value":3441},{"type":44,"tag":2818,"props":3888,"children":3889},{"style":3400},[3890],{"type":50,"value":3891}," Notes ",{"type":44,"tag":2818,"props":3893,"children":3894},{"style":2825},[3895],{"type":50,"value":3496},{"type":44,"tag":2818,"props":3897,"children":3898},{"class":2820,"line":3045},[3899],{"type":44,"tag":2818,"props":3900,"children":3901},{"style":2825},[3902],{"type":50,"value":3903},"|----------|--------|------|--------|-------|\n",{"type":44,"tag":2818,"props":3905,"children":3906},{"class":2820,"line":3058},[3907],{"type":44,"tag":2818,"props":3908,"children":3909},{"emptyLinePlaceholder":2841},[3910],{"type":50,"value":2844},{"type":44,"tag":2818,"props":3912,"children":3913},{"class":2820,"line":3092},[3914,3918],{"type":44,"tag":2818,"props":3915,"children":3916},{"style":2825},[3917],{"type":50,"value":2853},{"type":44,"tag":2818,"props":3919,"children":3920},{"style":2831},[3921],{"type":50,"value":3922},"Database\n",{"type":44,"tag":2818,"props":3924,"children":3925},{"class":2820,"line":3147},[3926,3930,3935,3939,3943,3947,3951,3955,3959],{"type":44,"tag":2818,"props":3927,"children":3928},{"style":2825},[3929],{"type":50,"value":3441},{"type":44,"tag":2818,"props":3931,"children":3932},{"style":3400},[3933],{"type":50,"value":3934}," Table ",{"type":44,"tag":2818,"props":3936,"children":3937},{"style":2825},[3938],{"type":50,"value":3441},{"type":44,"tag":2818,"props":3940,"children":3941},{"style":3400},[3942],{"type":50,"value":3482},{"type":44,"tag":2818,"props":3944,"children":3945},{"style":2825},[3946],{"type":50,"value":3441},{"type":44,"tag":2818,"props":3948,"children":3949},{"style":3400},[3950],{"type":50,"value":3491},{"type":44,"tag":2818,"props":3952,"children":3953},{"style":2825},[3954],{"type":50,"value":3441},{"type":44,"tag":2818,"props":3956,"children":3957},{"style":3400},[3958],{"type":50,"value":3891},{"type":44,"tag":2818,"props":3960,"children":3961},{"style":2825},[3962],{"type":50,"value":3496},{"type":44,"tag":2818,"props":3964,"children":3965},{"class":2820,"line":3199},[3966],{"type":44,"tag":2818,"props":3967,"children":3968},{"style":2825},[3969],{"type":50,"value":3970},"|-------|------------|--------|-------|\n",{"type":44,"tag":2818,"props":3972,"children":3973},{"class":2820,"line":3277},[3974],{"type":44,"tag":2818,"props":3975,"children":3976},{"emptyLinePlaceholder":2841},[3977],{"type":50,"value":2844},{"type":44,"tag":2818,"props":3979,"children":3980},{"class":2820,"line":3285},[3981,3985],{"type":44,"tag":2818,"props":3982,"children":3983},{"style":2825},[3984],{"type":50,"value":2853},{"type":44,"tag":2818,"props":3986,"children":3987},{"style":2831},[3988],{"type":50,"value":3989},"Tests\n",{"type":44,"tag":2818,"props":3991,"children":3992},{"class":2820,"line":3298},[3993,3997,4001,4006,4010,4014,4019,4023,4028,4033],{"type":44,"tag":2818,"props":3994,"children":3995},{"style":2825},[3996],{"type":50,"value":2867},{"type":44,"tag":2818,"props":3998,"children":3999},{"style":2870},[4000],{"type":50,"value":2873},{"type":44,"tag":2818,"props":4002,"children":4003},{"style":2876},[4004],{"type":50,"value":4005},"Source tests:",{"type":44,"tag":2818,"props":4007,"children":4008},{"style":2870},[4009],{"type":50,"value":2884},{"type":44,"tag":2818,"props":4011,"children":4012},{"style":2825},[4013],{"type":50,"value":2889},{"type":44,"tag":2818,"props":4015,"children":4016},{"style":2892},[4017],{"type":50,"value":4018},"test",{"type":44,"tag":2818,"props":4020,"children":4021},{"style":2898},[4022],{"type":50,"value":3745},{"type":44,"tag":2818,"props":4024,"children":4025},{"style":2898},[4026],{"type":50,"value":4027}," and",{"type":44,"tag":2818,"props":4029,"children":4030},{"style":2898},[4031],{"type":50,"value":4032}," count",{"type":44,"tag":2818,"props":4034,"children":4035},{"style":2825},[4036],{"type":50,"value":2911},{"type":44,"tag":2818,"props":4038,"children":4039},{"class":2820,"line":3339},[4040,4044,4048,4053,4057,4061,4066,4070,4075,4080],{"type":44,"tag":2818,"props":4041,"children":4042},{"style":2825},[4043],{"type":50,"value":2867},{"type":44,"tag":2818,"props":4045,"children":4046},{"style":2870},[4047],{"type":50,"value":2873},{"type":44,"tag":2818,"props":4049,"children":4050},{"style":2876},[4051],{"type":50,"value":4052},"Migrated:",{"type":44,"tag":2818,"props":4054,"children":4055},{"style":2870},[4056],{"type":50,"value":2884},{"type":44,"tag":2818,"props":4058,"children":4059},{"style":2825},[4060],{"type":50,"value":2889},{"type":44,"tag":2818,"props":4062,"children":4063},{"style":2892},[4064],{"type":50,"value":4065},"count",{"type":44,"tag":2818,"props":4067,"children":4068},{"style":2898},[4069],{"type":50,"value":3124},{"type":44,"tag":2818,"props":4071,"children":4072},{"style":2898},[4073],{"type":50,"value":4074}," migrated",{"type":44,"tag":2818,"props":4076,"children":4077},{"style":2898},[4078],{"type":50,"value":4079}," tests",{"type":44,"tag":2818,"props":4081,"children":4082},{"style":2825},[4083],{"type":50,"value":2911},{"type":44,"tag":2818,"props":4085,"children":4086},{"class":2820,"line":3379},[4087],{"type":44,"tag":2818,"props":4088,"children":4089},{"emptyLinePlaceholder":2841},[4090],{"type":50,"value":2844},{"type":44,"tag":2818,"props":4092,"children":4093},{"class":2820,"line":3406},[4094,4098],{"type":44,"tag":2818,"props":4095,"children":4096},{"style":2825},[4097],{"type":50,"value":2853},{"type":44,"tag":2818,"props":4099,"children":4100},{"style":2831},[4101],{"type":50,"value":4102},"Validation Log\n",{"type":44,"tag":2818,"props":4104,"children":4105},{"class":2820,"line":3414},[4106,4110,4115,4119,4124,4128,4133,4137,4142,4146,4150],{"type":44,"tag":2818,"props":4107,"children":4108},{"style":2825},[4109],{"type":50,"value":3441},{"type":44,"tag":2818,"props":4111,"children":4112},{"style":3400},[4113],{"type":50,"value":4114}," Entity ",{"type":44,"tag":2818,"props":4116,"children":4117},{"style":2825},[4118],{"type":50,"value":3441},{"type":44,"tag":2818,"props":4120,"children":4121},{"style":3400},[4122],{"type":50,"value":4123}," Tests ",{"type":44,"tag":2818,"props":4125,"children":4126},{"style":2825},[4127],{"type":50,"value":3441},{"type":44,"tag":2818,"props":4129,"children":4130},{"style":3400},[4131],{"type":50,"value":4132}," HTTP Match ",{"type":44,"tag":2818,"props":4134,"children":4135},{"style":2825},[4136],{"type":50,"value":3441},{"type":44,"tag":2818,"props":4138,"children":4139},{"style":3400},[4140],{"type":50,"value":4141}," Evidence ",{"type":44,"tag":2818,"props":4143,"children":4144},{"style":2825},[4145],{"type":50,"value":3441},{"type":44,"tag":2818,"props":4147,"children":4148},{"style":3400},[4149],{"type":50,"value":3491},{"type":44,"tag":2818,"props":4151,"children":4152},{"style":2825},[4153],{"type":50,"value":3496},{"type":44,"tag":2818,"props":4155,"children":4156},{"class":2820,"line":3427},[4157],{"type":44,"tag":2818,"props":4158,"children":4159},{"style":2825},[4160],{"type":50,"value":4161},"|--------|-------|------------|----------|--------|\n",{"type":44,"tag":53,"props":4163,"children":4164},{},[4165],{"type":50,"value":4166},"Not all sections are required — omit sections that don't apply to a given unit (e.g., a secrets unit won't have Endpoints or Database sections).",{"type":44,"tag":4168,"props":4169,"children":4170},"style",{},[4171],{"type":50,"value":4172},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":4174,"total":4269},[4175,4186,4196,4213,4228,4240,4255],{"slug":1650,"name":1650,"fn":4176,"description":4177,"org":4178,"tags":4179,"stars":24,"repoUrl":25,"updatedAt":4185},"build type-safe APIs with Encore","Define typed API endpoints in Encore.ts using `api(...)` from `encore.dev\u002Fapi`. Covers typed request\u002Fresponse interfaces, path\u002Fquery\u002Fheader\u002Fcookie params, request validation, and `APIError`. For raw endpoints (`api.raw()`) and inbound webhooks, use `encore-webhook` instead.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4180,4181,4182],{"name":22,"slug":23,"type":14},{"name":9,"slug":8,"type":14},{"name":4183,"slug":4184,"type":14},"TypeScript","typescript","2026-04-06T18:09:46.044101",{"slug":1675,"name":1675,"fn":4187,"description":4188,"org":4189,"tags":4190,"stars":24,"repoUrl":25,"updatedAt":4195},"implement Encore.ts authentication","Protect Encore.ts endpoints with authentication and authorize callers. Covers `authHandler`, `Gateway`, `getAuthData`, and `auth: true`.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4191,4193,4194],{"name":1399,"slug":4192,"type":14},"auth",{"name":9,"slug":8,"type":14},{"name":4183,"slug":4184,"type":14},"2026-04-06T18:09:47.336322",{"slug":1778,"name":1778,"fn":4197,"description":4198,"org":4199,"tags":4200,"stars":24,"repoUrl":25,"updatedAt":4212},"store files in Encore.ts buckets","Store unstructured files in Encore.ts using `Bucket` from `encore.dev\u002Fstorage\u002Fobjects` — uploads, images, documents, blobs.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4201,4204,4205,4208,4211],{"name":4202,"slug":4203,"type":14},"Backend","backend",{"name":9,"slug":8,"type":14},{"name":4206,"slug":4207,"type":14},"File Storage","file-storage",{"name":4209,"slug":4210,"type":14},"File Uploads","file-uploads",{"name":4183,"slug":4184,"type":14},"2026-05-16T05:59:52.813772",{"slug":1804,"name":1804,"fn":4214,"description":4215,"org":4216,"tags":4217,"stars":24,"repoUrl":25,"updatedAt":4227},"cache data in Redis with Encore.ts","Cache data in Redis from Encore.ts using `CacheCluster` and typed keyspaces from `encore.dev\u002Fstorage\u002Fcache`. Type-safe key\u002Fvalue access with TTLs, atomic increments, and per-keyspace data shapes.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4218,4219,4222,4223,4226],{"name":4202,"slug":4203,"type":14},{"name":4220,"slug":4221,"type":14},"Caching","caching",{"name":9,"slug":8,"type":14},{"name":4224,"slug":4225,"type":14},"Redis","redis",{"name":4183,"slug":4184,"type":14},"2026-05-16T05:59:56.808328",{"slug":4229,"name":4229,"fn":4230,"description":4231,"org":4232,"tags":4233,"stars":24,"repoUrl":25,"updatedAt":4239},"encore-code-review","review Encore.ts code","Review existing Encore.ts code for best practices and common anti-patterns.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4234,4237,4238],{"name":4235,"slug":4236,"type":14},"Code Review","code-review",{"name":9,"slug":8,"type":14},{"name":4183,"slug":4184,"type":14},"2026-04-06T18:10:01.123999",{"slug":1752,"name":1752,"fn":4241,"description":4242,"org":4243,"tags":4244,"stars":24,"repoUrl":25,"updatedAt":4254},"schedule recurring jobs in Encore.ts","Schedule periodic \u002F recurring work in Encore.ts using `CronJob` from `encore.dev\u002Fcron`. Covers `every: \"1h\"` interval syntax and `schedule: \"0 9 * * 1\"` cron expressions.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4245,4248,4249,4250,4253],{"name":4246,"slug":4247,"type":14},"Automation","automation",{"name":4202,"slug":4203,"type":14},{"name":9,"slug":8,"type":14},{"name":4251,"slug":4252,"type":14},"Scheduling","scheduling",{"name":4183,"slug":4184,"type":14},"2026-05-16T05:59:54.146651",{"slug":1701,"name":1701,"fn":4256,"description":4257,"org":4258,"tags":4259,"stars":24,"repoUrl":25,"updatedAt":4268},"build Encore databases","Work with PostgreSQL in Encore.ts using `SQLDatabase` from `encore.dev\u002Fstorage\u002Fsqldb` — schema migrations and SQL queries.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4260,4263,4264,4267],{"name":4261,"slug":4262,"type":14},"Database","database",{"name":9,"slug":8,"type":14},{"name":4265,"slug":4266,"type":14},"ORM","orm",{"name":4183,"slug":4184,"type":14},"2026-04-06T18:09:54.823017",28,{"items":4271,"total":4269},[4272,4278,4284,4292,4300,4306,4314,4321,4334,4350,4361,4371],{"slug":1650,"name":1650,"fn":4176,"description":4177,"org":4273,"tags":4274,"stars":24,"repoUrl":25,"updatedAt":4185},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4275,4276,4277],{"name":22,"slug":23,"type":14},{"name":9,"slug":8,"type":14},{"name":4183,"slug":4184,"type":14},{"slug":1675,"name":1675,"fn":4187,"description":4188,"org":4279,"tags":4280,"stars":24,"repoUrl":25,"updatedAt":4195},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4281,4282,4283],{"name":1399,"slug":4192,"type":14},{"name":9,"slug":8,"type":14},{"name":4183,"slug":4184,"type":14},{"slug":1778,"name":1778,"fn":4197,"description":4198,"org":4285,"tags":4286,"stars":24,"repoUrl":25,"updatedAt":4212},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4287,4288,4289,4290,4291],{"name":4202,"slug":4203,"type":14},{"name":9,"slug":8,"type":14},{"name":4206,"slug":4207,"type":14},{"name":4209,"slug":4210,"type":14},{"name":4183,"slug":4184,"type":14},{"slug":1804,"name":1804,"fn":4214,"description":4215,"org":4293,"tags":4294,"stars":24,"repoUrl":25,"updatedAt":4227},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4295,4296,4297,4298,4299],{"name":4202,"slug":4203,"type":14},{"name":4220,"slug":4221,"type":14},{"name":9,"slug":8,"type":14},{"name":4224,"slug":4225,"type":14},{"name":4183,"slug":4184,"type":14},{"slug":4229,"name":4229,"fn":4230,"description":4231,"org":4301,"tags":4302,"stars":24,"repoUrl":25,"updatedAt":4239},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4303,4304,4305],{"name":4235,"slug":4236,"type":14},{"name":9,"slug":8,"type":14},{"name":4183,"slug":4184,"type":14},{"slug":1752,"name":1752,"fn":4241,"description":4242,"org":4307,"tags":4308,"stars":24,"repoUrl":25,"updatedAt":4254},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4309,4310,4311,4312,4313],{"name":4246,"slug":4247,"type":14},{"name":4202,"slug":4203,"type":14},{"name":9,"slug":8,"type":14},{"name":4251,"slug":4252,"type":14},{"name":4183,"slug":4184,"type":14},{"slug":1701,"name":1701,"fn":4256,"description":4257,"org":4315,"tags":4316,"stars":24,"repoUrl":25,"updatedAt":4268},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4317,4318,4319,4320],{"name":4261,"slug":4262,"type":14},{"name":9,"slug":8,"type":14},{"name":4265,"slug":4266,"type":14},{"name":4183,"slug":4184,"type":14},{"slug":2317,"name":2317,"fn":4322,"description":4323,"org":4324,"tags":4325,"stars":24,"repoUrl":25,"updatedAt":4333},"connect frontend to Encore backend","Connect a frontend application (React, Next.js, Vue, Svelte, etc.) to an Encore.ts backend.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4326,4327,4329,4331],{"name":9,"slug":8,"type":14},{"name":4328,"slug":3173,"type":14},"Frontend",{"name":720,"slug":4330,"type":14},"next-js",{"name":4332,"slug":639,"type":14},"React","2026-04-06T18:09:56.091006",{"slug":1308,"name":1308,"fn":4335,"description":4336,"org":4337,"tags":4338,"stars":24,"repoUrl":25,"updatedAt":4349},"build and run applications with Encore.ts","Bootstrap a brand-new Encore.ts project from zero. Only for first-time CLI install and `encore app create` — not for architecture or feature questions.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4339,4340,4341,4342,4345,4346],{"name":22,"slug":23,"type":14},{"name":4202,"slug":4203,"type":14},{"name":9,"slug":8,"type":14},{"name":4343,"slug":4344,"type":14},"Local Development","local-development",{"name":4183,"slug":4184,"type":14},{"name":4347,"slug":4348,"type":14},"Web Development","web-development","2026-04-06T18:10:04.885446",{"slug":1659,"name":1659,"fn":4351,"description":4352,"org":4353,"tags":4354,"stars":24,"repoUrl":25,"updatedAt":4360},"build APIs with Encore Go","Define typed API endpoints in Encore Go using `\u002F\u002Fencore:api` annotations. Covers typed request\u002Fresponse structs, path\u002Fquery\u002Fheader\u002Fcookie params, and error returns. For raw endpoints (`\u002F\u002Fencore:api raw`) and inbound webhooks, use `encore-go-webhook` instead.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4355,4356,4357],{"name":22,"slug":23,"type":14},{"name":9,"slug":8,"type":14},{"name":4358,"slug":4359,"type":14},"Go","go","2026-04-06T18:09:48.578781",{"slug":1684,"name":1684,"fn":4362,"description":4363,"org":4364,"tags":4365,"stars":24,"repoUrl":25,"updatedAt":4370},"implement authentication with Encore Go","Protect Encore Go endpoints with authentication and authorize callers. Covers `auth.AuthHandler`, `auth.UserID`, the `Authorization` header, and `\u002F\u002Fencore:api auth`.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4366,4367,4368,4369],{"name":1399,"slug":4192,"type":14},{"name":4202,"slug":4203,"type":14},{"name":9,"slug":8,"type":14},{"name":4358,"slug":4359,"type":14},"2026-04-06T18:09:51.065102",{"slug":1787,"name":1787,"fn":4372,"description":4373,"org":4374,"tags":4375,"stars":24,"repoUrl":25,"updatedAt":4383},"store files in Encore Go buckets","Store unstructured files in Encore Go using `objects.NewBucket` from `encore.dev\u002Fstorage\u002Fobjects` — uploads, images, documents, blobs.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[4376,4377,4378,4379,4380],{"name":4202,"slug":4203,"type":14},{"name":9,"slug":8,"type":14},{"name":4206,"slug":4207,"type":14},{"name":4358,"slug":4359,"type":14},{"name":4381,"slug":4382,"type":14},"Storage","storage","2026-05-16T06:00:03.633918"]