Skip to content

Building AI features into your own app without reinventing the LLM stack

Robert Boylan8 min read

You put "add AI" on the roadmap six months ago. It's still there. Every time you circle back to it, you end up reading a blog post about RAG pipelines and fine-tuning and vector databases, and then you close the tab and work on something else.

Here is the thing: most AI features that actually ship from indie projects are not the ones with the fanciest architecture. They are the ones where the developer figured out what type of problem they were solving, picked the simplest tool that worked, and shipped it.

This post is for the indie dev whose roadmap says "add AI" and whose app still doesn't. By the end you will know which archetype your feature fits, how to pick a provider without overthinking it, when streaming is worth the complexity, and which "AI features" are traps.

The four archetypes that actually work at indie scale

Before you write a single line of integration code, you need to know which of these four things you are building. Almost every useful AI feature at indie scale is one of them.

Classify: you give the model some text and it puts it in a bucket. A bug report categorised as "billing", "performance", or "UI". A customer message routed to the right support template. Classification prompts are short, cheap, and fast. The output is a label, not prose.

Summarise: you give the model a long thing and get back a short thing. Meeting notes condensed to three bullets. A GitHub issue distilled into one sentence for a dashboard. Summarisation prompts have a clear contract: here is the input, here is the shape of the output.

Generate: you give the model a brief and get back content. Draft email copy based on a form submission. A product description from a title and bullet points. Generation is where most people start because it is the most obvious use, but it is also where the most over-engineering happens.

Extract: you give the model unstructured text and get back structured data. Pull a company name, role, and LinkedIn URL from a pasted email signature. Parse a feature request into fields: priority, category, and affected users. Extraction replaces a lot of regex spaghetti and brittle parsers, and it is underrated.

One more honest note: most features that seem too complex for this list are actually two of these chained together. "AI that understands my users" is probably classify then summarise. "Smart search" is probably extract then return. Break it down before you build it.

Provider choices: AI SDK plus gateway vs direct SDK

Once you know your archetype, you need to pick how you call the model. There are two sensible paths.

Go direct with the provider's SDK when you want simplicity and you are calling one model from one provider. Anthropic's SDK, OpenAI's SDK, and Google's SDK are all well-documented and take about twenty minutes to set up. If your app only ever needs one model, this is fine. The friction of adding a second provider later is not that bad.

Use an abstraction layer when you want to swap providers without rewriting call sites. The Vercel AI SDK (opens in new tab) is the most widely used option for TypeScript apps. It gives you a consistent interface over Anthropic, OpenAI, Google, Mistral, and others, plus built-in streaming support and a clean way to handle tool calls. The cost is a thin abstraction layer and a slightly larger dependency tree. For most indie apps it is a good trade.

Use an AI gateway (like Vercel's AI Gateway or OpenRouter) when you want to route traffic across providers at runtime, add caching, or see unified spend across multiple models. Worth setting up if you are calling AI from several parts of your app. If you are wiring up one feature, it is overkill.

The rule: start with a direct SDK, move to an abstraction layer when you have two or more features, and reach for a gateway when you have a spending or routing problem you can actually see. Most indie apps never need the third step.

Streaming vs one-shot: when the complexity is worth it

Streaming means sending the model's response to the user token by token as it arrives, instead of waiting for the full response and sending it all at once. It feels snappy. Users see progress immediately. For long generations it is the difference between "this feels alive" and "did it hang?"

But streaming adds real complexity. You need a streaming-capable endpoint on the server, a reader on the client, and logic to handle partial states, errors mid-stream, and cancellation. In a serverless environment, check whether your hosting platform supports streaming before you design around it.

The heuristic: stream when the response is long and the user is watching it generate in real time. Generation features almost always benefit. A "draft a reply" button where the user watches the email appear is a better experience than a spinner. Extract and classify almost never benefit. The response is short, you do not want the user seeing partial JSON, and you are probably transforming the output before displaying it anyway. Summarisation is in the middle: short summaries do not need streaming, but a paragraph-length summary might.

If you are not sure, build one-shot first. You can add streaming later. Building streaming first and discovering you did not need it is a waste of a day.

Cost modelling: how to keep an AI feature from breaking your unit economics

This is the part most indie devs skip, and it is the reason some AI features get pulled six weeks after launch.

Before you write any code, estimate the cost of one call, multiply by expected volume, and check whether the number still makes sense at 10x volume. Classify and extract calls cost fractions of a cent. Summarisation with a long input document can run to several cents per call. Generation sits in between and scales with output length.

Three levers you control:

Model selection. The cheapest models that can do the job are dramatically cheaper than the premium ones. For classification and extraction, a smaller model is often indistinguishable from a flagship model in output quality. Test the cheapest model first. Only move up when you can demonstrate the quality gap matters.

Prompt length. Input tokens cost money. A system prompt that is three times longer than it needs to be is a quiet tax on every call. Audit your prompts before launch. You will almost always find 30% that can be cut without changing the output.

Caching. If you are calling the same model with the same system prompt thousands of times a day, Anthropic's prompt caching can cut your input costs by up to 90% on the cached portion. OpenAI has a similar feature. This is worth setting up early if your system prompt is long and stable.

The deeper question is whether the AI feature is part of your core value or a nice-to-have. If it is core, you can often charge for it directly or include it in a higher-tier plan. Thinking about how you are pricing your indie app before you design the feature makes the cost question much easier to answer.

The features you should not add AI to yet

This is the temptation list. These are all real things developers have tried to build AI features into when they probably should not have.

Search. Semantic search with embeddings and a vector database sounds great. It is also a genuine infrastructure project. Unless keyword search is demonstrably failing your users and you have the logs to prove it, ship basic search first. Add AI when you have evidence that it solves a problem basic search cannot.

Recommendations. "Recommend content based on the user's history" requires enough history to be meaningful, a feedback loop to know whether the recommendations worked, and a coherent data model. Most indie apps do not have any of these at launch. You need the users before you need the recommendation system.

Real-time anything. A chatbot that knows your user's account data, a live assistant that can see what the user is doing, an AI that answers questions about your product using current data. All of these require a retrieval system, tool use, or a live data feed. None of them are hard in principle, but all of them are a full feature sprint, not an afternoon.

Fine-tuning. Fine-tuning a model on your own data almost never makes sense at indie scale. The data collection, labelling, and training pipeline is a project in itself, and the quality improvement over a well-written prompt is often smaller than you expect. This is for teams with millions of examples and a dedicated ML engineer.

The common thread: all of these require the AI to do something structurally new, not apply one of the four archetypes to data you already have. When in doubt, ask which archetype it fits. If you cannot answer in one sentence, it is probably not ready to build.

What to actually do next

Pick one feature. Decide which archetype it is. Write the prompt first, in plain text, before you write any code. Paste some real inputs into the API playground and see if the output is useful. If it is, wire it up. If it is not, fix the prompt.

The prompt is the product. That is the thing most developers learn late about prompt engineering: the quality of your AI feature is almost entirely determined by how clearly you described the problem. Architecture decisions matter, but they matter far less than having a prompt that works.

Once you have one feature shipping, the second one is much easier. You already know your provider, your deployment setup, and what your unit economics look like. The goal for the first feature is not to build the most impressive AI integration. It is to build one that works and ships before you lose interest.

If "add AI features" has been on your roadmap long enough that it has started to feel vague, Draftlytic is a good first stop. Describe the idea, answer a few questions, and get back a structured plan that makes the feature concrete before you touch the integration at all.