Bolt.diy with a Custom OpenAI-Compatible Endpoint

In short: OpenAI-Like lives under Local Providers and ships disabled, so a correct environment file produces no provider until the toggle is on, and environment changes are read at server start. There is no model id field: ids come from your models route and are used verbatim. Every discovered model is also assigned an 8000-token limit in the source, and the context length your endpoint reports is never read. The client is a browser tab, so the endpoint has to answer cross-origin requests.

Bolt.diy runs a full development environment in the browser and asks a model to write the application. Pointing it at a gateway means setting two environment variables, but the variables alone will not put a provider in the model picker — and once it is there, the model list is not something you type.

OpenAI-Like sits under Local Providers and is disabled by default, so a perfectly correct .env.local looks like it did nothing. There is no model-id field: ids are discovered by requesting {base_url}/models and used exactly as returned. And every discovered model is assigned an 8000-token limit in the source, regardless of what your endpoint reports for its context length.

You need a key before the code below runs. Create an account, generate a key, and copy the base URL (https://aicomp.ai/v1). Create one free →
Check current rates → Free to sign up · $1 minimum top-up · No prepayment

This page covers the two variables, the toggle they depend on, what the browser does to your endpoint's requirements, and what a month of app generation costs.

The two variables, and the toggle they need

# .env.local
OPENAI_LIKE_API_BASE_URL=https://gw.example.com/v1
OPENAI_LIKE_API_KEY=sk-your-gateway-key

Then open Settings, go to Providers, and switch OpenAI-Like on under Local Providers. It is off until you do.

The environment variables are read at server start, so changing .env.local requires restarting the dev server — saving the file is not enough, and nothing in the UI tells you the values are stale.

The ordering trips people up in a specific way: configure the variables, restart, and still see no OpenAI-Like models, then conclude the base URL is wrong and start editing it. The URL was fine; the toggle was off.

Model ids are discovered, not typed

There is no text box for a model id anywhere in the provider settings. Bolt.diy requests {base_url}/models with your key and builds the picker from the response, using the ids verbatim.

Two consequences follow. If your gateway does not expose /models, or returns something that is not a list the client can read, the picker stays empty and no amount of editing the base URL changes that. And if the ids your gateway reports differ from the ones its /chat/completions route accepts, you cannot correct them from the UI — you get to send whatever /models said.

There is an escape hatch: declaring models through OPENAI_LIKE_API_MODELS uses the limits you write there instead of the discovered ones, but the discovery step still has to produce something first.

The 8000-token limit is not your model's

Every model discovered from /models is assigned maxTokenAllowed: 8000 in the source. The context_length field your endpoint returns is never read, so a model with a million-token window still shows as roughly 8k in the picker.

This number feeds the picker label and a server-side warning log. Nothing in the streaming path clamps the request or truncates the chat — so treat it as a display artifact, not as a ceiling you are hitting. Seeing 8k next to a large model is expected, not a misconfiguration.

One related quirk, because it looks like a failure and is not: the health badge for local providers performs a browser-side request to {base_url}/models with no Authorization header at all. An endpoint that requires a key rejects it and the badge goes red, while generation keeps working fine. A red badge with working output means the badge, not the gateway.

The browser is the client, and that changes the requirements

Bolt.diy is the only tool in this matrix where the request originates in a browser tab rather than from your machine or your server. Two things follow.

Your endpoint has to answer cross-origin requests. The built-in example is LM Studio, whose documentation note is explicit: enable CORS. A gateway that only accepts same-origin or server-side calls will fail with a fetch error in the console rather than with an API error, because the request never gets as far as your key.

Use 127.0.0.1, not localhost. The shipped example file says so directly, citing IPv6 resolution issues. A local endpoint written as localhost is a plausible-looking source of "Failed to fetch".

Also worth noting if you copy from the example file: HYPERBOLIC_API_BASE_URL is a full URL including /chat/completions, while OPENAI_LIKE_API_BASE_URL is a base URL that must not include the operation path. Two variables, same file, opposite conventions.

What generating applications costs

Bolt.diy asks for a lot of output: it writes files, so a single prompt can produce thousands of tokens of code, and the default output allowance is 8000 tokens. Input is large too, because each turn carries the project state the model needs to keep editing consistently.

A day of work on this page's workload is 380k input and 50k output tokens — 7.6M input and 1M output across 20 working days. This is the heaviest profile in the tool matrix, and it is output-heavy enough that the output rate matters more here than in a chat session. See output vs input pricing for why that flips which model is cheapest.

Per 1M input / output tokens and a 20-day month
ModelGateway rate
in / out per 1M tokens
One day20 days
claude-opus-5$2.5 / $12.5$1.57$31.50
gpt-5.6-terra$1.00 / $6.00$0.68$13.60
deepseek-v4-pro$0.66 / $1.98$0.35$7.00
glm-5.3$0.70 / $2.2$0.38$7.52
qwen3.8-max$1.00 / $3.00$0.53$10.60

One day = 380k input + 50k output on this page's workload. 20 days = 7.6M input and 1M output. Rates checked 2026-10-11 — gateway rates move with upstream promotions, so verify the current number in your dashboard before committing to a budget.

Across 219 catalogue models that publish both rates, the median output rate is 4.0× the input rate, and 68% of them (150 models) charge at least 4× more for output than input. The other 624 raw catalogue entries are dropped by cleaning — test entries, dated snapshots and non-chat variants — not for a missing rate. This is why an agent workload is decided on the output column, not the input one everyone quotes.

Verifying the route

  1. Set both variables, then toggle OpenAI-Like on under Settings → Providers → Local Providers.
  2. Restart the dev server. Environment changes are read at start.
  3. Check {base_url}/models yourself with your key. If it returns nothing usable, the picker will be empty no matter what the base URL says.
  4. Ignore the 8000 in the picker and ignore a red health badge that accompanies working generation.
  5. For a local endpoint, use 127.0.0.1 and confirm CORS is enabled — a console fetch error is a browser rejection, not an API error.

FAQ

FAQ

I set the variables and restarted but see no provider

OpenAI-Like is disabled by default and lives under Local Providers. Toggle it on in Settings → Providers.

Why is the model list empty?

Bolt.diy populates it from {base_url}/models. If that route is missing or unreadable, nothing appears. Check the route with your key before changing the base URL.

Why does my model show 8000 tokens of context?

Discovered models are assigned that limit in the source, and your endpoint's context_length is not read. It affects the label and a log line; it does not clamp or truncate the actual request.

The health badge is red but generation works

The badge performs a browser request to /models without an Authorization header. An endpoint that requires a key rejects that probe while normal requests succeed.

I get "Failed to fetch" against a local endpoint

Either CORS is not enabled on the server, or you used localhost. Use 127.0.0.1 with the scheme, and enable CORS.

Should the base URL end in /chat/completions?

No. OPENAI_LIKE_API_BASE_URL is a base URL. The example file's Hyperbolic variable is the one that takes a full path — do not copy its shape.

Related

Get API access