Can AI help you build useful apps without settling for slop? This guide shows a human-led workflow for taking a product idea through requirements, feature-level implementation, API design, and verification. I use Orbit, a Slack-style team chat demo, as a case study. You can apply the process to your own product, whether you write code or are still shaping the idea.
My first prompt was simple: “I want to build a Slack clone.” That sentence named a product category. It did not say who the product was for, what the first version had to do, what “done” meant, or which parts could be simulated.
On social media, I often see two absolute claims: AI only builds “slop,” and AI cannot help create applications that reach production. Both claims miss the role of the people building the product. AI can help create useful software when people set the scope, review the changes, test the behavior, and own the release decision. AI-generated code cannot certify itself as production-ready.
Orbit is a demo, not a production application. It has no sign-in, uses one shared public demo owner, and loses stored data when its process restarts. I will show what the AI-assisted workflow produced and what still needs verification before a production release. The prompt examples are teaching examples, not transcripts of the original conversations.
“Slop” is a fair description of output that looks complete but does not meet the user’s needs. A vague request gives an AI room to guess. If no one checks those guesses against real requirements, the result can look polished while behaving like the wrong product.
The process for Orbit added checks at each handoff. ChatGPT helped expose missing decisions. Claude organized the decisions in a PRD and feature specs. Grok Build implemented bounded changes. I reviewed the UI, revised the requirements, and asked for an API audit only after the UI behavior was accepted. Feature acceptance criteria and tests made some results observable.
That work is evidence that AI can contribute to product planning, interface work, API design, and implementation. It does not prove that Orbit is production-ready. The current demo has no sign-in, shared demo data, and process-scoped persistence. The last implementation notes report focused API and compose tests passing, but also note broader baseline failures and a blocked browser journey. The sections below describe both the work and its limits.
The screenshots follow a new visitor from the welcome screen to a channel, a thread, and a direct message.
The welcome screen tells visitors that they share demo data. There is no sign-in. Do not enter private messages. Calls are simulated; they do not carry live audio or video.
The welcome screen explains the shared demo before a visitor enters.
The seeded workspace lets a reviewer see a populated channel at once.
The channel shows the navigation, conversation, and composer in one view.
The thread pane keeps replies beside the message that started them.
A thread is a separate conversation path inside the channel.
Direct messages use the same basic layout with a different recipient and history.
A direct message has its own conversation history.
These screens helped me judge the product's direction. They did not prove that every control behaved as required. I used the feature PRDs and acceptance criteria to review behavior.
“Build a Slack clone” leaves many decisions open. Does the first version need accounts, real-time messages, calls, file uploads, mobile navigation, or search across every message?
If a model answers those questions by guessing, it can build a polished interface for the wrong product. I used ChatGPT to make the missing decisions visible before I asked Claude to write the PRD.
For your own product, replace the chat-specific questions with the users, tasks, data, and risks that matter in your domain. Keep the same method: ask the AI to expose unknowns before it writes a specification.
I want to build a Slack-style team chat app.
Help me clarify the idea before you write a build prompt.
Ask questions about:
- who will use the app and what they need to do;
- the smallest useful first version;
- workspaces, channels, direct messages, threads, and search;
- accounts, data ownership, persistence, and real-time behavior;
- files, calls, mobile use, and accessibility;
- security, edge cases, and features that are out of scope.
Separate confirmed facts, assumptions, recommendations, and open questions.
Do not turn an unanswered question into a requirement.
Do not write code.
When the important questions are answered, write a structured brief I can
give to another assistant to draft a PRD.
The key instruction is to separate what I decided from what the model suggested. If the answer says “accounts are required” but I never chose an account system, that is an assumption to review, not a requirement to pass along.
For a non-technical builder, describe the user and the problem in everyday language. For a technical builder, add the stack, integrations, data boundaries, and deployment constraints. Either way, ask the model to list unanswered questions instead of filling them in.
The document names vary between companies. Teams also combine them. These are common meanings:
The terms are related, but they do not mean the same thing. An SRS is a software requirements specification, not a “software specification requirement.” Formal standards use their own artifact names. ISO/IEC/IEEE 29148 describes requirements engineering across the system and software lifecycle, including business and software requirements specifications.
For Orbit, Claude drafted the product requirements document, and we later created eight feature PRDs. We did not create separate BRD or SRS documents for this project. The feature PRDs and API contract captured the detail we used to build and review the app.
Use the brief below to draft a Product Requirements Document for Orbit.
Include:
1. product problem, users, goals, and success measures;
2. priority user journeys;
3. functional requirements with testable acceptance criteria;
4. non-functional requirements for security, privacy, accessibility,
responsive behavior, and performance;
5. data and integration needs;
6. non-goals, dependencies, risks, and open questions.
For every requirement, mark its source as confirmed, assumed, or proposed.
Do not invent business decisions. Put unresolved choices in an open-questions
section. Use plain language. Do not write code.
A PRD gives the people building the product one description of the user, the goal, and the expected behavior. It also gives the AI a boundary. “Build Slack” is not a boundary.
Once Claude drafted the PRD, I passed it to Grok Build. The first design looked close to what I had in mind. That was a useful checkpoint. It was not a reason to assume that every behavior had been defined.
Read the attached Orbit PRD and the existing project instructions.
First summarize the user, the first-release scope, and the acceptance criteria.
List conflicts and unanswered questions before changing the app.
Build the interface and behavior described in the approved scope.
Keep simulated behavior visibly separate from real persistence or services.
Do not add features because they are common in Slack.
After the change, report what works, what is simulated, what is incomplete,
and which acceptance criteria you could not verify.
The line about features common in Slack prevents scope creep. A clone brief does not automatically include every feature in the original product.
When the first interface looked right, I returned to Claude and asked: “For this application, list out the features.” I turned that list into separate feature PRDs. Then I fed those documents to Grok Build one at a time.
Break the approved Orbit PRD into feature-level PRDs.
For each feature, include:
- user problem and user story;
- in-scope behavior and explicit non-goals;
- normal flow, edge cases, and empty/error states;
- data and permission rules;
- dependencies on other features;
- measurable acceptance criteria.
Keep accessibility and responsive requirements explicit.
Link each feature to the parent PRD requirement.
Flag overlap or conflict. Do not silently resolve it.
Separate the first release from later work.
Each feature needs a clear boundary. For example, “make channel switching smooth” is hard to verify. “When a user selects a channel, update the header, messages, composer placeholder, draft, and active sidebar item together” describes a visible result.
Implement only the attached feature PRD: [feature name].
Before editing, summarize its acceptance criteria and identify the relevant
existing UI and tests. Ask about any conflict with the parent PRD instead of
guessing. Keep unrelated features unchanged.
After editing, report each acceptance criterion as verified, not verified,
or blocked. Show the behavior change and remaining gaps.
Do not claim that a simulated feature uses a real service.
I checked each revision against the accepted requirements before moving to the next feature. That review caught differences between a screen that looked right and a behavior that was actually specified.
The first UI pass had eight feature-level PRDs. They describe UI behavior with local state and no backend. The calls PRD describes simulated calls and excludes WebRTC, signaling, and a media server. It refers to a separate future calls spec. The linked Gist contains only these eight feature PRDs. It does not contain the master product PRD, the later API specification, or the future calls spec.
I extracted the eight Markdown PRDs and published them as individual files in a public GitHub Gist. Select a title below to read the full PRD:
| Feature PRD | What it specifies |
|---|---|
| Layout | Workspace rail, navigation sidebar, conversation pane, and thread pane. |
| Conversation experience | Message rendering, grouping, reactions, threads, and message actions. |
| Composer | Multiline input, sending, formatting controls, attachments, and per-conversation drafts. |
| Navigation and search | Channel and DM switching, search, Activity, Later, and menus. |
| Calls | Simulated personal and group call flows, call states, and call history messages. |
| Sample content | Seeded channels, DMs, threads, reactions, mentions, and work conversations. |
| Responsive behavior | Desktop, medium, and mobile navigation and layout rules. |
| Accessibility | Semantic structure, keyboard use, visible focus, contrast, and edge cases. |
The feature PRDs turn a product goal into work a designer or developer can review. Their acceptance criteria describe outcomes, not just appearance. The responsive spec, for example, says that mobile should show one primary pane at a time and keep the composer reachable when the keyboard is open.
The eight PRDs above describe the initial UI scope. After I was comfortable with the interface and its revisions, I asked ChatGPT to help draft a prompt for a new task: audit what the platform actually did and derive the REST API from those behaviors.
This order matters. The API review started from accepted screens, feature specs, and user actions. It did not start from a list of endpoints or a guess about what Slack might need.
The Orbit interface and feature PRDs have been reviewed and accepted.
Audit the provided screens, PRDs, interaction list, and existing project behavior.
Use only these sources. Do not add features because a competitor has them.
First, inventory each user-visible action and the data it reads or changes.
Group related actions by resource. Do not create one endpoint for every button.
Separate browser-only state from data that must persist on the server.
For each proposed operation, document:
- user outcome and resource;
- HTTP method and versioned URI;
- request and response shape;
- success and error status codes;
- authentication, ownership, and authorization rules;
- validation, size limits, and safe failure behavior;
- idempotency or concurrency needs;
- pagination and ordering rules;
- one observable API behavior test.
Design a resource-oriented HTTP API using standard method semantics.
Use RFC 9457 Problem Details for API errors with the
application/problem+json media type.
Describe the contract in OpenAPI.
Before implementation, list assumptions, conflicts, and questions.
Do not write application code.
I reviewed the proposed operations before implementation. The API contract records the paths, methods, inputs, outputs, and failure cases that the UI and server agree to support. OpenAPI gives those details a machine-readable format for documentation and contract checks.
REST means Representational State Transfer. It is an architectural style for networked systems. Roy Fielding's description includes constraints such as a uniform interface, stateless interactions, cacheable responses, a layered system, and hypermedia. Fielding's dissertation explains the REST constraints.
A resource-oriented API organizes its paths around the things the product manages. Orbit has workspaces, conversations, messages, reactions, saved messages, and calls. Clients use standard HTTP methods to read or change representations of those resources.
For example, GET reads a representation, POST submits data for processing or creates a resource in a collection, and DELETE requests removal of a resource. PATCH applies partial changes. RFC 9110 defines HTTP method semantics, and RFC 5789 defines HTTP PATCH.
Teams often use “RESTful” to describe APIs with resource paths and standard HTTP semantics. Those choices alone do not prove that an API follows every REST constraint. Orbit uses a resource-oriented REST API design. This article does not claim full hypermedia-driven REST conformance.
Here are actual operations from the Orbit API contract:
| User behavior | HTTP operation |
|---|---|
| List workspaces | GET /api/v1/workspaces |
| Create a workspace | POST /api/v1/workspaces |
| List a workspace's channels and DMs | GET /api/v1/workspaces/{workspaceId}/conversations |
| Send a message or thread reply | POST /api/v1/conversations/{conversationId}/messages |
| Edit or restore the caller's message | PATCH /api/v1/messages/{messageId} |
| Add or remove a reaction | PUT orDELETE /api/v1/messages/{messageId}/reactions/{emoji} |
These paths name resources, such as /messages, instead of actions, such as /sendMessage. That gives developers and clients a predictable contract to read and test. It does not provide authorization by itself. The server must still validate every request and enforce ownership.
An HTTP status code gives the general result. A 400 Bad Request response says that the request is invalid, but the client may need more detail to explain the problem or let the user fix it.
RFC 9457 defines a common, machine-readable format for those details. The response uses the application/problem+json media type. This gives API clients one shape for errors instead of a different format on each route. RFC 9457 defines Problem Details for HTTP APIs.
For example, an invalid message-page token could return:
{
"type": "https://api.orbit.example/problems/invalid-page-token",
"title": "Invalid page token",
"status": 400,
"detail": "The page token is malformed or expired.",
"instance": "/api/v1/conversations/c_123/messages"
}
The HTTP response carries the actual status code. The JSON body gives the client a stable problem type and a safe explanation. Do not put stack traces, secrets, or private message content in the error detail.
Consider sending a message to a channel. This single behavior connects the product, UI, API, security rules, and tests:
The original Composer PRD described UI-only local state. The later API work changed that boundary: sent messages became server-owned, while unsent drafts stayed in the browser. The PRD and API contract describe different stages of the project.
Four commits record decisions after the first interface:
| Commit | What changed | Why it mattered |
|---|---|---|
| “Finish workspace switching and the broken message actions.” | Workspace creation and switching, workspace-scoped search, safe links, and message actions became usable. | The main user journey needed to work as one product. |
| “feat(orbit): persist workspace data through API.” | Shared actions moved behind versioned REST routes and SQL-backed tables. The API contract and action map were documented. | The UI needed a consistent place to read and write saved data. |
| “chore: clarify Orbit interface copy.” | The interface text became clearer. | Labels affect what users expect each control to do. |
| “Optimize Orbit runtime and pagination.” | Repeated scans were reduced, message details were fetched in batches, and stable keyset pagination was added while offset cursors remained supported. | Long message histories need stable pages and bounded work. |
The API build added a server boundary:
React interface → versioned REST API → validation and ownership checks → SQL
The browser keeps view state and unsent drafts. The API stores shared product data. When authentication is enabled, the server scopes reads and writes to the verified owner.
Orbit's current demo has no sign-in. All visitors use one shared public demo owner. Its local database survives page reloads while the process runs, but a process restart clears that data. Production identity and durable storage have not been verified. Do not use the demo for private messages.
The performance commit reduced repeated scans and batched reads. The project has no benchmark baseline, so the commit does not prove a measured speedup.
The implementation notes for the last code phase report 21 focused API and compose tests passing and a passing TypeScript check. The broader suite still had baseline failures. A browser journey also could not bind its server in the default sandbox. Those results do not support the claim that every check passed.
AI does not change the release standard. A team still needs evidence that the application is safe, reliable, and operable in its target environment. A polished screen, a successful build, or a group of passing tests cannot establish that on its own.
Before a production release, review at least these areas:
Orbit does not pass this full release review today. It has no sign-in, uses a shared public demo owner, and has process-scoped persistence. The project notes also record broader test failures, a browser journey that could not run in its environment, and no performance baseline. Those are known limits to address before production use.
This is how AI-assisted work can fit into production development: AI helps produce plans, code, and test ideas; the team verifies the system, closes release gaps, and owns the decision to ship. NIST's Secure Software Development Framework and OWASP's Application Security Verification Standard provide deeper guidance for that work.
The documents do not remove judgment from the process. They give the team something specific to review each time the AI makes a change.
Prompt design
Product and software requirements
HTTP APIs and errors
Accessibility
I started with one broad idea and used AI across product clarification, PRDs, interface work, feature revisions, and API design. The useful skill was making each decision explicit, reviewing the result, and recording what remained unverified.
That workflow applies beyond team chat. Start with the people and problem behind your product. Ask AI to expose uncertainty. Approve the requirements. Build and review one feature at a time. Derive the API from the behavior the product needs. Then check the evidence required for your own release.
Orbit shows that AI can contribute to serious application work under human direction. It also shows why a prototype and a production release need different evidence.