External services
An external service is something your application depends on that Kuppit does not provision: a payment processor, a model API, an email sender, an error tracker, an internal API of your own. Kuppit creates nothing for it and manages nothing about it. It is part of the architecture, so it is drawn on the project's Overview — outside every environment, with an edge from each service that uses it — and it is where the variable names those services read for it are kept in view.
What Kuppit detects
When Kuppit analyses a repository it looks for the services the code uses, from the names it finds and nothing else:
| Evidence | Example |
|---|---|
A package in package.json, or an import of one | stripe, @sentry/nextjs |
| A variable name read in code, or listed in an example environment file | STRIPE_SECRET_KEY, NEXT_PUBLIC_STRIPE_KEY |
| A hostname addressed over HTTP | api.openai.com |
| A file named for the service | app/api/webhooks/stripe/route.ts, sentry.client.config.ts |
Kuppit never reads the value of a variable, in your code or in an example file. A key pasted into .env.example is recognised by the name beside it and never stored.
The services Kuppit recognises today are Stripe, OpenAI, Anthropic, Resend, Sentry, Clerk and Supabase. Anything else is added by hand.
Each finding is weighed. A package on its own is worth a look and is marked Review; a variable name on its own is not enough to mention; the two together are a service in use. How sure Kuppit is — very confident, likely, possible — is under the service's Detection in its panel, which opens every piece of evidence behind it.
When you create a project
The New project page draws what it found as the proposed architecture: the resources as cards, and the detected services behind one External services card beside them — the same card a project's Overview puts beside each environment. Its title counts what detection found and the line beneath says how much of it the plan carries, because the two differ while a decision is open. Open it and the services stand behind it, one card each, and selecting one opens its panel: who uses it, the variables it is read as, the evidence, and Include in the project.
A service Kuppit is sure of starts included; one worth a look starts left out. Left out does not mean hidden: the group's panel lists every detected service, so a suggested one can be read and brought in with its checkbox — which is the decision, and it is drawn on the picture from the moment it is checked. Unchecked is a decision: the service is ignored, and Kuppit does not suggest it again. An ignored service can be brought back from the Overview (below), or from this panel before the project exists.
On the Overview
Beside each environment that uses anything outside Kuppit stands one External services card: how many, either Configured or how many of them need configuration in that environment, and, on a third line when detection has found something this environment's services use that nobody has decided about yet, how many are suggested. A dotted line runs to it from every service in the environment that uses something, with no label — the line is the relationship, and the card says how many. Open the card with its chevron and the services stand behind it, one short card each: its name and, when this environment has not set every name it reads, how many — ⚠ 1 — then beneath it the kind of service. The card does not say External again, and who uses it is its panel's to say. A dotted line runs from the group to each, with no label. Each environment opens and closes on its own, and the picture makes room for what is open; nothing about it is remembered between visits. Select the group, a service, or a line, to open the panel.
Which environments a service stands behind is what each environment's own commit says. Kuppit holds a service once, bound to the component that uses it, and reads every deployment's commit for what that component uses there — so a service a pull request began using stands behind the preview, and not behind Production or Staging, until the change merges and deploys to them. An environment whose commit has not been analysed yet shows what the component was last seen using anywhere.
The group's panel lists every service in that environment with a check or how many names it is missing; a row opens the service, seen from that environment. Under Suggested, it lists the services detected in the commit this environment runs that nobody has decided about, each with Add to graph and Ignore — the same decision the notice above the picture asks for, beside the environment it concerns. Add external service and Detect external services are there too. A service's panel shows what it is, who uses it in that environment, its Required variables each with a check or Missing, Set on — each service with a link to its Variables — Why Kuppit detected it, when it was last detected and at which commit, and where else in the project it is used. Open leads to the service's site. Its menu, on a right-click or behind the ellipsis, offers Open service and Ignore for a detected service; Edit… and Delete external service for one you added.
Point at a line from a service to the group and it names the services it uses; point at a line from the group to a service and it names the Required variables, or the ones that are missing. Neither is a connection: they summarise bindings and can be changed nowhere. Kuppit reads the names, never the values.
On a phone, each environment lists External services beneath its cards, with how many need configuration and how many are suggested, opening onto them.
Services waiting for a decision
When Kuppit has found a service nobody has decided about, a line above the picture says so — An external service was detected in the repository: Resend — with Review. The panel then lists each one with Add to graph and Ignore, and, under Ignored, the services you have ignored before, each with Add to graph to restore it. The External services card of every environment whose services use it says how many are suggested there, and the group's panel asks the same question under Suggested.
Detecting again
Right-click empty canvas and choose Detect external services. Kuppit reads the production branch's head again, exactly as it does for a new project, and records what it finds beside what it already knew. A decision you have made is kept: a confirmed service stays confirmed, an ignored one stays ignored, and only a service that is new to the project is suggested. Variable names already configured on your production services count as evidence too — a service you set STRIPE_SECRET_KEY on by hand is a service that uses Stripe.
Detection follows your deployments
Every deployment's source is analysed beside the build — for what the commit requires, and for the external services the service that deployed uses. What it shows is recorded beside what the project knew: a service the code began using is suggested, and a service the component stopped referencing is unbound from it once no environment's copy of the component is at a commit that still uses it — Production redeploying does not take a service away from a pull request's preview that reads it, and the service itself stays, with whatever else still uses it, and a decision about it is kept. The project's Activity says which: web uses Resend as of a1b2c3d, worker no longer references Stripe as of a1b2c3d.
Detection runs when you create a project, on every deployment, and when you ask for it. It never holds a deployment up and never fails one: the analysis is asynchronous, reads its own copy of the source, and a deployment is never waiting on it.
Configuration
In a preview, a service the pull request began using wears New on its card and, until the names it reads are set, counts under needs configuration; the preview's panel lists each name under Application changes with Set variable beside it, which sets it on the preview's service.
Once a service is on the graph, Kuppit compares what each component reads for it against what each environment has set. The names come from the code — STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET — and each environment's copy of the component either has each name, as its own variable or one inherited from the environment, or does not. Kuppit reads the names, never the values.
A name an environment has not set is Missing. That environment's External services card says how many services need configuration, the service's own card counts its missing names — ⚠ 1 — and the service's panel lists every name with a check or Missing, beside the link to the service's Variables where it is set:
Staging · web Variables →
STRIPE_SECRET_KEY ✓
STRIPE_WEBHOOK_SECRET Missing
Set the variable and the warning goes; nothing is redeployed for it, and the running deployment is unchanged until the next one, as with any variable change.
Services you add yourself
Right-click empty canvas and choose Add external service… for anything Kuppit cannot detect: an internal API, a vendor it does not know. Give it a Name, a Kind, optionally a URL for Open to lead to, and tick the components under Used by that depend on it. It is drawn at once, with the same card and the same edges as a detected one. Edit… changes any of that later; Delete external service removes it from the graph and changes nothing that runs.
What an external service is not
It has no status, no deployments, no logs and no variables of its own. It cannot be connected to, copied into an environment or deleted with one. The application graph draws it so that the whole architecture is in one picture; what runs is still exactly the resources inside the environments.
The project's Activity records each decision — a service added to the graph, ignored, added by hand or removed — and each change a deployment revealed.
Connections
Connect a service to a database as one act. A connection injects the database's variables into the service, owns them, and is where they are renamed, re-pointed or removed.
Application changes
What a pull request adds, removes or changes about the application — the variables it reads, the services it uses, the resources it requires — and what its preview still needs.