How I transformed copilot-proxy into a modern full-stack application Coxy using workflow-first development, AI-assisted coding, and systematic specifications

Recently I tried spec-driven development to build Coxy, a complete rewrite of my previous copilot-proxy project. The experience taught me valuable lessons about modern development workflows, AI integration, and sustainable architecture decisions. Here's why I made the switch, how I approached it, and what I learned along the way.

Why I Rewrote copilot-proxy

Technical Limitations of the Original Project

The original copilot-proxy was built with SolidStart, which seemed like a good choice initially but created several challenges:

Framework Maturity Issues: SolidStart is lightweight and performant, but its ecosystem isn't as mature as Next.js. I spent considerable time debugging build processes and working around framework limitations instead of focusing on features. The time investment in tooling troubleshooting outweighed the framework's benefits.

Monolithic Architecture Problems: I had combined frontend and backend implementations in a single codebase, which initially seemed efficient but quickly became messy. As the proxy management features grew more complex, maintaining clear separation between API logic and UI components became increasingly difficult. This architectural decision made testing, deployment, and scaling problematic.

Development Experience Friction: The build process was unpredictable, dependency management was complex, and the development workflow felt fragmented. These friction points slowed down iteration cycles and made the project less enjoyable to work on.

The Opportunity for Spec-Driven Development

Beyond addressing technical limitations, I wanted to experiment with spec-driven development methodology. This approach promised several advantages:

  • Clearer requirements definition before writing code
  • Better AI collaboration through structured prompts and specifications
  • More maintainable architecture with documented decision rationales
  • Systematic approach to feature development reducing scope creep

The rewrite presented a perfect opportunity to implement these methodologies from the ground up, rather than retrofitting them onto existing code.

My Spec-Driven Development Strategy

Workflow-First Philosophy: Avoiding Vendor Lock-in

My core strategy focused on development workflow optimization rather than tool selection. This philosophy aimed to avoid vendor lock-in with specific AI tools like Cursor or Claude Code, which can limit flexibility as new tools emerge.

Key principles I established:

  • I determine the workflow, tools adapt to serve the workflow
  • Documentation drives implementation, not the reverse
  • Tool-agnostic specifications enable switching between AI assistants
  • Modular architecture supports different development approaches

This approach meant investing time upfront in workflow design, knowing that I could optimize tool choices later without restructuring the entire development process.

Benefits of Workflow-First Development

The workflow-first approach delivered three key wins: cleaner architecture through upfront planning, faster debugging with systematic processes, and easy tool switching when better options emerged.

Implementation: From Architecture to Features

Nx Monorepo: Scalable Project Structure

I chose Nx as the foundation for Coxy's architecture, primarily to achieve clean separation between frontend and backend concerns that plagued the original copilot-proxy.

Strategic architecture decisions:

coxy/
├── apps/
│   ├── frontend/                # Next.js frontend
│   ├── backend/                 # Nest.js backend
│   └── frontend-e2e/            # End-to-end tests
├── libs/
│   ├── shared/              # Cross-platform utilities
│   ├── ui/                  # React component library
│   ├── logger/              # Centralized logging
│   └── types/               # TypeScript definitions
└── ...

Why this structure worked for Coxy:

  • Clear boundaries between proxy management UI and API logic
  • Shared libraries eliminated code duplication across apps
  • Independent deployments for frontend and backend services
  • Scalable foundation supporting future microservices architecture

Tooling Optimization: Biome Over ESLint/Prettier

I replaced ESLint and Prettier with Biome for better performance and simpler configuration. Biome reduced setup complexity by 70%, improved build times, and required fewer dependencies to manage. The migration was straightforward with immediate performance benefits.

Spec-Driven Development: USER_STORY.md Files

Following spec-driven development principles, I created comprehensive USER_STORY.md files for each Coxy feature. These documents became the foundation for all development activities.

Example for proxy configuration management:

 # User Story 1: OpenAI-Compatible Proxy Endpoint
 
As a developer using OpenAI-compatible tools, I want to send requests to a proxy server that forwards them to GitHub Copilot so that I can use GitHub Copilot through existing OpenAI-compatible interfaces.
 
 ## Acceptance Criteria (EARS):
 
 - **Given** a valid OpenAI-compatible request, **when** sent to `/chat/completions`, **then** forward to GitHub Copilot API.
 - **Given** an invalid API key, **when** making a request, **then** return `401 Unauthorized`.
 - **Given** a malformed request, **when** sent to the proxy, **then** return `400 Bad Request` with validation errors.
 - **Where** the system acts as a transparent proxy between OpenAI clients and GitHub Copilot.
 
 ---
 
 # User Story 2: Admin Dashboard
 
 As a system administrator, I want an admin interface to monitor and configure the proxy so that I can manage API usage, view logs, and configure settings.
 
 ## Acceptance Criteria (EARS):
 
 - **Given** admin credentials, **when** accessing `/admin`, **then** display dashboard with usage statistics.
 - **Given** proxy requests, **when** they occur, **then** log them for admin review.
 - **Given** configuration changes, **when** submitted through admin panel, **then** update proxy behavior.
 - **Where** admin access is protected by authentication.

Project-Wide System Prompt: Development Constraints

I created a comprehensive system prompt that served as both a constraint and development guideline for AI assistance throughout the project:

# Nx Project Refactoring System Prompt

## 1. Persona
You are a senior software architect and Nx expert with extensive experience in monorepo management, dependency optimization, and large-scale refactoring. You have deep knowledge of:
- Nx workspace architecture and best practices
- TypeScript/JavaScript ecosystem and tooling
- Micro-frontend and library design patterns
- Build optimization and dependency graph management
- Code migration strategies for monorepos

