Files
llmgw/internal/web/templates/landing.html
T
Ilker ManapandClaude Opus 5 082d52bc97
CI / test (push) Successful in 1m23s
Stop shipping a placeholder that looks like a value, and say what is served
A user copied the curl from the profile page and sent it as it stood. Every
other field in that snippet is filled in for them — the base URL, the key
they had just been issued — so "model": "MODEL" reads as a value rather
than a blank, and they got:

  no endpoint serves "MODEL"

which is true and useless. It reads the same whether the name was a typo,
a placeholder left in from the documentation, or a real outage, and it
never says what would have worked.

The message now lists what is being served, capped at ten with a count for
the rest, and says plainly when nothing is. That list is what /v1/models
already returns to the same caller, so it discloses nothing new.

The profile page's example now names a model that is actually running,
real ones before simulated — the point of an example someone can run is
that it runs, and sending a first request to the sim engine would answer
in Greek letters. The landing and claim pages keep a placeholder, because
they are served without a key and deliberately say nothing about what is
here; theirs is <model-name>, which cannot be mistaken for a value, with a
line saying where to get the real one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 18:23:19 +02:00

69 lines
2.8 KiB
HTML

{{define "landing"}}<!doctype html>
<html lang="en"><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>llmgw</title><link rel="stylesheet" href="/_static/base.css">
</head><body><div class="wrap">
<header>
<h1>llmgw</h1>
<p class="sub">An OpenAI-compatible endpoint in front of self-hosted models.</p>
</header>
<p>Point any OpenAI client at this address. The API is the one you already have a
client for; only the base URL changes.</p>
<h2>Base URL</h2>
<pre>{{.BaseURL}}/v1</pre>
<h2>Example</h2>
<pre>curl {{.BaseURL}}/v1/chat/completions \
-H "Authorization: Bearer $LLMGW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "&lt;model-name&gt;", "messages": [{"role":"user","content":"hello"}]}'</pre>
<p class="note">
Replace &lt;model-name&gt; with a name from
<code>GET {{.BaseURL}}/v1/models</code>, which needs your key. Sending the
placeholder unchanged is answered with the list of models that are available.
</p>
<pre>from openai import OpenAI
client = OpenAI(base_url="{{.BaseURL}}/v1", api_key=os.environ["LLMGW_API_KEY"])</pre>
<h2>Which models</h2>
{{if .AuthEnabled}}
<p><code>GET /v1/models</code> lists what is available to your key. It needs the key,
which is why this page does not list them: this page is served to anyone who can
reach the address.</p>
{{else}}
<p><code>GET /v1/models</code> lists what is available.</p>
<p class="note">This gateway has no API keys configured, so it serves anyone who can
reach it. That is a deployment choice and only safe on a trusted network.</p>
{{end}}
<h2>Getting a key</h2>
{{if .SignupOpen}}
<p><a href="/signup">Create an account</a>. Someone will approve it, and then you
can issue your own keys from your <a href="/profile">profile</a> — as many as you
need, revoking them yourself when a laptop is retired or a script is done.</p>
<p class="note">Already have an account? <a href="/login">Sign in</a>.</p>
{{else if .Contact}}
<p>Ask {{if .ContactHref}}<a href="{{.ContactHref}}">{{.Contact}}</a>{{else}}<strong>{{.Contact}}</strong>{{end}}
for one. {{if .AuthEnabled}}If you already have an account,
<a href="/login">sign in</a>.{{end}}</p>
{{else}}
<p>Keys are issued by whoever operates this gateway. If you do not know who that
is, the address you reached this page at is the place to start asking.</p>
{{end}}
<p>A key is shown once and never again — only its hash is kept here — so put it in
a password manager straight away.</p>
{{if .Notice}}<p class="note">{{.Notice}}</p>{{end}}
<h2>Once you have one</h2>
<ul>
<li><code>GET {{.BaseURL}}/v1/models</code> — what your key may use</li>
<li><code>GET {{.BaseURL}}/me</code> — its limits, and what it has spent</li>
</ul>
<footer><span>llmgw {{.Version}}</span><span>{{.Now}}</span></footer>
</div></body></html>{{end}}