Hackday · marmelab · Jul. 2026

react-admin vs from-scratch vs shadcn

The same SpaceX admin built three times by Claude — feature by feature, same API, same prompts. Main variable: how the UI is built. Then replayed in full with Opus 4.8 to add the "model" axis (see the dedicated section). The scoreboard below is for the Sonnet run.

Tokens

811,240 react-admin
1,085,066 from-scratch
1,489,950 + shadcn

cheapest: react-admin

Active time

112 min react-admin
175 min from-scratch
225 min + shadcn

fastest: react-admin

Lines of code

1,212 react-admin
3,032 from-scratch
4,904 + shadcn

least code: react-admin

Production bundle

1,056 KB react-admin
272 KB from-scratch
660 KB + shadcn

lightest: from-scratch

Estimated cost*

€2.24 react-admin
€2.99 from-scratch
€4.11 + shadcn

cheapest: react-admin

* Estimated cost: total tokens × an assumed blended Sonnet rate (~$3/Mtok, in $3 / out $15 / cache-read ~$0.30 — the split was not captured) × 0.92 €/$. Order of magnitude only; the real cost is likely lower (dominated by cache reads). For an exact billed amount: ccusage.

The protocol

Three ways to build the same app

One SpaceX admin built three times by Claude (Sonnet), in 9 identical steps (00→08). Each case runs in a single continuous, "warm" agent session, driven by an orchestrator that sends one feature prompt per turn and records that turn's token/time usage. Prompts 01→08 are byte-identical across the three; only the bootstrap (step 00) differs.

react-admin

marmelab's admin framework. UI provided by MUI (Material Design) — "free".

from-scratch (bare)

React + Vite, no framework, no design system. Minimal hand-rolled styling — raw UI.

from-scratch + shadcn

React + Vite + Tailwind + shadcn/ui: the MUI analog, for a polished UI without an admin framework.

domain: Space (real Launch Library 2 data, 205 launches, 6 resources)API: FakeRest simple-rest writablemodels: Sonnet + Opus 4.8

The verdict

react-admin is cheapest AND polished; shadcn is polished but priciest

Adding a design system to from-scratch (shadcn) finally yields a nice UI — but it is the most expensive of the three cases. react-admin gets a polished UI (MUI) for the fewest tokens, the least time and the least code. Bare from-scratch only wins on shipped weight, at the cost of a raw UI.

Metricreact-adminfrom-scratch+ shadcn
Tokens to build811,240 1,085,0661,489,950
Estimated cost (€)€2.24 €2.99€4.11
Active time (min)112 min 175 min225 min
Lines of code1,212 3,0324,904
Production bundle (KB)1,056 KB272 KB 660 KB
Declared dependencies1110 23
Polished "ready" UIMUI ✓raw ✗shadcn ✓
Steps build-passing9/99/99/9
The reading that matters. The 3rd case answers the "design" bias: react-admin starts with MUI, so a nice UI for free; bare from-scratch is functional but ugly. Giving it shadcn/ui to level the look pushes the cost to 1,489,950 tokens — that's +46% vs react-admin and +27% vs bare from-scratch. Aiming for design parity widens react-admin's lead.

New dimension — the model

Sonnet vs Opus 4.8 — same work, different model

The three cases were replayed end-to-end with Claude Opus 4.8 (byte-identical prompts, same API, same warm-agent protocol). The comparison now reads on two axes: the framework (react-admin / from-scratch / shadcn) and the model (Sonnet / Opus 4.8). Clear verdict: Opus spends about as many tokens as Sonnet on react-admin and from-scratch (±1%), and noticeably fewer on shadcn (−19%) — all in roughly half the time.

CaseTokens SonnetTokens OpusΔTime SonnetTime OpusΔ
react-admin 811,240817,823+1% 112 min62 min−45%
from-scratch 1,085,0661,075,930−1% 175 min94 min−46%
from-scratch + shadcn 1,489,9501,206,005−19% 225 min113 min−50%
Total (3 cases) 3,386,2563,099,758−8% 512 min269 min−47%

The estimated cost, on the other hand, goes up with Opus — not because it spends more, but because its rate is higher (input $5/Mtok · output $25 vs $3 · $15 for Sonnet). Despite ~8% fewer tokens overall, the Opus bill stays about 1.5× Sonnet's:

CaseEst. cost Sonnet*Est. cost Opus*Δ
react-admin €2.24€3.76 +68%
from-scratch €2.99€4.95 +65%
from-scratch + shadcn €4.11€5.55 +35%
Total (3 cases) €9.35€14.26 +53%
What we learn. Switching model does not change the framework ranking: under Opus as under Sonnet, react-admin stays cheapest in tokens (817,823) ahead of bare from-scratch (1,075,930) then shadcn (1,206,005). What Opus changes is speed: ~47% less active time across the run. The token budget (i.e. the order of magnitude of the work) is remarkably stable across models — a feature's intrinsic difficulty dominates over which model implements it.
Two Opus steps were interrupted. An Anthropic API connection drop truncated shadcn·05 and from-scratch·07 mid-turn; the code was already written and was verified on resume, but those two steps' token counts reflect the recovery turn (context replay) — approximate, with a possible slight undercount.
Opus — react-admin: 1343 LoC · 1090 KB · 9 depsfrom-scratch: 3776 LoC · 212 KB · 8 depsshadcn: 4203 LoC · 768 KB · 22 deps

Methodological finding

The context7 effect on react-admin (v1 vs v2)

A first react-admin run (v1) went with the documentation MCP context7 over quota: Claude fell back on slow WebFetch lookups. That single broken dependency flipped the time verdict and inflated the tokens. The react-admin figures above are from run v2 (context7 live), corrected.

