DEV Community

Jorge Gomez
Jorge Gomez

Posted on

๐Ÿš€ How I Used AI, FRDs, Claude Sonnet, Windsurf, and Antigravity to Orchestrate a Complete Backend Without Chaos

A Reproducible Methodology for Generating Real, Clean, and Scalable Software Using LLM Agents Orchestrated Through Formal FRD Documents

Introduction

Over the past few weeks, Iโ€™ve been applying a development approach based on FRDs (Functional Requirements Documents) orchestrated with the support of Artificial Intelligence to build modern, clean, and scalable backends. This method allowed me to generate a complete backendโ€”from CRUD, database layer, JWT authentication, migrations, and unit testingโ€”without chaos, without improvisation, and with clean code from the very first commit.

Although FRDs are a traditional standard widely used in software engineering, whatโ€™s truly interesting here is not the FRD concept itself, but how FRDs are combined with LLM agents to create a deterministic build process.

This approach aligns with modern techniques such as LLM Orchestration, Task Graphs, and Agentic Pipelines, which are becoming mainstream in tools like Windsurf, Cursor, Claude Sonnet, and VSCode Agents.

One key insight I found early on was that I initially started with a massive FRDโ€”a single document describing all phases (boilerplate, database, authentication, testing, etc.). Even though the document was detailed, two real problems quickly emerged:

  1. LLMs had to process too much information in a single context window, increasing reasoning load and causing the agent to drift, forget steps, or ask redundant questions.
  2. The process became slow because the model entered loops of โ€œconfirmation,โ€ uncertainty, ambiguity, and frequent re-validation.

This led me to investigate a more scalable approach: splitting the project into multiple small FRDs, each responsible for a specific phase, and introducing a Master FRD-00 responsible for orchestrating them in the correct order.

With this structure:

  • The LLM no longer needs to parse a giant document
  • Each stage has a short, precise FRD
  • The Master FRD controls the entire execution pipeline
  • The agent stops asking โ€œwhatโ€™s nextโ€ and simply executes
  • Adding new features becomes safer and easier because each one lives in its own FRD without interfering with others

What Is FRD-Based Orchestration?

FRDs define:

  • What needs to be built
  • In what order
  • What criteria must be satisfied
  • Which steps are mandatory
  • What behaviors the AI must validate
  • What acceptance conditions each phase must pass

The key insight is that youโ€™re not only describing features, youโ€™re also defining the construction process itself, ensuring accuracy, repeatability, and zero improvisation.


๐Ÿ“˜ Connection to Existing Practices

FRD-based orchestration does not try to reinvent methodologiesโ€”it integrates formal, well-known practices with the new wave of AI-assisted development.

This method incorporates ideas from:

  • LLM-driven Development Workflows
  • Prompt Chaining
  • Task Graph Execution
  • Reproducible Pipelines
  • Specification-Driven Engineering

The contribution here lies in how the process is structured, not in the FRD concept itself.


FRD-00: The Orchestration Controller

This master document defines:

  • Required phases
  • Clear dependencies
  • Agent behavior
  • Validation rules per stage
  • Strict conditions to advance or stop
  • Success criteria for each phase

It acts as the logical pipeline that ensures the project can be executed by AI without deviations.

๐Ÿ”— Ruta


๐Ÿš€ How Orchestration Actually Begins

Before starting any phase, I execute this initial instruction so the AI loads all FRDs and understands the execution order:

@FRD-00-master-orchestration.md
@FRD-01-boilerplate-core-products.md
@FRD-02-products-database.md
@FRD-03-auth-security.md
@FRD-04-unit-testing.md 

folder name: api-products

FRD-00-master-orchestration.md
FRD-01-boilerplate-core-products.md
FRD-02-products-persistence-typeorm.md
FRD-03-unit-testing.md

Start the orchestration.

Enter fullscreen mode Exit fullscreen mode

Why Is This Critical?

  • Ensures the agent follows the correct order
  • Enforces FRD-00 as the master controller
  • Reduces context overload
  • Prevents unnecessary loops or clarifying questions
  • Makes the process reproducible across any AI editor: Windsurf, Antigravity, Cursor, Sonnet, VSCode Agents, etc.

General Project Architecture

The final result was a NestJS backend with:

