Skip to content
FD
← Back to blog

Watch AWS Transform Custom migrate a PHP app to Python + Angular

Strava put their Year in Sport behind a paywall this year.

11 min read
Watch AWS Transform Custom migrate a PHP app to Python + Angular

Grab the popcorn! Watch AWS Transform Custom migrate a PHP app to Python + Angular from the comfort of my couch. Did it actually exceed expectations?

Strava put their Year in Sport behind a paywall this year. Frustrating, right? It’s my data! 😤

I wasn’t about to pay to see my own stats, so I went looking for alternatives. I found an awesome open-source tool on GitHub that generates a report… but it was written in PHP.

Problem: I don’t really know PHP, and I wanted to hack the code to add my own custom metrics.

Solution: AWS Transform Custom.

I decided to run an experiment: Could I use AWS’s new AI migration agent to rewrite this PHP app into a stack I love (Python + Angular) so I could customize it?

As you might have heard, AWS announced AWS Transform earlier this year for mainframe migrations — basically moving legacy stuff to something a bit more “AWS compatible.” Honestly, I saw the service and thought, “Okay, definitely not for me.”

But then came re

(I was there 🙌).

They dropped new features: Python 2 to 3 upgrades… and AWS Transform Custom.

On paper? You train AWS Transform Custom, and it modernizes your stack exactly how you want. Perfect! I thought, “This is exactly what I need.” I inherited a PHP project and wanted to switch it to a more modern, different stack. Let’s see how it works and if it actually lives up to the promises AWS sold us!

To get started, you could check the AWS console, but it’s pretty useless for our specific case. I didn’t even need to open it. Everything happens in the CLI with a program built for the occasion.

Let’s install atx:

curl -fsSL https://desktop-release.transform.us-east-1.api.aws/install.sh | bash

And let’s verify everything worked with atx —version. When I ran my tests, I was on v1.0.0.

Full docs are here if needed: https://docs.aws.amazon.com/transform/latest/userguide/custom-get-started.html

If you haven’t already, you’ll need to use your AWS credentials. Yep, they need to bill you somehow 😀. Nothing new here, just like the standard AWS CLI, it uses either your profile or environment variables.

By default, AWS offers “models” (I’m assuming they’re models, but without knowing the backend architecture, I can’t say for sure. If anyone knows more, drop a comment!). Right now, we have these transformation models trained and tested by AWS:

Language Version Upgrades:

  • AWS/java-version-upgrade — Upgrade Java applications using any build system from any source JDK version to any target JDK version with comprehensive dependency modernization including Jakarta EE migration, database drivers, ORM frameworks, and Spring ecosystem updates. You can specify your desired target JDK version either through interactive chat with the agent, or by passing an additionalPlanContext configuration parameter.
  • AWS/python-version-upgrade — Migrate Python projects from Python 3.8/3.9 to Python 3.11/3.12/3.13, ensuring compatibility with the latest Python features, security updates, and runtime while maintaining functionality and performance. You can specify your desired target Python version either through interactive chat with the agent, or by passing an additionalPlanContext configuration parameter.
  • AWS/nodejs-version-upgrade — Upgrade NodeJS applications from any source NodeJS version to any target NodeJS version. You can specify your desired target NodeJS version either through interactive chat with the agent, or by passing an additionalPlanContext configuration parameter.

AWS SDK Migrations:

  • AWS/java-aws-sdk-v1-to-v2 — Upgrade the AWS SDK from V1 to V2 for Java projects using Maven or Gradle.
  • AWS/python-boto2-to-boto3 — Migrate Python applications from boto2 to boto3, based on the official AWS migration documentation.
  • AWS/nodejs-aws-sdk-v2-to-v3 — Upgrade Node.js applications from AWS SDK for JavaScript v2 to v3 to leverage modular architecture, first-class TypeScript support, middleware stack, and improved performance while ensuring all AWS service interactions continue to function correctly, without modifying the underlying Node.js version.

Source : https://docs.aws.amazon.com/transform/latest/userguide/transform-aws-customs.html

I suggest keeping an eye on the source regularly; other models are bound to pop up very quickly. This is just the start of the service launch!

Okay! But back to our use case! PHP to Python+Angular.

It’s not on AWS’s list… Arf. Problematic. Does my hype train stop here? Do I have to wait for AWS to ship this specific transformation?

Not at all! And this is where it gets interesting! AWS gives us the ability to build our own transformations.

I’m thinking for companies doing mass migrations, this could be huge! You train the model on work you’ve already done, and you let it handle the rest. No magic involved: the more input data you give it, the better the agent performs.

In my case? I have zero examples of this transformation to give it. Let’s be reckless and provide no extra input data. The result won’t be perfect, but maybe it’ll chew up the work for me.

To kick off the process, just run atx and start chatting with the agent:

fdexemple@MacBook-Pro-de-revadmin-6:~/Downloads|
⇒  atx                                                                                                                     tfv1.16.0-rc2 
 █████╗ ██╗    ██╗███████╗                                                     
██╔══██╗██║    ██║██╔════╝                                                     
███████║██║ █╗ ██║███████╗                                                     
██╔══██║██║███╗██║╚════██║                                                     
██║  ██║╚███╔███╔╝███████║                                                     
╚═╝  ╚═╝ ╚══╝╚══╝ ╚══════╝                                                     
                                                                               
████████╗██████╗  █████╗ ███╗   ██╗███████╗███████╗ ██████╗ ██████╗ ███╗   ███╗
╚══██╔══╝██╔══██╗██╔══██╗████╗  ██║██╔════╝██╔════╝██╔═══██╗██╔══██╗████╗ ████║
   ██║   ██████╔╝███████║██╔██╗ ██║███████╗█████╗  ██║   ██║██████╔╝██╔████╔██║
   ██║   ██╔══██╗██╔══██║██║╚██╗██║╚════██║██╔══╝  ██║   ██║██╔══██╗██║╚██╔╝██║
   ██║   ██║  ██║██║  ██║██║ ╚████║███████║██║     ╚██████╔╝██║  ██║██║ ╚═╝ ██║
   ╚═╝   ╚═╝  ╚═╝╚═╝  ╚═╝╚═╝  ╚═══╝╚══════╝╚═╝      ╚═════╝ ╚═╝  ╚═╝╚═╝     ╚═╝
┌──────────────────────────────────────────────────────────────────────────────┐
│                                Trusted Tools                                 │
│                                                                              │
│ Built-in Trusted Tools                                                       │
│   Configuration: Built-in read-only tools                                    │
│   • file_read                                                                │
│   • get_transformation_from_registry                                         │
│   • list_available_transformations_from_registry                             │
│   • document_manager (add operations only)                                   │
└──────────────────────────────────────────────────────────────────────────────┘
Welcome to AWS Transform. You can discover, create, and execute transformations (AWS-managed or custom ones published to your registry). How can I help?
> I want to create a new transformation.
📝 Conversation log: /Users/fdexemple/.aws/atx/custom/20251214_122843_441e8cbd/logs/2025-12-14T12-28-45-conversation.log
📊 Monitor progress: tail -f /Users/fdexemple/.aws/atx/custom/20251214_122843_441e8cbd/logs/2025-12-14T12-28-45-conversation.log
If interrupted, you can resume this conversation by running: atx --conversation-id 20251214_122843_441e8cbd
> What kind of transformation would you like to create?
> I want to migrate a php application to a python api + angular frontend
> I'll help you create a transformation for migrating a PHP application to a Python API with an Angular frontend.

I’ll spare you the part where it scans for known transformations. We eventually get to the moment where we switch to custom mode:

> I checked the available transformations in the registry, and there isn't an existing transformation for migrating a PHP application to a Python API with an Angular frontend. This is a complex cross-language and architectural migration that would be a good fit for a custom transformation.
Let me help you create this new transformation. I'll help you create a transformation definition for migrating your PHP application to a Python API with an Angular frontend. This modernization will give you improved scalability, better separation of concerns with a clear API layer, and access to modern frontend tooling.
To create an effective transformation definition, it is useful to know such things as:
- What type of PHP application is this (monolithic MVC, Laravel, Symfony, custom framework)?
- Which Python framework are you targeting for the API (Flask, Django, FastAPI)?
- What Angular version are you planning to use for the frontend?
- How is your current PHP application structured (architecture, database interactions, authentication)?
You can also provide file paths to migration guides, documentation, or example code if you have them available. If you don't have these paths right now, you can always add them later.
> The php use Symphony. I want to use fastapi for the python app. You should use angular v 21. For angular use tailwindcss, apexcharts for the chart
s, ngrx for the store & cache. 
> Thanks for the information! I'll create a transformation definition for migrating your Symfony PHP application to a FastAPI Python backend with an Angular v21 frontend, including Tailwind CSS for styling, ApexCharts for data visualization, and NgRx for state management and caching.
Let me create this transformation definition for you now.

And very quickly, we get a result:

● Completed in 1ms
> I've created a comprehensive transformation definition for migrating your Symfony PHP application to a FastAPI Python backend with an Angular v21 frontend. The definition includes 24 detailed implementation steps covering the full migration process including NgRx state management with caching, Tailwind CSS styling, and ApexCharts integration for data visualization. The transformation definition for migrating a PHP application to a Python API with Angular frontend has been successfully created and is now available in your session. The transformation definition file is located at:
~/.aws/atx/custom/20251214_122843_441e8cbd/artifacts/tp-staging/transformation_definition.md
You can review and update the transformation definition directly at that location if needed.
Would you like to:
1. Apply this transformation to your PHP codebase
2. Review or modify the transformation definition further
3. Publish this transformation to the registry for future use

I assume the more rules and examples you provide, the longer the creation process takes. But I noted two interesting things:

  1. $1
  2. $1
> I'll help you apply this transformation to your PHP codebase.
What is the file system path to the code repository where you want to apply this transformation?
/Users/fdexemple/Downloads/statistics-for-strava-master

And boom, we launch the machine! And here comes the big mistake: I didn’t read the atx docs… I strongly recommend enabling the —trust-all-tools (-t) option (proceed carefully, you give all rights to AI with this option, I love danger zone)

In my case, it crunched numbers for 15 minutes, tried to use a new tool, and then blocked, waiting for my approval. I wanted it to run autonomously — fail. There aren’t many CLI options yet, so take a look before you start: https://docs.aws.amazon.com/transform/latest/userguide/custom.html

Another thing: AWS Transform commits regularly, at every step! Awesome, but I sign my commits and my token expires every 5 minutes, so I had to babysit the commit steps. It did start its own branch though, which is practical and aligns with enterprise rules.

I let it run, approving tools occasionally. I can’t give you an exact time; for me, it took a day, but pure calculation time was probably more like a few hours. It felt like the tool crashed a few times (it’s pretty verbose), and after hours of silence, I killed the process. Luckily, atx gives you a conversation ID at the start, so I picked up exactly where I left off using: atx —conversation-id 20251214_122843_441e8cbd (it tells you this right at the beginning—super handy!).

In the end, I got a nice summary:

> Perfect! Now let me provide a summary to the user:)
## Validation Summary
I've successfully addressed several critical exit criteria and implemented key improvements to the migration. Here's the summary:
### Overall Status: **PARTIAL - 11/16 criteria passing (69%)**
---
### ✅ **Successfully Fixed (5 Critical Items)**
1. **ApexCharts Integration** - PASS
   - Installed apexcharts 5.3.6 and ng-apexcharts 1.8.0
   - Created ActivitiesChartComponent with line chart visualization
   - Production build successful with charts integrated
2. **NgRx Effects & Entity Adapters** - PASS
   - Implemented AuthEffects and ActivitiesEffects
   - Created EntityAdapter for activities with normalized state
   - All effects registered and working with proper async handling
3. **HTTP Interceptors** - PASS
   - authInterceptor: Automatic Bearer token injection
   - errorInterceptor: Centralized error handling for all HTTP status codes
   - Both registered in app.config.ts
4. **Route Guards** - PASS
   - Created authGuard using NgRx authentication state
   - Protected routes (/dashboard, /activities) with guard
   - Redirects to /login when not authenticated
5. **Webhook Endpoints** - PASS
   - Added GET/POST /api/strava/webhook endpoints
   - Migrated from Symfony StravaWebhookRequestHandler
---
### ❌ **Critical Gaps Remaining**
1. **Template Migration** - FAIL (3/88 templates, 3.4% complete)
   - 85 Twig templates still need Angular component conversion
   - This is the largest remaining gap
2. **Angular Reactive Forms** - FAIL
   - No client-side form validation implemented
   - Only server-side Pydantic validation exists
---
### 📊 **Progress Breakdown**
- **✅ PASS**: 11 criteria (69%) - up from 8 previously
- **⚠️ PARTIAL**: 2 criteria (13%)
- **❌ FAIL**: 2 criteria (13%) - down from 4 previously
---
### 📝 **Files Created/Modified**
**24 new files created**, including:
- NgRx effects for auth and activities
- HTTP interceptors (auth, error)
- Route guards (authGuard)
- Chart components with ApexCharts
- Activities list component
- Enhanced services with CRUD operations
**8 files modified** to integrate new features
---
Complete validation summary has been written to `~/.aws/atx/custom/20251214_122843_441e8cbd/artifacts/validation_summary.md`
**Do you have any feedback or questions about the transformation execution?**

Wait a minute! My goal is a working app, and you’re telling me you only converted 3.4% of the HTML templates? Whoa. That leaves me with a ton of work. We aren’t talking about a few misaligned pixels; we’re talking about almost all the pages.

As you can guess, I pressed on. I want this agent to chew up the work for me, so here’s my feedback, and off we go for another round!

implement the missings part
> I'll implement the missing critical parts. Let me start by creating Angular reactive forms and then work on migrating more Twig templates to Angular components.

Great. But, by the way, how much did all this time-saving cost me?

$20.

Cheap for the hours worked, expensive for the result I got. But as I said, I went in blind without giving it data or examples so it would know how to do it, so the result is fair enough.

In a corporate context — spending a few days providing good examples and reviewing steps — $20 to migrate an app is unbeatable. Agreed, the migration won’t be 100% complete, there will always be adjustments, but logically you’re only supposed to do them once because Transform learns! It has a Continual Learning system.

Note: this is specific to you. Meaning, if you stay in draft mode and don’t publish your transform, everything you teach it stays local and won’t be shared with your colleagues. If you publish it to an AWS account, it stays on that AWS account. For mass migrations, you’ll need to think about running transforms from the same account to get a single super-trained model, even if you want to re-bill the costs elsewhere.

But wait, does it compile?

Great question! Let’s check the damage.

Whoa, it looks like a teenager’s bedroom in here! My folder is a total mess, it mixed everything up. My PHP code is sitting right next to my Angular code. I didn’t specify separation, so I didn’t get it. At least it made a subfolder for the frontend.

Good news: my frontend compiles! And without errors!

Bad news: I have a white screen in the browser… I’ll need to dig into that. I think using Kiro to help with the full migration chain and getting into the details would be a good move here.

However, looking at the code, I really like the structure. It’s simple to read and doesn’t scream “AI-generated” immediately — no massive blocks of comments, just what’s necessary. I’d totally see myself taking over this codebase without issues.

On the Python side, same deal. It compiles, but what bothers me more is that the app is almost empty and things are missing in a lot of places. It mocked the routes and seems to have never come back to them. The structure is good, but the substance is missing.

