Soloper: compressing the development phase of a mobile-to-web port with GitHub Copilot

Matteo Pietro Dazzi
Matteo Pietro Dazzi
12 May 2026
  • Share

We explore the process put in place to port a React Native healthcare application to a React single-page application (SPA), using GitHub Copilot as the primary accelerator during the build.

Can a single senior developer, paired with an AI coding agent, take on the development phase of porting a large-scale mobile app to the web, work that would traditionally need a frontend team of several engineers? And how fundamental is the Human In The Loop (HITL) in keeping that output production-ready?

In this blog post, we explore the process put in place to port a React Native healthcare application to a React single-page application (SPA), using GitHub Copilot as the primary accelerator during the build. The wider programme had everything you'd expect: design, QA, DevOps, product, and the existing backend that the mobile app already ran on. What changed was the frontend development itself; instead of a team of engineers, one developer carried the port from initial scaffolding through to a working SPA, with Copilot doing the heavy lifting and a human staying firmly in the loop. That developer is the Soloper: solo + developer.

The challenge

The project in question is a mobile application built for the Irish public healthcare system. It allows users to view appointments, healthcare messages, alerts, vaccinations, and other health-related data directly on their smartphones. The mobile app has been in active development over the last couple of years, a complex, multi-party programme involving engineering, design, QA, product, and clinical stakeholders, integrating with a wide ecosystem of backend systems and third-party healthcare services.

At the end of 2025, a new requirement landed: create a web experience that matched the mobile experience, with a go-live planned for June 2026. The backend, the design system, the research, and the product thinking were all already in place; what was needed was the frontend itself.

My first reaction was that this was going to be tight. Six months to deliver a web frontend matching a mobile app of this scope, even with the foundations already in place, is not a small ask. But the more I thought about it, the more I leaned into the constraint rather than away from it: rather than spinning up a full team from day one, I'd take on the initial heavy lift solo by scaffolding the code architecture, establishing the patterns, and driving the bulk of the early build before others joined. The logic was straightforward: with GitHub Copilot doing the heavy lifting on code generation, the bottleneck was no longer raw output; it was decision-making and context. In the early phase of a port like this, when every architectural decision sets a precedent for everything that follows, a single developer working tightly with an AI agent moves faster and more coherently than a team still aligning on conventions.

Let’s walk together through the approach, week by week.

Week 1: extracting reusable code

Before writing a single line of web code, the first step was to identify what could be shared between the existing mobile codebase and the new SPA.

We defined three categories of reusable code:

  • Custom hooks built on top of React Query for async data management;
  • Utility functions containing common business logic (e.g., date formatting, appointment characteristics);
  • Form validation schemas written with Zod and consumed by React Hook Form.

All of this code was moved from the mobile app repository into a new, shared library. The library was built with Vite targeting both the web and the mobile platforms, and tested with Jest simply because the tests had been originally written for React Native with Jest. This is something that can change in the future, but it works for now.

Avoiding barrel files for performance

The only notable challenge during the creation of the new library was configuring Vite to avoid barrel files, but also to avoid the burden for each developer to define the path of every new file that needs to be exported.

A barrel is a file that does nothing but re-export things from other files. Usually, those are named index.*. It’s meant to hide the internal structure of a directory from its consumers.

The reason to force this is straightforward: a test runner (like Jest and Vitest) is not a bundler. It cannot tree-shake unused dependencies, so every time it loads a barrel file, it parses everything that file re-exports, even if the test only needs a single function.

We opted for longer, explicit import paths in exchange for significantly faster test execution. This required a custom Vite configuration that compiles each file individually, preserving the original directory structure in the output.

This entire extraction phase consumed the first week of the project. Out of seven total weeks, one was now spent, and not a single part of the web application had been built yet.

Week 2 to 2.5: bootstrapping the SPA repository

With the shared library in place, we were ready to bootstrap the web portal repository. We opted to use the Vite React SPA TypeScript template and configured the CI pipeline to run the classic install, lint, build, and test commands.

Then came the most important part: configuring GitHub Copilot to actually understand the whole project.

The Copilot instructions file

The .github/copilot-instructions.md file is always included every time Copilot is invoked in VS Code or through remote agents. This file can be seen as the Copilot-specific implementation of the more standardised AGENTS.md file.

Ours contains:

  • A project overview describing what the portal is, what it does, and why;
  • A directive to read the developer agent definition for any development task;
  • Pointers to the README.md, .env.sample, and package.json files for additional context on libraries and their versions.

The reason we force GitHub Copilot to read the developer agent definition from the instructions file is subtle but important: when you open a pull request and ask Copilot to review it, it reads the copilot-instructions.md and the content of the instructions folder by default. If you want the code reviewer to share the same knowledge as the code writer, you have to point it to the same knowledge base.

