Most web app projects do not fail because the code was bad. They fail because the brief was vague, the scope drifted, and nobody agreed on what "done" meant until the invoice arrived. A good development process exists to make those failures impossible, or at least visible early enough to correct. This is how we run a web app from a first conversation to a live, maintained product, and what you should expect to receive at each stage.
The Five-Phase Arc, and Why Order Matters
A web app moves through five phases: discovery, design, build, QA, and launch, followed by an iteration loop. The phases are not bureaucracy. Each one resolves a class of risk before it gets expensive to fix. A wrong assumption caught in discovery costs an email. The same assumption caught after launch costs a rebuild.
The temptation is always to skip ahead to building because that is the part that feels like progress. Resist it. Code written against an unvalidated assumption is not progress; it is debt with a deadline. The phases below are sequential in their gates but overlapping in practice. Design begins while discovery is still tightening, and QA runs continuously during build rather than waiting at the end.
Phase 1: Discovery — Turning a Brief Into a Plan
Discovery answers one question: what are we actually building, and for whom? You arrive with a brief, a budget, and a hunch. You leave with a shared, written understanding that both sides can be held to.
What good discovery produces:
- A problem statement in one or two sentences, written from the user's point of view, not the feature list.
- A scope document that lists what is in, and explicitly what is out. The "out" list is the more valuable half.
- User stories or jobs-to-be-done prioritized into a must-have core and a later-phase backlog.
- A technical approach: stack, hosting, integrations, and the major architectural decisions with their tradeoffs named.
- A timeline and budget tied to the scope, not to optimism.
The single most useful artifact is the cut line: the explicit boundary between version one and everything that comes after. Features above the line ship first; everything else is parked, in writing, for a later phase. This is where scope creep is prevented, not in a change-control meeting three months later.
How to collaborate here: be honest about constraints. A real budget and a real deadline produce a better plan than aspirational ones. If you have an existing system, give access early. The fastest way to derail discovery is to discover an undocumented legacy integration in week six of build.
Phase 2: Design — Making the Thing Real Before It Is Real
Design takes the discovery plan and makes it concrete enough to react to. It moves in increasing fidelity so that feedback gets cheaper, not more expensive, as you go.
Information Architecture and Flows
Before any pixel is polished, we map the screens and the paths between them. What can a user do, in what order, and where do they get stuck? Flow diagrams and low-fidelity wireframes are deliberately ugly so that conversation stays on structure and not on button colors.
High-Fidelity UI and Design System
Once the structure holds, design moves to high fidelity: the real layouts, typography, color, and components. The deliverable is not a pretty picture but a design system — a set of reusable tokens and components that the build phase implements directly. This is what keeps a fifty-screen app visually coherent and fast to extend.
A practical rule: review designs against the user stories from discovery, not against personal taste. The question is "does this let the user accomplish the job?" not "do I like blue?" Subjective feedback is fine, but flag it as such so it can be weighed differently from a functional gap.
Phase 3: Build — Where Discipline Pays Off
Build is the longest phase and the easiest to get wrong through invisibility. The fix is to ship in thin vertical slices: a working, deployable increment of real functionality every one or two weeks, rather than a big reveal at the end.
We work against a typed contract between frontend and backend so both sides can move in parallel without guessing. Defining the shape of data up front removes an entire category of integration bugs:
// Shared contract: the API and the UI both import this.
// If the shape changes, TypeScript breaks the build, not production.
export interface Project {
id: string; // uuid
ownerId: string;
name: string;
status: "draft" | "active" | "archived";
createdAt: string; // ISO 8601
}
export interface ApiResult<T> {
data: T | null;
error: { code: string; message: string } | null;
}
export type GetProjects = (ownerId: string) => Promise<ApiResult<Project[]>>;A few build-phase principles that consistently pay off:
- Working software over status reports. A staging URL you can click beats a percentage-complete number every time. Ask for one.
- Trunk-based, small commits, continuous integration. Long-lived branches hide divergence until the merge hurts.
- Tests written alongside features, not after. The goal is not 100 percent coverage; it is confidence in the paths that carry money or data.
- Infrastructure as code from day one. Environments should be reproducible, not artisanal.
Handling Change Without Chaos
Requirements will change; that is normal and healthy. The discipline is in how change is absorbed. Every new request is sized against the cut line: it either replaces something of equal weight in version one, or it joins the backlog for a later phase. This single habit — trade, do not stack — is what separates a project that ships from one that expands until the budget runs out.
Phase 4: QA — Proving It Works, Not Hoping It Does
Quality assurance is not a final gate; it is a layer that runs the whole way through. By the time you reach a formal QA pass, most defects should already be caught by automated checks.
| Test type | What it proves | When it runs |
|---|---|---|
| Unit | A function behaves correctly in isolation | On every commit |
| Integration | Modules and the database work together | On every commit |
| End-to-end | A real user journey works in a browser | On merge and pre-release |
| Manual / exploratory | The things automation cannot predict | Before each release |
| Accessibility | The app is usable by everyone | Continuously, audited pre-launch |
End-to-end tests deserve special attention for web apps because they exercise the system the way a user does. A small suite of the critical journeys — sign up, the core action, payment — catches the regressions that actually hurt.
import { test, expect } from "@playwright/test";
test("a new user can sign up and create their first project", async ({ page }) => {
await page.goto("/signup");
await page.getByLabel("Email").fill("[email protected]");
await page.getByLabel("Password").fill("a-strong-password");
await page.getByRole("button", { name: "Create account" }).click();
await expect(page).toHaveURL(/\/dashboard/);
await page.getByRole("button", { name: "New project" }).click();
await expect(page.getByText("Untitled project")).toBeVisible();
});Alongside functional testing, QA covers performance (Core Web Vitals, real-device load times), security (authentication, authorization, input handling, dependency audit), and cross-browser behavior. The deliverable from this phase is a defect log with severities and a clear, agreed-upon bar for what blocks launch versus what ships as a fast-follow.
Phase 5: Launch — A Procedure, Not an Event
Launch should be the least dramatic day of the project because everything that could be rehearsed already was. We treat it as a checklist, run in a deliberate order:
- Pre-launch: production environment provisioned, secrets in a vault and not in code, database migrations tested on a copy of real data, backups and rollback verified.
- Observability ready: error tracking, uptime monitoring, and analytics live before traffic arrives, not after the first incident.
- DNS, SSL, and caching configured and tested, with TTLs lowered ahead of any cutover.
- Go-live: deploy, smoke-test the critical journeys against production, then open the doors. For higher-risk launches, a phased or canary rollout limits blast radius.
- Day-one watch: someone owns the dashboards for the first hours and has a tested path to roll back.
The most common launch failures are not code: they are an expired certificate, a missing environment variable, or a migration nobody ran against production data. The checklist exists to make those impossible.
Phase 6: Iterate — Where the Product Actually Gets Good
Launch is the start of learning, not the end of the work. The iteration loop is short and evidence-driven: ship, measure against the goals set in discovery, talk to users, prioritize, ship again. Analytics and error rates tell you what is happening; user conversations tell you why. A healthy cadence is small, frequent releases rather than rare, large ones — they are less risky and they keep momentum visible. This is also where the parked backlog from discovery comes back into play, now informed by real usage instead of guesses.
What to Expect From a Good Studio at Each Phase
A quick decision list for evaluating whether a process is serving you:
- In discovery: you get a written scope with an explicit out-of-scope list. If not, walk.
- In design: you get clickable prototypes, not just static mockups.
- In build: you get a staging URL and regular working increments, not just status updates.
- In QA: you get a defect log with severities and an agreed launch bar.
- At launch: you get monitoring, backups, and a rollback plan, documented.
- After launch: you own the code, the credentials, and the documentation. Always.
Frequently Asked Questions
How long does it take to build a web app from brief to launch?
A focused version-one web app typically takes eight to sixteen weeks: roughly one to two weeks of discovery, two to three of design, the bulk in build and continuous QA, and a short launch window. Timelines stretch mainly through scope additions and slow feedback, both of which a disciplined cut line and quick review cycles keep under control.
What is the difference between a fixed scope and an agile approach?
Fixed scope locks features, price, and date, trading flexibility for predictability. An agile approach fixes the budget and time, then prioritizes features within them. We usually fix the version-one cut line firmly while running the build agilely inside it, which gives you a predictable launch without freezing decisions you will want to revisit once real users arrive.
How do you stop scope creep without being rigid?
By trading, not stacking. Every new request is welcome, but it is sized against the existing version-one scope: it either replaces something of equal weight or it joins the backlog for a later phase. Change is logged and re-estimated transparently, so the budget and timeline stay honest while the product still adapts to what you learn.
What do I actually own when the project is finished?
Everything. The source code in your repository, the production credentials and infrastructure configuration, the design files, and the documentation needed to run and extend the app. You should never be locked into a studio by missing access. A good handover means another competent team could pick up the project and ship to it.
Do I need a designer if I already know what I want?
Usually yes, but the design phase scales to fit. Even a clear vision benefits from flows and a component system that keep the build consistent and fast. If you arrive with strong existing brand assets, design becomes lighter and faster, but skipping structure entirely tends to surface as rework during build, which is the most expensive place to discover it.
Working with CodeAustral
We build web platforms, AI products, and restaurant and iOS apps for clients worldwide, and we run every one through the process above because it is what consistently ships software that lasts. If you have a brief — even a rough one — send it to us at codeaustral.com/contact. We will tell you honestly what the cut line should be, what version one looks like, and how we would get it live.