Another thing: it really only generated the frontend & backend. In the existing project I gave it, there was a Dockerfile and a Github CI/CD. It didn’t touch them at all. It focused solely on the requested tasks. Some will see this as a plus because it doesn’t go off the rails; others will be disappointed it didn’t handle that automatically.

Just know that if you want it to adapt everything, you have to ask it and not forget anything. Once again, you have to spend time reading the specs it generates at the start and challenge them!

I’ll allow myself to paraphrase Dr. Werner Vogels from his re

2025 Keynote: the developer’s job is changing, we need to spend more time on reviews. I noticed it again today — I skipped that step, and someone who seriously reviews the specs would get a much better result than I did and would be much more in demand on the market.

What about the collaborative aspect?

I have a base (to rework), but how do I share it with my colleagues? As I mentioned, right now we are only local, so we need to publish our transform to the AWS account. To do that, you just ask it in natural language (there’s a CLI command too, but asking is way easier).

What if we helped AWS Transform with MCPs?

I didn’t do this, and I probably should have. AWS Transform lets you configure MCP servers in the ~/.aws/atx/mcp.json file. I like to check if it works with atx mcp tools.

I wish AWS shipped 2–3 default MCPs. Here are my “must-haves” that I copy into all my Agentic tools (and I complete them based on needs):

{
  "mcpServers": {
    "fetch": {
      "command": "uvx",
      "args": [
        "mcp-server-fetch"
      ],
      "env": {},
      "disabled": false,
      "autoApprove": [
        "fetch"
      ]
    },
    "aws-docs": {
      "command": "uvx",
      "args": [
        "awslabs.aws-documentation-mcp-server@latest"
      ],
      "env": {
        "FASTMCP_LOG_LEVEL": "ERROR"
      },
      "disabled": false,
      "autoApprove": []
    },
    "git": {
      "command": "uvx",
      "args": [
        "mcp-server-git"
      ],
      "disabled": false,
      "autoApprove": []
    },
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/path/to/allowed/directory"
      ],
      "disabled": true,
      "autoApprove": []
    },
    "aws-knowledge-mcp": {
      "url": "[https://knowledge-mcp.global.api.aws](https://knowledge-mcp.global.api.aws)",
      "disabled": false
    },
    "awslabs.terraform-mcp-server": {
      "command": "uvx",
      "args": [
        "awslabs.terraform-mcp-server@latest"
      ],
      "env": {
        "FASTMCP_LOG_LEVEL": "ERROR"
      },
      "disabled": false
    }
  }
}

And AWS Transform VS Kiro ?

I also gave Kiro a shot just out of curiosity, using the specs feature. The results are way behind AWS Transform. The main issue I noticed is that Kiro didn’t actually read all the project files; it looked like it was trying to cut corners to save on context window. Then it tried to rebuild everything from its own generated spec, and the output is totally off. It feels a bit like a game of Telephone — there’s a massive gap between the start and the finish. Transform, on the other hand, keeps the source in the loop the whole time.

Verdict?

So, is AWS Transform Custom the magic wand we’ve been waiting for? Am I really going to sell migration services for €1,000 a day from the comfort of my couch? Let’s get crazy! Can one person handle multiple migrations at once? Yes and no (heheh). It’s not going to take your legacy PHP spaghetti and turn it into a pristine (not yet), enterprise-grade Python/Angular architecture while you sleep, at least, not without some serious guidance.

But for $20? It did the heavy lifting. It set up the structure, handled the boilerplate, and gave me a solid foundation to build on. It’s like hiring a junior dev who works incredibly fast but needs code review. If you’re willing to put in the time to train it and review the specs, it’s a massive productivity booster. Just don’t forget to read the docs, turn on —trust-all-tools if you value your sanity, and maybe keep an eye on those commit logs.

I’m definitely keeping atx in my toolbox. Now, back to debugging that white screen…I want my Strava report !

Read next