← Blog

How to Build an AI App From Scratch: Full Walkthrough

2026-09-21 · 5 min read · SubToAPI Team

Building an AI app from scratch means making a series of concrete decisions in a specific order: what the app does, how it talks to a model, how you store state, how you handle streaming and errors, and how you ship it. There's no shortcut around these decisions, but there is a sane order to make them in, which is what this guide walks through.

If you already know Python or JavaScript, you don't need a new framework to start — you need a clear architecture. Below is the full path from a blank folder to a deployed AI app, with the trade-offs at each step explained rather than glossed over.

Step 1: Define the interaction, not the feature

Before writing code, decide what kind of interaction your app has with the model:

This decision changes your entire backend shape. A single-turn app can be nearly stateless. A chat app needs a conversation store. An agentic app needs a tool-execution loop and a way to cap iterations so it doesn't run forever.

Step 2: Choose how you'll access the model

You have three realistic options:

  1. Call a model provider's API directly with your own API key, billed by token usage.
  2. Use your existing chat subscription through a wrapper that exposes it as an HTTPS API — this is what SubToAPI does for Claude access, giving you an application key (sub_live_...) instead of managing provider billing separately.
  3. Self-host an open model — only worth it if you have GPU infrastructure and specific latency/privacy requirements.

For most people building a first AI app, option 1 or 2 is right. Self-hosting adds infrastructure work that has nothing to do with your actual product.

Step 3: Set up the backend skeleton

You need a server that takes a request from your frontend, calls the model, and returns a response. Keep the model call isolated in its own module so you can swap providers later without touching your app logic.

// server.js
import express from "express";
const app = express();
app.use(express.json());

async function callModel(messages) {
  const res = await fetch("https://api.subtoapi.app/v1/messages", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      model: "claude-3-7-sonnet",
      max_tokens: 1024,
      messages
    })
  });
  return res.json();
}

app.post("/api/chat", async (req, res) => {
  const reply = await callModel(req.body.messages);
  res.json(reply);
});

app.listen(3000);

This is enough to have a working AI app end to end. Everything after this is refinement: streaming, memory, tools, error handling, and deployment.

Step 4: Add streaming for a real product feel

Users expect tokens to appear as they're generated, not a spinner followed by a wall of text. Streaming is a server-sent event connection you proxy from your backend to your frontend.

const stream = await fetch("https://api.subtoapi.app/v1/messages", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    model: "claude-3-7-sonnet",
    max_tokens: 1024,
    stream: true,
    messages: [{ role: "user", content: "Explain event loops" }]
  })
});

Streaming is not optional if your app has any chat-like interface — it's the difference between an app that feels responsive and one that feels stalled. See /docs/streaming for the exact event format if you're using SubToAPI as your model layer.

Step 5: Handle conversation memory correctly

Models are stateless between requests — the model doesn't remember your last message unless you send the full history back every time. Two things trip people up here:

A minimal schema is enough to start:

CREATE TABLE messages (
  id SERIAL PRIMARY KEY,
  conversation_id UUID NOT NULL,
  role TEXT NOT NULL,
  content TEXT NOT NULL,
  created_at TIMESTAMPTZ DEFAULT now()
);

Step 6: Add tool use if your app needs to act, not just talk

If your app should look things up, run calculations, or call other APIs based on model reasoning, you need tool/function calling. The model doesn't execute anything itself — it returns a structured request, your backend runs the actual function, and you send the result back in the next turn.

{
  "tools": [
    {
      "name": "get_weather",
      "description": "Get current weather for a city",
      "input_schema": {
        "type": "object",
        "properties": { "city": { "type": "string" } },
        "required": ["city"]
      }
    }
  ]
}

Your server loop checks the response for a tool call, executes it, appends the result to the message history, and calls the model again. Cap this at a fixed number of iterations to avoid infinite loops on ambiguous inputs. /docs/tools covers the request/response shape if you're implementing this against SubToAPI.

Step 7: Handle errors, rate limits, and costs before launch

Three things will break in production that never break in development:

Step 8: Deploy and monitor

Deploy your backend (Vercel, Fly.io, Render, or a plain VPS all work fine for this kind of app — none of it is AI-specific). Add basic logging on request latency and error rate for the model-calling endpoint specifically, since that's your slowest and most failure-prone path.

If you're getting your model access through a subscription-based API layer, check the plan limits before scaling traffic — SubToAPI's Solo, Team, and Scale plans differ mainly in seats and usage headroom, and you can start on a free trial via /signup to test the whole flow before committing. The quickstart and messages docs cover the exact request format for turning your key into your first API call.

Questions

Do I need to fine-tune a model to build a real AI app? No. The overwhelming majority of production AI apps use prompting, context, and tool calling on a general-purpose model. Fine-tuning is a later optimization for narrow, high-volume tasks, not a starting requirement.

What's the minimum stack to build an AI app from scratch? A backend that calls a model API, a way to store conversation state if needed, and a frontend that renders streamed responses. That's three components — everything else (agents, tools, RAG) is added once the basic loop works.

Should I use my own model provider account or an API wrapper like SubToAPI? Use whichever gets you a stable, documented HTTPS endpoint fastest. If you already pay for a Claude subscription, wrapping it into an API key avoids setting up separate provider billing while you validate the product.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →