Internal Apps
Describe the screen. Skopx already has the data.
Most app builders can reach your data and then design the screen from column names and types alone. Skopx runs the query first, measures what actually came back, and designs for that. Which is why the first draft fits your business instead of a guess about it.
The layer nobody talks about
Your database stores what you decided. Your tools are where you decided it.
A record says the deal renewed. It does not say the customer threatened to walk over payment terms, that someone agreed to net-60 in a reply, or that the exception never made it into any system. That is not an edge case. That is most of what a company knows, and it lives in the movement between tools, where no single tool owns it.
Two of those are records. The other three are what actually happened, and no screen in your company shows all five at once. Skopx is already connected to all five, because that is what it has been doing for everything else. An internal app is the first time you get to see them together, and each panel reads its own system at the moment you open the page rather than serving you a copy taken last night.
Why the first draft fits
Most builders design from your schema. Skopx designs from your data.
When an AI builder generates a screen, it is usually working from column names and types alone. Retool describes its own approach plainly: the model “works with schemas, column names, and data types, not the records themselves.” Skopx makes the same call about the result set: 3,412 records never reach the model. The difference is what it sends instead of nothing.
What a schema tells you
account_name text
owner text
status text
mrr numeric
created_at timestamp
Five names and five types. Enough to write a query. Not enough to know that one of these columns will destroy a bar chart and another is mostly empty.
What Skopx measured
3,412 rows
account_name ~53 chars, all unique
owner 61% empty
status 6 distinct, repeating
mrr currency, 0 to 84,000
Measurements, plus a single example row so the model can see the shape of a value. Never the result set. Enough to design correctly, and a rounding error next to handing over the data.
And these are the conclusions it hands itself
"account_name" averages 53 characters. Never use it as a chart x-axis, the labels overlap and become unreadable. Use it as a table column or a list title instead.
"owner" is 61% empty. Avoid building a metric or chart on it.
"status" has 6 distinct values (open, pending, blocked, waiting, closed, ...). It is a good select filter, and a good x-axis or grouping column.
"created_at" is a date and "mrr" is numeric, so a time series (line chart) is available.
Not a paraphrase for this page. That is the literal text Skopx writes for itself before it draws a single panel.
Then it checks its own work
When the runtime overrules the model, it says so on the chart.
A definition is authored against a profile taken before the app was saved, and the shape of a query drifts. So the renderer measures the rows again at paint time and treats the requested chart as an intent rather than an instruction. A chart quietly showing 25 of 340 rows is worse than one that looks crowded, so every override is captioned in the open.
Shown horizontally so the labels fit
The x labels averaged over 24 characters, so a vertical bar chart would have stacked them on their sides.
Same value in all 340 rows, so a chart would be flat
Every row carried the identical number. One figure says it; a chart would have drawn a straight line.
Shown as a table because there is no numeric column to chart
Nothing in the result held a number. A chart here would have plotted zeroes and looked like an answer.
Labels shortened, hover to read them in full
The label budget shrinks as bars multiply: 20 characters up to six bars, 14 up to twelve, 10 beyond.
Samples
Five consoles. One sentence each.
Each of these began as a single request typed into chat. The tools underneath are the ones the company had already connected for everything else.
Everything waiting on someone.
And exactly how long it has waited.
Asked for: What is waiting on an approval right now, who is sitting on it, and what is it worth?
12
Awaiting approval
$84k
Value held up
4
Waiting over 3 days
Held up by type
Every figure reads live from the tool it came from. Every button acts through that same tool, on a click, after it asks.
How it works
Four steps, and none of them are drawing.
01
Your tools are already connected
Slack, the inbox, the CRM, billing, tickets, a database. You connected them for everything else Skopx does, and that is the part that actually takes time. An internal app inherits it.
02
You describe the screen in a sentence
Not a schema, not a form builder, not a canvas. You say what it should show, the way you would ask a colleague to pull it together.
03
It measures, then writes a definition
Skopx runs the draft query, measures what came back, and authors a declarative definition its own runtime renders. There is no generated app with its own database, its own auth and its own holes.
04
You correct it in the same chat
Tell it what is wrong in plain words and the console repaints in place. Every save keeps a version you can restore.
Who sees what
A shared console is not a shared login.
An app reads from the systems that run your company and its buttons write back into them. That is worth taking seriously, so the parts that could go wrong are constrained by the runtime rather than by good intentions.
Read-only, checked twice
A query must be a single statement starting with SELECT or WITH. The check runs again the moment before execution, not only when the app was saved, because a definition can be edited through the API or restored from an older version.
Values never touch the SQL text
Filter and reader values arrive as bound parameters. If a connector cannot carry parameters, the query is refused rather than served an assembled statement. A standalone test compiles that module alone and asserts a hostile value never reaches the query text.
Owner data or reader data, on purpose
A shared console runs as its owner by default, so everyone sees the same numbers. Switch it to run as the reader and every panel executes as whoever opened it, against sources they connected themselves.
Every write asks, then is logged
The only write path is a button, on a click, into a connected tool, with a confirmation by default. Each run is written to an append-only log with who clicked it and what it ran.
The log keeps a digest, not your data
Arguments are stored as a sha256 digest rather than in full. Attributing a write is not a reason to keep a second copy of the customer data inside it.
Private, or your organization
Those are the only two states, enforced by a database constraint. An app you cannot reach answers exactly as an app that does not exist, so an id nobody shared never confirms itself.
The honest part
What an internal app is not.
You will hit these in the first week, so you may as well have them now.
It stores nothing
There is no form, no input, no upload and no record creation. An internal app is a view over systems that already hold your data, not a new place to put it.
It does not run while you are away
No schedules, no alerts, no emailed reports. Refresh ticks only while the tab is open, and an action fires only when a person clicks it.
It is not a drag-and-drop builder
There is no canvas to arrange. Every change is a sentence in chat, which is the point, but it is worth knowing before you arrive expecting a designer.
It has no public link
No embeds, no anonymous access, no client-facing portal. Every route requires a signed-in session that owns the app, or belongs to the organization it was shared with.
Charts are bar, line, pie and area
No scatter, no gauges, no maps, no dual axes. The four that read well, chosen and corrected against your actual values.
A board shows status, it does not move it
The kanban view is read-only. Cards cannot be dragged between lanes, because the lane belongs to the system the card came from.
An internal app is a console over systems that already exist. When what you need is a place to keep new records, the honest answer is that this is not it.
Internal Apps
A builder that designs before it looks is just drawing.
The screen was never the hard part. Being connected to everything the screen needs to show is the hard part, and that connection was already made before anyone asked for an app.