This is the administrative dashboard for managing content and data for dileepa.dev and its associated API.
Important
This app is not deployed. It runs on localhost against whichever API API_URL names. That
is why it has a single .env rather than the per-environment split the API and the main site
use — two files would always hold the same values.
This application serves as the central admin interface for:
- dileepa-dev: The personal portfolio website.
- api-dileepa-dev: The backend API providing data for the platform.
- Dashboard — counts what is live on the site rather than what exists in the database. A count of rows tells you the database is not empty; a count of what a visitor can see tells you whether the site is right, which is the question someone opening this app is asking.
- Content management, grouped the way the site is:
- Profile — about, experiences, educations, tools, pillars, speaking topics
- Community — communities, events, videos
- Content — projects, blogs, comments, media
- Events carry speakers, photos, recordings and links as repeatable field groups. Photos attached here are the site's event gallery.
- Blogs are an index of what is in Git, not the posts themselves. The screen says so: the sync
rewrites most of these fields on every push to
blog-dileepa-dev. View and reaction counts are shown but not editable — readers write those, and the API refuses them on write. - Comments — moderation, not authoring. Readers post from the website and their comments are live immediately, so this screen is what comes after: hiding one (reversible, and the replies underneath survive), correcting one, deleting one, or replying as the author. It is the only screen showing a commenter's email address; the public endpoint returns a model with no field for one.
- Drag to reorder. Any list can opt into it — tools, pillars and speaking topics do today. Rows carry a grip, their position number, and up/down arrows, because drag is a mouse gesture and the arrows are the whole keyboard and touch path. The order commits in one request, not one per row.
- Media — Cloudinary-backed uploads. This app never holds those credentials; every upload goes through the API, which is the only thing that does.
- Videos carry a short description shown under the title on the site. Optional — a video that predates the field simply has none.
- Account — who you are signed in as and for how long: email, roles, whether the account is active, and the session's expiry counted down live alongside when it was issued, how long it runs, and how it is signed. The account comes from the API and the session from your cookie, so where they disagree you can see it. The token is decoded on the server; only the claims reach the browser.
- A status badge in the header, on every screen — which environment, which API host, and
which database this session is talking to. Reads
GET /status, which the API registers in every environment specifically so this cannot be mistaken. Production gets--warningstyling and an explicit warning line; an unreachable API says so in--errorrather than the badge going quiet. - Database — copy production into the development database, or empty it, so every screen here
shows real content without production being touched. The copy only runs in one direction, and
not because this app is careful: the API writes to the database it is pointed at and reads from
a separately configured source, so there is no argument here that could be inverted. Both
actions stay disabled until the target database's own name is typed out.
usersis never copied, so you stay signed in. Development only — the API does not register these routes when it runs in production, so pointingAPI_URLatapi.dileepa.devmakes the screen say the feature is unavailable rather than offering buttons that would fail. - Authentication — JWT in an
httpOnlycookie, with the session watched client-side so an expired token signs out at the door rather than on the first save. - An unreachable API degrades rather than crashes. Every list read falls back to empty and a banner names the API that is not answering, so a blank table is never mistaken for no data.
- Themes — dark and light, sharing the
dileepa-themestorage key with every other surface, so the theme follows you between them.
- Framework: Next.js 16 (App Router)
- Language: TypeScript
- UI & Styling: React 19, Tailwind CSS 4, Lucide React
- Validation: Zod
- Design system: the platform token sheet, vendored to
app/brand-tokens.cssfromdileepadev/docs/brand/. It is a copy, and a copy can drift — when the canonical file changes, re-copy it rather than patching this one. Every colour resolves through a semantic token; there is no hard-coded hex in any component.
- Node.js (Latest LTS recommended)
- npm or pnpm
-
Clone the repository:
git clone https://github.com/dileepadev/admin-dileepa-dev.git cd admin-dileepa-dev -
Install dependencies:
npm install
-
Set up environment variables:
cp .env.example .env
One file, on purpose — see the note at the top.
API_URLis read on the server, where every call is made from, and it is the only thing that decides which database you are editing. How you start this app says nothing about it:next devpointed at the deployed API is editing production, and looks exactly likenext devpointed at a local one.API_URLTalks to Database http://localhost:8000a local API whatever its own banner says, usually dev https://api.dileepa.devthe deployed API production — saves are live The header badge reports which of those answered, and whether this admin is local, on every screen. Write it with no trailing slash and with
httpsfor anything that is not localhost; a trailing slash builds//projects, which the API 404s, andhttpputs the admin token on the wire in cleartext. Both are corrected at load with a warning — seenormalizeApiUrlinlib/api.ts— but the file should be right. -
Start the API. This app is a client and does nothing useful without one:
cd ../api-dileepa-dev && uv run fastapi dev
Run the development server:
npm run devThe dashboard is at http://localhost:3001.
To create an optimized production build:
npm run build
npm run start- dileepa-dev - Personal Portfolio Website.
- api-dileepa-dev - Personal Data API.
- blog-dileepa-dev - Personal Blog Content.
- links-dileepa-dev - Linktree-style page.
Please refer to the following documents for contribution and development standards:
This project is licensed under the MIT License - see the LICENSE file for details.