Some useful examples of this strategy can be found in GitHub Copilot’s documentation.

The developer agent definition

The developer agent file is where the real knowledge lives. Ours is close to 30,000 characters, nearly hitting GitHub Copilot’s length limit. It includes:

  • Detailed project overview: what the application does, who it serves, how the web portal relates to the mobile app, and the existing backend services;
  • Project structure: a Markdown representation of where each type of file is stored and why;
  • Environment configuration: how to define new environment variables and the related rules;
  • Code organisation preferences: a list of naming conventions and coding preferences to follow during the implementation;
  • Testing requirements: snapshot tests for stateless display components, minimum 90% code coverage for each source file;
  • Build and deploy commands: list of commands that the agent can run during the development lifecycle;
  • Pre-commit checklist: a checklist of commands that must be executed before every push to consider the work as done. This is particularly critical for GitHub Copilot’s remote agents, which sometimes push broken code. With the pre-commit requirements in place, the agent iterates over the checklist until everything passes;
  • Troubleshooting tips: suggestions about how to behave in specific scenarios, like when the code coverage value is not met;
  • Additional resources: links to React documentation, Zod documentation and other references that the agent can fetch for up-to-date information.

At this point, we were ready to start delivering something: the repository was ready, the agent was configured, and the shared library was in place.

Week 2.5 to 5: MCP servers and spec-driven development

The scope was growing. Instead of porting only the existing mobile features, we had agreed to also include new functionalities coming with upcoming app releases. To save more time, we had to help the agent produce better code, with fewer errors and fewer rounds of code review: here is our approach.

Configuring MCP servers

We started by configuring Model Context Protocol (MCP) servers, which are external tools that extend the agent’s capabilities.

The full list includes:

  • Atlassian MCP server: allows the agent to look up Jira ticket definitions (including the definition of done) and move them to the correct status once a feature is complete;
  • Figma MCP server: gives the agent access to the Figma files of the mobile application, so it can understand the expected design and port it to the web;
  • Chrome DevTools MCP server: lets the agent inspect the official healthcare website to understand its structure and styling;
  • GitHub MCP server: used to read the source code of the mobile app from its repository;
  • Context7: a real lifesaver. It grabs the package.json, reads the installed version of each library we need to interact with, and retrieves the most recent and LLM-optimised documentation for it. This means the agent generates code aligned with the actual library version, instead of relying on potentially outdated training data;
  • Storybook MCP server: allows the agent to interact with a local Storybook instance to understand the available design system components, the same used by the public healthcare website.

The prompt-per-feature approach

Having been part of the original project for over a year, I knew all the functionalities that needed to be ported. So instead of following a heavy Spec-Driven Development (SDD) framework like BMAD, I created a single prompt file for each functionality: roughly 40 prompts in total.

Each prompt followed the same structure:

  1. Context: we are migrating a mobile app feature to the web portal;
  2. Figma reference: a link to the relevant Figma screens previously made for the mobile app;
  3. Source code reference: a pointer to the existing React Native implementation;
  4. Instructions: instead of immediately diving into the code, the agent had to produce a plan and store it in a different folder.

The plan included:

  • A general overview of the functionality;
  • References to the source code that it analysed;
  • The proposed web design and component architecture;
  • A list of design system components to use;
  • Data fetching strategy;
  • Unit test approach with a description of test cases;
  • An implementation checklist;
  • Technical notes, such as what has been excluded and why.

Two-model strategy: think expensive, implement cheap

The key insight was to separate planning from implementation using different models.

For plan generation, I opted for Claude Opus 4.5. It could take all the MCP context (Figma, GitHub, Storybook, Chrome DevTools) and produce a thorough specification document, thanks to its deeply analytical capabilities. It was slow, but very accurate.

For implementation, I used Claude Sonnet 4.5. Considering that the plan was already a compact, self-contained document that fits within the context window, Sonnet could follow it reliably without needing the same depth of reasoning. It also produced a high-quality output very fast.

This approach was viable for the whole month thanks to the GitHub Copilot Pro+ licence, which provides 1,500 premium requests per month.

Reusable prompts

To avoid copy-pasting the same implementation prompt 40 times, I leveraged GitHub Copilot’s custom prompt feature. By creating .prompt.md files inside the .copilot/prompts folder, you can define reusable slash commands, similar to agent skills.

For example, after generating and reviewing a spec, I would:

  1. Open the spec file in VS Code;
  2. Attach it to a fresh chat with Sonnet;
  3. Run the /implement-spec slash command, forcing the agent to read the following prompt file content:
