Skip to main content
Building with AI (Vibe Coding)

⏱ About 20 min20 XP

Connecting the Pieces

Almost every meaningful application is built from multiple components that must work together: a user interface that displays data fetched from a server, a server that reads and writes a database, a notification system that triggers when a record changes. Each component may work perfectly in isolation. The moment you try to connect them, a new class of problem appears — not bugs inside a component, but failures at the boundaries between components. This lesson is about those boundaries.

Interfaces: The Contract Between Components

An interface (in the architectural sense used here) is an explicit agreement between two components about how they will communicate. It specifies: - What the caller sends: the name, type, and constraints of every input. - What the callee returns: the structure, type, and possible values of every output. - What happens on error: how failures are communicated back to the caller. Interfaces must be defined before either component is built — not discovered after the fact by reading the code. When two components are built to separate, pre-agreed interfaces, connecting them is straightforward. When they are built without such an agreement, connecting them requires reading both implementations, finding the mismatches, and fixing them — a much slower and more error-prone process. Concrete example: consider a front-end component that displays a list of expenses and a back-end route that fetches them. The interface between them might read: Request: GET /expenses?month=2026-04 Response (success, HTTP 200): { status: "ok", data: [ { id: string, amount: number, category: string, date: string, note: string | null } ] } Response (error, HTTP 500): { status: "error", message: string } With this interface agreed on, the front-end developer and the back-end developer (or the two separate prompting sessions that build them) can work independently without coordination beyond the interface itself.

An Interface Is a Contract

An interface between components is a legally binding contract in the software sense: both sides must honor it. If the back-end returns amount as a string but the front-end expects a number, the contract is broken — and the failure will appear as a runtime error, not a compile-time warning. Reviewing interfaces before building implementations is the cheapest time to find and fix mismatches.

When connecting components in practice, the integration phase has three steps: Step 1 — Verify the interface on each side. Before writing any connection code, check: does the back-end actually return the format specified in the interface? Does the front-end actually send the request in the format the back-end expects? Do this by reading the code on each side against the written interface specification. Step 2 — Test the connection in isolation. Connect only two components at a time, with the simplest possible data. For a web app, use a tool like curl or Postman to send a test request to the back-end and confirm the response matches the interface. Then connect the front-end to the back-end with a hardcoded test case before adding real data. Step 3 — Identify and fix mismatches. Mismatches are nearly inevitable. The amount field is returned as a string '12.50' but the front-end expects a number 12.50. The date field is returned as a full ISO timestamp but the front-end expects just the YYYY-MM-DD part. Each mismatch must be fixed either in the producer (the component sending the data) or the consumer (the component receiving it) — and that decision should be recorded in your project brief. AI assistance in the integration phase is particularly valuable for writing the small transformation functions that convert data from one format to another. These are tedious to write by hand, well-specified (you know the input format and output format exactly), and straightforward for the AI to generate correctly given precise input and output descriptions.

Complete the sentences about component integration.

An defines what one component sends to another and what it expects in return. A mismatch found after building both components is fixed either in the or the consumer.

Common Integration Failures and How to Prevent Them

Four integration failures appear repeatedly in AI-assisted projects: 1. Type mismatch: one component sends a string, the other expects a number. Prevention: specify types explicitly in every interface definition. 2. Field name mismatch: one component uses 'categoryName,' the other uses 'category.' Prevention: define field names in the interface, not in the components independently. 3. Error-handling gap: a component fails silently (returns null or undefined instead of an error message) and the other component crashes because it receives something unexpected. Prevention: always define the error case in the interface. 4. Timing mismatch: one component assumes the other has already fetched data by the time it runs, but the fetch is asynchronous and may not be complete. Prevention: design interfaces to make asynchronous flow explicit (the component that needs data must wait for the fetch to complete before using the result). Each of these is a design problem, not a coding problem. They are best caught at the interface review stage, before either component is implemented.

Do Not Skip the Interface Review

Developers under time pressure often skip writing interface specifications and jump straight to building components. This feels faster in the moment but is reliably slower overall: integration failures discovered late are much harder to fix than interface mismatches caught before implementation. The AI is especially prone to generating components that assume implicit conventions — so the developer who provides an explicit interface prevents a category of error the AI cannot catch on its own.

Two components are built without a written interface agreement. What is the most predictable consequence?

A back-end route returns { amount: '12.50' } (a string) but the front-end expects { amount: 12.50 } (a number). What kind of integration failure is this?

Interface Specification Workshop

  1. Working in a group of two or three, choose a simple application (a to-do list, a book-review site, a weather dashboard).
  2. Divide the application into exactly three components: a front-end display layer, a back-end logic layer, and a data store layer.
  3. For each boundary between adjacent components, write a complete interface specification:
  4. - List every piece of data that flows across the boundary.
  5. - For each field, specify its name and type.
  6. - Specify what happens when an error occurs.
  7. Now deliberately introduce one mismatch (change a field name or type on one side only) and swap specifications with another group.
  8. The other group must read both specifications and identify the mismatch without seeing the original application description.
  9. Discuss: was the mismatch obvious? What made it harder or easier to spot?