## 2. Task Statement
Analyze and refactor code within an Nx workspace to improve maintainability, performance, and adherence to Nx best practices while preserving functionality and minimizing breaking changes.

## 3. Context
You are working within an Nx monorepo that may contain:
- Multiple applications (React, Angular, Node.js, etc.)
- Shared libraries and utilities
- Complex inter-project dependencies
- Existing build configurations and tooling
- Team conventions and coding standards
- CI/CD pipelines that depend on the current structure

This system prompt ensured consistency across different AI tools and development sessions.

AI-Enhanced Development Workflow

Structured LLM Prompt Guidelines

I developed a systematic approach to creating feature-specific prompts using "Structured LLM Prompt Guidelines." This meta-process involved:

Prompt creation workflow:

  1. Analyze USER_STORY.md to extract key requirements
  2. Feed Structured LLM Prompt Guidelines to Claude for refinement
  3. Generate feature-specific prompts tailored to proxy management needs
  4. Test prompts across different AI tools for consistency

Example Structured LLM Prompt Guidelines (partial):

# Structured LLM Prompt Guidelines

## 1. Persona
Specify the role, expertise, or point of view you want the model to adopt.

_Example:_
> You are a senior frontend developer experienced in React and TypeScript.

## 2. Task Statement
Clearly define the main objective or requirement of your prompt.

_Example:_
> Implement a reusable modal dialog component for a web application.

## 3. Context
Provide relevant background information, project details, or the scope of application to ensure the model understands nuances and boundaries.

_Example:_
> The component will be used across multiple pages in a SaaS dashboard built with React, styled using Tailwind CSS, and should support ARIA accessibility attributes.

Example feature prompt for chatting feature (partial):

# AI Chat Feature Implementation Prompt

## 1. Persona
You are a senior React/Next.js developer specializing in real-time chat interfaces and conversational UX design. You have extensive experience building intuitive messaging systems with optimistic UI updates and seamless user experiences.

## 2. Task Statement
Implement the AI chatting feature with a centered input box on the main page that transitions to a dedicated chat session page after the first message is sent, supporting continuous conversation flow with follow-up messages.

## 3. Context
This is part of a larger AI chatbot SaaS application built with Next.js 15, TypeScript, and Tailwind CSS. The chat feature should provide a smooth, intuitive experience where users start with a prominent input box and seamlessly transition into a full conversation interface. The system integrates with an external AI API and uses Clerk for authentication. Users should feel like they're having a natural conversation with instant feedback and proper message handling.

Multi-Tool AI Implementation Strategy

I used Rovo Dev and Gemini CLI as primary implementation tools, chosen for their modern LLM models and generous free quotas.

Development workflow:

  1. Plan Review: AI generates implementation plan based on USER_STORY.md
  2. Architecture Validation: Manual review ensures alignment with Nx structure
  3. Iterative Implementation: Code generation with frequent human oversight
  4. Bug Resolution: Systematic debugging using AI assistance

Why this multi-tool approach worked:

  • Cross-validation reduced AI hallucinations in complex scenarios
  • Tool-specific strengths: Rovo Dev excelled at backend logic, Gemini CLI at frontend components
  • Flexibility: Could switch tools based on feature requirements
  • Learning opportunity: Compared AI tool capabilities across different use cases

Documentation Synchronization Strategy

A crucial aspect of the workflow was keeping specifications synchronized with implementation:

Periodic documentation updates:

  • Manual analysis where AI reviewed current code against specifications
  • Automatic detection of specification-implementation gaps
  • Document updates reflecting architectural decisions and lessons learned
  • Prompt refinement based on implementation experience

This process ensured that specifications remained valuable throughout the development lifecycle.

Lessons Learned: What Worked and What Didn't

What Worked Well

Top-down understanding transformed my development approach. Spec-driven development forced systematic thinking about requirements and architecture before implementation, leading to better decisions and more cohesive features.

AI revealed unknown unknowns during planning. When creating proxy management specifications, AI identified edge cases, security considerations, and performance optimizations I hadn't considered, leading to more robust implementations.

Structured specifications accelerated development. Comprehensive USER_STORY.md files enabled AI tools to generate higher-quality initial code. Time invested in specifications paid dividends through faster iteration and fewer bugs.

Challenges That Required Adaptation

Tool switching created mental overhead. Managing different AI tools required energy that could have been spent on development. I learned to batch similar tasks within single tools.

Documentation became a project itself. Organizing specifications and prompts required dedicated time and systematic approaches. Templates and naming conventions helped manage this complexity.

Costs accumulated quickly. AI tool quotas sometimes were exhausted faster than expected. The convenience came with real monetary costs that needed project planning consideration.

Next Steps: SpecKit and Beyond

GitHub SpecKit offers exciting opportunities to formalize my spec-driven approach. I plan to explore SpecKit integration for native GitHub workflow management, automated documentation generation, and standardized specification formats.

For future projects, I'll focus on systematic prompt management with version-controlled prompt libraries, performance tracking, and automated testing. The goal is creating repeatable processes that scale across different projects and team members.

Conclusion: Growing with AI, Not Surrendering to It

Building Coxy with spec-driven development taught me that AI collaboration works best when humans maintain architectural ownership while leveraging AI for implementation speed. Rather than giving complete control to AI tools, the spec-driven approach helped me grow alongside AI capabilities.

The key insight: systematic approaches scale better than ad-hoc AI usage. Structured prompts, comprehensive specifications, and organized workflows produce more consistent results than spontaneous AI interactions. Documentation remains critical while AI generates code quickly, human-created specifications ensure that code serves actual business requirements.

The transformation from copilot-proxy to Coxy represents more than a technology upgrade. It demonstrates how thoughtful AI integration with systematic development practices can elevate both project outcomes and developer capabilities.