๐Ÿงฉ Included Modules

  • Auth (JWT + bcrypt + Passport)
  • Users (registration, login, hashing)
  • Products (CRUD with validation)
  • Centralized config
  • SQLite + TypeORM + migrations
  • Unit testing (33 tests)

๐Ÿ“ Final Structure

api-products/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ auth/
โ”‚   โ”œโ”€โ”€ products/
โ”‚   โ”œโ”€โ”€ users/
โ”‚   โ”œโ”€โ”€ config/
โ”‚   โ””โ”€โ”€ main.ts
โ”œโ”€โ”€ migrations/
โ”œโ”€โ”€ README.md
โ””โ”€โ”€ package.json
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”ฅ Phase 1 โ€” Boilerplate + In-Memory CRUD

  • Project created using nest new
  • Swagger enabled
  • Global validation pipes
  • In-memory CRUD
  • DTOs with class-validator
  • Mandatory JSDoc
export class CreateProductDto {
  @IsString()
  name: string;

  @IsBoolean()
  isPremium: boolean;

  @IsNumber()
  price: number;
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”— Ruta


๐Ÿ—„๏ธ Phase 2 โ€” Database + TypeORM

  • TypeORM integration
  • Migrations
  • ProductRepository
  • Real persistence using SQLite
@Entity()
export class Product {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column()
  name: string;

  @Column()
  isPremium: boolean;

  @Column('float')
  price: number;
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”— Ruta


๐Ÿ” Phase 3 โ€” JWT Authentication

  • UsersService + repository
  • bcrypt hashing
  • LocalStrategy + JwtStrategy
  • JwtAuthGuard
  • Swagger Bearer Auth
  async login(loginDto: LoginDto): Promise<{ accessToken: string }> {
    const user = await this.usersService.validateCredentials(loginDto.email, loginDto.password);

    if (!user) {
      throw new UnauthorizedException('Invalid credentials');
    }

    const payload = { email: user.email, sub: user.id };
    const accessToken = this.jwtService.sign(payload);

    return { accessToken };
  }
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”— Ruta


๐Ÿงช Phase 4 โ€” Unit Testing

  • 6 test suites
  • 33 tests
  • Clean mocks
  • No real database
  describe('login', () => {
    it('should login successfully and return access token', async () => {
      const loginDto: LoginDto = {
        email: 'test@example.com',
        password: 'password123',
      };
      const accessToken = 'jwt-token';
      mockUsersService.validateCredentials.mockResolvedValue(mockUser);
      mockJwtService.sign.mockReturnValue(accessToken);

      const result = await service.login(loginDto);

      expect(result).toEqual({ accessToken });
      expect(usersService.validateCredentials).toHaveBeenCalledWith(loginDto.email, loginDto.password);
      expect(jwtService.sign).toHaveBeenCalledWith({ email: mockUser.email, sub: mockUser.id });
    });

    it('should throw UnauthorizedException for invalid credentials', async () => {
      const loginDto: LoginDto = {
        email: 'test@example.com',
        password: 'wrongpassword',
      };
      mockUsersService.validateCredentials.mockResolvedValue(null);

      await expect(service.login(loginDto)).rejects.toThrow(UnauthorizedException);
      expect(usersService.validateCredentials).toHaveBeenCalledWith(loginDto.email, loginDto.password);
    });
  });
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”— Ruta


๐Ÿ“Š Final Results

  • All 33 tests passing
  • Migrations working
  • JWT fully functional
  • CRUD operational
  • Consistent architecture

๐Ÿ–ผ๏ธ Visual Evidence

(Gallery with screenshots from Windsurf, Antigravity, and Claude Sonnet)


๐Ÿง  Why This Matters in the AI Era

  1. AI needs structure
  2. Enables end-to-end project execution
  3. Reinforces best practices in LLM-assisted development workflows.
  4. Reproducible, scalable, modular

๐Ÿงญ Conclusion

FRD Orchestration is not merely an operational techniqueโ€”it is a way of structuring collaboration between humans and AI models to produce reproducible, stable, and scalable software.

This method enhancesโ€”not replacesโ€”the developer.

๐Ÿ“‚ Official Repository with FRDs + Full Backend


`

Top comments (0)