Step (react-admin)v1 — WebFetchv2 — context7Δ
00 Bootstrap65,07147,584−27%
01 Lists + pagination66,30052,042−22%
02 References (CRUD)84,12370,408−16%
03 To-many relations93,39679,508−15%
04 Filters / search / sort108,26894,520−13%
05 Dashboard115,997102,168−12%
06 Calendar124,877113,828−9%
07 Bulk actions132,189120,876−9%
08 Extensibility: capsules142,657130,306−9%
TOTAL tokens932,878811,240−13%
Total time182 min112 min−38%
The lesson. In v1, with context7 off, react-admin looked slower than from-scratch (182 vs 99 min); in v2 it is faster (112 vs 175 min). Don't benchmark a framework with its documentation MCP switched off. (from-scratch and shadcn don't use the docs path → unaffected.)

Flight log — 9 steps

Each step in detail

Each feature prompt (identical for all three after the bootstrap) and its token cost, with each case's approach and a real screenshot of the three final UIs where it's telling.

00

Bootstrap

Scaffold the app, connect it to the API on :4000, and prove a list (rockets) renders.

react-admin 47,584 ≈ €0.13
from-scratch 50,715 ≈ €0.14
from-scratch + shadcn 66,042 ≈ €0.18

RA Vite + react-admin + ra-data-simple-rest.

FS Vite + React + react-router, hand-rolled fetch.

SH Vite + Tailwind + shadcn/ui (CLI), hand-rolled fetch.

01

Lists + pagination

List views for the 5 resources, server-side pagination (range + Content-Range header).

react-admin 52,042 ≈ €0.14
from-scratch 60,222 ≈ €0.17
from-scratch + shadcn 84,280 ≈ €0.23

RA <List><Datagrid> — native pagination.

FS Generic ResourceList + Content-Range hook.

SH shadcn Table + Pagination, generic list.

react-admin
react-admin — Lists + pagination
from-scratch
from-scratch — Lists + pagination
+ shadcn
shadcn — Lists + pagination
02

References (CRUD)

create/edit/show everywhere; resolve launch→rocket & launch→launchpad to names.

react-admin 70,408 ≈ €0.19
from-scratch 90,373 ≈ €0.25
from-scratch + shadcn 127,037 ≈ €0.35

RA <ReferenceField> / <ReferenceInput>.

FS Hand-rolled getMany + <select> + generic form.

SH shadcn Dialog/Select/Dropdown + hand-rolled getMany.

Launch edit form (rocket/launchpad references resolved) — steps 02 + 03

react-admin
react-admin — References (CRUD)
from-scratch
from-scratch — References (CRUD)
+ shadcn
shadcn — References (CRUD)
03

To-many relations

launch↔astronauts & launch↔spacecraft, editable.

react-admin 79,508 ≈ €0.22
from-scratch 106,107 ≈ €0.29
from-scratch + shadcn 145,888 ≈ €0.40

RA <ReferenceArrayInput><AutocompleteArrayInput>.

FS Hand-rolled chips editor + batch resolution.

SH shadcn Badge chips + Select, batch resolution.

04

Filters / search / sort

Full-text search, combined filters (status, success, date range), column sort — all server-side.

react-admin 94,520 ≈ €0.26
from-scratch 129,713 ≈ €0.36
from-scratch + shadcn 182,746 ≈ €0.50

RA <List filters>: SearchInput / SelectInput.

FS Filter bar + buildFilter, hand-rolled.

SH shadcn Input/Select + buildFilter, sortable headers.

05

Dashboard

Landing page: KPIs (total, success rate) + charts (launches/year, by rocket).

react-admin 102,168 ≈ €0.28
from-scratch 140,828 ≈ €0.39
from-scratch + shadcn 195,363 ≈ €0.54

RA useGetList/useGetMany hooks; MUI/CSS charts.

FS Hand-rolled useGetAll pager + SVG/CSS BarChart.

SH shadcn Cards + hand-rolled BarChart (no lib).

react-admin
react-admin — Dashboard
from-scratch
from-scratch — Dashboard
+ shadcn
shadcn — Dashboard
06

Calendar

Monthly calendar of launches by net date, server window net_gte/net_lte.

react-admin 113,828 ≈ €0.31
from-scratch 152,641 ≈ €0.42
from-scratch + shadcn 215,232 ≈ €0.59

RA Custom + <CustomRoutes> + custom <Layout>.

FS Calendar grid + route, hand-rolled.

SH Grid + shadcn Card/Button.

react-admin
react-admin — Calendar
from-scratch
from-scratch — Calendar
+ shadcn
shadcn — Calendar
07

Bulk actions

Row selection + bulk status change + multi-delete.

react-admin 120,876 ≈ €0.33
from-scratch 172,097 ≈ €0.47
from-scratch + shadcn 232,430 ≈ €0.64

RA useUpdateMany + <BulkDeleteButton>.

FS Selection + hand-rolled updateMany/deleteMany.

SH shadcn Checkbox/AlertDialog + updateMany/deleteMany.

08

Extensibility: capsules

Add a whole capsules resource (spacecraft reference + to-many launches) — the marginal cost of one feature.

react-admin 130,306 ≈ €0.36
from-scratch 182,370 ≈ €0.50
from-scratch + shadcn 240,932 ≈ €0.66

RA 1 <Resource> line + 5 views, patterns reused.

FS 1 config + type + 2 registrations.

SH 1 config + 2 lines, components reused.

react-admin
react-admin — Extensibility: capsules
from-scratch
from-scratch — Extensibility: capsules
+ shadcn
shadcn — Extensibility: capsules

Good to know

Limits & a finding along the way