Oct 23, 20265 min read

How to Build an Internal Admin Dashboard with Claude Code and Deploy It to Your Own AWS

Claude Code can write an admin dashboard in an afternoon. Getting it onto AWS with a database, login and no shared keys is the slow part. Here is the hand-built route and the Encore route for a TypeScript backend.

Most admin dashboards are a few tables, a search box and two or three buttons that change a row. Claude Code can write that from a prompt like "build an admin page for our orders table with refunds," but it cannot decide by itself where the database lives on AWS and which credentials run the deploy.

This guide builds the same dashboard twice, once on hand-built AWS and once with Encore, and shows what the agent has to produce in each case.

The dashboard at a glance

QuestionWith EncoreHand-built on AWS
DatabaseDeclared in the service, RDS in your accountRDS instance, subnet group and security group you define
Local databaseencore run starts Postgres locallyYour own local Postgres setup
LoginAuth handler in code, checked by the API gatewayMiddleware you write and wire up
Frontendapi.static endpoint or a separate hostS3 and CloudFront, or the same container
Deploygit push, Encore provisions in your AWSCI pipeline with AWS credentials
Who holds AWS accessEncore's IAM role in your accountThe CI role or whoever runs the deploy

The hand-built route: Express, RDS and ECS

A typical prompt produces an Express server with a pg pool, and a React app built by Vite. The backend code is short, using Postgres' case-insensitive ILIKE for search:

import express from "express"; import pg from "pg"; const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL }); const app = express(); app.use(express.json()); app.get("/api/orders", async (req, res) => { const q = String(req.query.q ?? ""); const { rows } = await pool.query( "SELECT id, email, total_cents, status FROM orders WHERE email ILIKE $1 ORDER BY id DESC LIMIT 50", [`%${q}%`], ); res.json({ orders: rows }); }); app.use(express.static("dist")); app.listen(8080);

The rest of the work is on AWS. The dashboard needs an RDS instance in private subnets, a security group that lets only the service reach it, an ECS service behind a load balancer, a task role, a secret for the connection string, and a pipeline that builds and pushes the image. Vite's static deploy guide covers the frontend build, but the hosting choice is yours.

An agent can write all of this as infrastructure code. Applying it needs AWS permissions, so either the agent gets credentials on the machine or a person runs the apply and debugs what the agent wrote. Login is also missing, since the Express app above answers anyone who can reach it, so the agent still has to add identity provider integration before the URL goes anywhere.

Encore: the dashboard as one TypeScript app

Encore

Encore combines an open source SDK for TypeScript and Go backends with a platform that provisions and deploys what the code uses into your own AWS account. The SDK covers APIs, databases, auth, Pub/Sub, cron jobs and secrets, and the platform turns those declarations into RDS, Fargate or EKS, and IAM.

The orders service declares its database and endpoints together:

// orders/orders.ts import { api } from "encore.dev/api"; import { SQLDatabase } from "encore.dev/storage/sqldb"; const db = new SQLDatabase("orders", { migrations: "./migrations" }); interface Order { id: number; email: string; total_cents: number; status: string; } export const search = api( { expose: true, auth: true, method: "GET", path: "/api/orders" }, async ({ q }: { q?: string }): Promise<{ orders: Order[] }> => { const pattern = `%${q ?? ""}%`; const orders = await db.queryAll<Order>` SELECT id, email, total_cents, status FROM orders WHERE email ILIKE ${pattern} ORDER BY id DESC LIMIT 50`; return { orders }; }, );

auth: true means the request has to pass the app's auth handler before the endpoint runs. The dashboard's built frontend is served from the same app with a static assets endpoint:

// web/web.ts import { api } from "encore.dev/api"; export const assets = api.static({ expose: true, path: "/!path", dir: "./dist" });

Claude Code runs the whole thing with encore run, which starts Postgres locally and applies the migrations, and it can call the endpoints and read traces through the local MCP server. Because the database and the login check are part of the code, a prompt like "add a status filter and an index for it" lands as one change that the agent has already run, rather than a code change plus a ticket for infrastructure.

Deploying is a push to the branch connected to an environment in your AWS account. Encore creates the VPC, places RDS in a storage subnet with no internet access, and gives the service an IAM role scoped to what it uses. The agent writes code and pushes, and cloud access sits with Encore's IAM role, not the agent.

Good to know

Encore recommends a dedicated frontend host for public sites. For an internal dashboard used by a few dozen people, serving the Vite build from api.static is a reasonable trade for one deployment. Single-page apps with client-side routing need the fallback path shown above.

Get started
brew install encoredev/tap/encore &&
encore app create
Copy

Run in your terminal to get started locally.

How to choose

  • Encore when you want Claude Code to build and change the dashboard and its database together and deploy to your AWS account, with cloud access held by Encore's IAM role rather than the agent.
  • Hand-built on AWS when the dashboard has to fit an existing ECS cluster and infrastructure repo that your platform team already runs.

Frequently asked questions

How do I build an admin dashboard with Claude Code and deploy it to AWS?

Ask Claude Code for a TypeScript backend with the endpoints the dashboard needs and a React frontend built to static files. With Encore, the agent declares the database and an auth handler in the code, runs everything with encore run, which starts Postgres locally, and you deploy by pushing to the branch connected to your AWS environment. Encore provisions RDS, Fargate or EKS, and IAM in your account.

Does Claude Code need AWS credentials to deploy the dashboard?

Not with Encore. Cloud access sits with Encore's IAM role in your account, not the agent. The agent changes code and pushes, and you can require manual infrastructure approval for production.

Can Encore serve the dashboard frontend too?

Yes. An api.static endpoint serves the built HTML, JavaScript and CSS from a directory in the app. For a public product site Encore recommends a frontend host, but for a small internal dashboard serving the static build from the backend keeps it to one deployment.

Deploy to your cloud on AWS and Google Cloud
without managing infrastructure

Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.

~/orders — claude
Claude Code
Claude Code v2.1.180Opus 5.5~/orders