Lessons from testing AI agents for multi-framework apps
Building sample apps across multiple frameworks is traditionally time-intensive, yet AI agents offer new possibilities. Here's how we automated migrations with AI agents, and the lessons we learned along the way.
For small presales or Developer Relations teams, creating sample applications in multiple frameworks can be a heavy lift. Each framework has its own conventions, libraries, and syntax, meaning the same integration needs to be re-implemented in different ways. Even simple demo apps can require significant time and effort when multiplied across React, Vue, Svelte, and others.
Our goal was clear: build a Kickstart sample app in various frameworks, each one demonstrating the same essentials. Every app should showcase a simple landing page that fetches content from Kontent.ai, uses a type-safe generated model, and resolves rich text with embedded components. That baseline experience is enough to help developers understand how integration works, without overwhelming them with unnecessary complexity.
This makes sample apps a compelling space to explore the potential of AI agents. Their structured and constrained nature makes them a suitable test case for automation. Instead of hand-coding each version, a team can experiment with AI-driven migrations that adapt shared logic while handling framework-specific differences. At Kontent.ai, we used our Kickstart repository as the baseline project for testing this approach, and Claude Code as the AI agent for guiding framework-to-framework transformations.
Preparing the codebase for AI
A successful migration starts with a clean and focused repository. Reducing unnecessary code helps the AI stay on task, avoids distractions and hallucinations from parts of the application irrelevant to the sample.
Adding basic screenshot tests ensures that visual changes are caught early. Even in small sample apps, framework migrations can unintentionally alter layouts or break styles. Automated checks provide a safety net by verifying that each migrated sample app renders consistently with the original base version.
Finally, we include the Playwrightand Context7 MCPs (Model Context Protocol) in the repository to give the agent practical tools and current knowledge. Playwright helps the agent check that pages still look and behave as expected by letting it interact with the app in a browser-like environment. Context7 brings in up-to-date documentation and examples, so the agent can base its changes on the latest APIs and best practices. With these in place, the agent doesn’t just generate code blindly - it can verify results and adapt its actions accordingly.
Iterating toward an effective prompt
Getting the AI to perform consistently required careful prompt design. The challenge was striking the right balance between generalized instructions that could apply across frameworks and concrete examples that showed the agent exactly what to do. For instance, providing direct links to the Portable Text repositories helped keep it on course, instead of letting it drift and remove that functionality entirely.
Another key factor was ensuring the AI always worked with the latest documentation, achieved by instructing it to fetch fresh sources through the Context7 MCP. Frameworks evolve quickly, and relying on outdated examples caused repeated errors. By referencing up-to-date docs, the AI could better understand library choices, syntax changes, and best practices.
This process was highly iterative. Each attempt refined the prompt, teaching us how much structure was necessary for the AI to stay on track without becoming too rigid.
Finalized prompt for Claude Code CLI agent to run autonomous migrations (in Markdown):
You will migrate a sample **TypeScript** application from one frontend framework to another while preserving its functionality and structure. Target framework: `$FRAMEWORK`.
Follow these steps:
* **Research the target framework.** Read the official documentation, identify the latest techniques and best practices, and record your findings in `framework-notes.md`. Find the newest best practices. For instance, when transitioning to Svelte, use Runes and find libraries (for instance, on routing, use a library that supports Runes. Focus on:
* Project structure and conventions
* Component syntax and lifecycle
* Data fetching
* State management approaches
* Routing patterns
* Build configuration
* Recommended official dependencies
* Tailwind configuration
* Eslint Configuration
* Typescript integration - for example, Svelte uses \`svelte-check\`
* **Portable‑Text plan (do not remove it).** Keep Portable‑Text; switch to the correct adapter for the target framework.
Research and review [https://github.com/kontent-ai/rich-text-resolver-js](https://github.com/kontent-ai/rich-text-resolver-js) to understand rich‑text handling in the chosen framework. If a binding is missing, consult [https://github.com/orgs/portabletext/repositories](https://github.com/orgs/portabletext/repositories) for available adapters. Implementation details vary by framework (e.g., Svelte’s Portable‑Text often requires a helper function to access Portable‑Text data and passing a `context` prop to the `<PortableText>` component with additional data). Create a dedicated plan in `portable-text-transition.md`.
* **Install dependencies.** Using npm, install the required packages for the target framework (per the official docs):
```bash
npm install <framework-packages>
```
* **Assess the current repo and draft a plan.** Detect the current framework in the repository and create `transition-plan.md` a description of the migration from the original framework to the new one, referencing `framework-notes.md` and `portable-text-transition.md`.
* **Migrate the code in order.** Using `transition-plan.md`Start with the `components/` directory, then proceed to the `pages/` directory, converting each file to the target framework’s syntax and conventions.
* **Styling is off‑limits.** Do not modify any styling or CSS; preserve all existing style and design files. Update the Tailwind configuration only as required by the target framework.
* Code Quality: Run the following checks to ensure good code quality `npm run lint` `npm run dprint:check` and use framework-specific typecheck. Use tsconfig.app.json for type-checking. Only continue if it passes.
* **README update.** Add instructions for starting the app with the new framework, including required scripts, commands, and any local setup notes. **Do not mention that the app is AI‑generated.**
* **E2E testing.** Test the migrated application end‑to‑end with Playwright. Run Chromium‑only tests via:
```bash
npm run test:visual
```
**CRITICAL:** Do not update screenshots and do not update playwright tests logic.
* Use Playwright MCP to make sure that there are no errors in the console.
* **Cleanup (CRITICAL).** After the migrated version works correctly, remove all legacy components and pages from the old framework and uninstall its related packages.
**Outcome:** A repository fully migrated to the new framework with no remaining traces of the previous framework.
Where AI excelled during migrations...
The AI performed well when frameworks shared structural similarities. Transitions to Solid, Vue.js, and Svelte from the baseline project went smoothly. In these cases, the agent was able to:
Suggest appropriate libraries for each framework.
Provide clear explanations of concepts for developers reviewing the code.
Summarize repository changes and migration steps.
Transform component-level code in under ten minutes.
The component migration in particular was a standout strength. The AI could translate components into the target framework with minimal intervention, saving significant developer time.
...and where it struggled
The limitations became more obvious when frameworks diverged in structure. Attempts to migrate to React Native, Angular, or React with GraphQL failed. In many cases, the generated code wouldn’t even build, and when it did, it produced runtime errors or displayed no data at all. For a developer without prior experience in the target framework, the AI’s output added little to no value.
Framework-specific quirks introduced more friction. For example, different ways of resolving Portable Text (structured rich text) led to repeated errors. The agent sometimes ignored instructions, attempting to push migrations forward even after hitting a failed build. In one case, it repeatedly disabled Svelte Runes, even though they are the recommended best practice.
These failures underscored a key reality: AI is not yet capable of handling fundamentally different frameworks on its own.
Lessons learned
The experiments revealed a nuanced picture of where AI is most useful:
Best fit: Migrating between similar frameworks (e.g., React → Solid). In these cases, autonomy worked well.
Assisted mode needed: For complex tasks like restructuring projects or resolving rich-text, AI worked best with a developer-in-the-loop to guide and review progress.
Value proposition: Even if not autonomous, AI can significantly speed up migration workflows, handling repetitive tasks while leaving humans to resolve tricky framework-specific issues.
In the end, AI serves better as an accelerator than as an autonomous entity. It helps teams move faster and reduce repetitive effort, but meaningful results still depend on developer insight and review.
What if we told you there was a way to make your website a place that will always be relevant, no matter the season or the year? Two words—evergreen content. What does evergreen mean in marketing, and how do you make evergreen content? Let’s dive into it.
How can you create a cohesive experience for customers no matter what channel they’re on or what device they’re using? The answer is going omnichannel.
To structure a blog post, start with a strong headline, write a clear introduction, and break content into short paragraphs. Use descriptive subheadings, add visuals, and format for easy scanning. Don’t forget about linking and filling out the metadata. Want to go into more detail? Dive into this blog.
Lucie Simonova
Subscribe to the Kontent.ai newsletter
Get the hottest updates while they’re fresh! For more industry insights, follow our LinkedIn profile.