---
name: implementSpec
description: Implement an attached specification
argument-hint: Provide the specification to be implemented as an attachment
---

Given the attached spec, your duty is to follow it and implement what's defined.
If you have any doubt, ask me instead of making decisions. Use the MCP tools available to grab the additional information you need.
yaml

This small automation saved significant time and reduced the burden of remembering and applying the correct prompt.

Week 5 to 7: wrapping the initial build

The final two weeks of the solo phase focused on getting the codebase into a state where the project could move into its next stage: testing, QA, UI refinement, and bug fixing. This involved:

  • implementing items that had been parked pending design approval, such as error states, skeletons, and similar UI elements;
  • fixing subtle bugs caused by hard-coded business logic in the UI, which was then extracted into the shared library;
  • upgrading every dependency and GitHub Action to its latest version.

Lessons learned: the Human In The Loop

By the end of week seven, the application had a working, end-to-end codebase covering the agreed scope. It was not "done" in any release sense; what followed was a period of testing, bug fixing, UI iteration, accessibility work, and integration validation, with the wider team now engaged. What week seven represented was the handover point: the architecture, patterns, and bulk of the implementation were in place, ready for the project to move from a solo build into a full team delivery.

The brownfield advantage

In scenarios like this, where you are porting an existing application, verbose SDD frameworks can be time-consuming. The existing application’s code is your spec. The agent can read the mobile implementation, cross-reference it with the Figma designs and the design system, and produce a plan that is grounded in reality rather than abstract requirements.

As the project progressed, I noticed the agent no longer needed the Figma reference at all. Once enough components had been built, the LLM could make a perfect match between the mobile implementation and the existing web components. Removing Figma from the prompt saved context tokens and improved the quality of the analysis for more complex features.

Trust, but verify

Even when the agent implements a feature correctly, it tends to create unnecessary CSS classes, redundant wrapper div elements, or overcomplicated component hierarchies. This makes the page slightly slower to load and harder to maintain.

The recommended workflow is:

  1. Generate the prompt;
  2. Generate the plan with the expensive model;
  3. Review the plan by yourself, make some manual changes if needed or ask the model to do them for you;
  4. Generate the code with the cheaper model;
  5. Review the code output;
  6. Optimise the outcome, manually or with the agent;
  7. Commit and start from scratch with the next feature.

The review and optimise steps are non-negotiable. AI can compress timelines dramatically, but a human must still validate the output.

Remote agent considerations

If you use GitHub Copilot remote agents, remember that their execution environment is different from your CI. You’ll want a dedicated setup, using the .github/workflows/copilot-setup-steps.yaml action, to install packages, provide access credentials, and perform any environment-specific configuration.

Request consumption

Depending on how you configure your repository, GitHub Copilot can start a new review every time you push something new: it means burning a premium request from your personal quota every time. Plan accordingly to avoid wasted requests.

The real numbers

The seven-week timeline deserves context. The broader healthcare programme had run for a longer time period, but that timeline included design, planning, customer conversations, UX decisions, and backend API development, all of which were owned by a separate team. What the solo phase compressed was specifically the frontend porting work, not the entire programme.

This distinction matters because it underscores why the approach worked: by the time the frontend build began, the hard decisions had already been made. The specification was not abstract; it was a working mobile app. The design system already existed. The backend APIs were tested and stable. The requirements were clear, validated, and documented.

The solo developer moved quickly, not because of Copilot alone, but because context and clarity were already there to consume.

Final considerations

The approach used in this project demonstrates that strategic use of AI coding agents, combined with focused engineering decisions, can set a foundation for rapid, high-quality development even with a single developer.

The key enablers were:

  • Code reuse: extracting shared logic into a library before writing any web code;
  • Thorough agent configuration: investing time in detailed instructions and agent definitions that act as a persistent knowledge base;
  • MCP servers: extending the agent’s capabilities to access the tools you use the most;
  • Two-model strategy: using expensive models for planning and cheaper models for implementation, to cut the costs;
  • Human In The Loop: reviewing and optimising every output, never trusting the agent blindly, to keep a high-quality output.

Whether you're scaling AI across a 30-person engineering team or compressing a brownfield port with a single developer, the enablers are the same: thorough agent configuration, MCP, two-model strategies, and a human firmly in the loop. If you'd like to talk through how AI-native engineering applies at your scale, reach out to Nearform.

But wait - there's more.

Nearform publishes real-world learnings on data & AI, engineering, and digital strategy - with more merged in weekly.

Insights

Perspectives on AI in engineering, product development, and strategy, for enterprise executives.

Community

Deep dives and tutorials by engineers, for engineers.

Insight, imagination and expertly engineered solutions to accelerate and sustain progress.