Engineering ·
Vibe coding a personal website with Codex
A weekend chat with codex turned into a personal website; now live, with the story of how the website came into -what you are reading now- as the first write-up published in it.
I had owned the domain amalkm.com for quiet some time now. I even had a normal template based wordpress website, where I had published a couple of write-ups long back. I never maintained it well, and it was almost abandoned. Part of the reason why it was abandoned was that it never felt personal, the design, the process of writing and maintaining(if you work in IT and has a special bond with the command line / terminal, then you would understand the pain and irritability of navigating a GUI! Wordpress was not the thing for me!!). As someone using cursor AI regularly at work, I knew what the new generation of LLMs are capable of. Thtas why I thought of reviving my idea of having a personal website, with the help of AI. I also wanted it to feel like something I would actually maintain. A place for my engineering write-ups, projects, and the occasional thought that refuses to stay inside an engineering category. All of which I can write from the command line, and push to deploy.
Why Codex?
The choice of using codex was an obvious one for me. ChatGPT was my go-to AI model, like many of you, from the moment LLMs became popular. I have been using it regularly and by now, I feel like it has some very relevant context about my interests, personality, and passions. This was important because my first design choice was that the website MUST be an extension of my personality- not a show-off of what AI can do. No fancy animation gimmicks, no crazy transitions: just something that represents me.
"Used codex" to build it needs some unpacking. I set the direction, made the product and architecture decisions, reviewed what came back, and tested it. Codex proposed designs, worked through implementation details, wrote code and ran checks. Sometimes I accepted a suggestion. Sometimes I changed my mind. Sometimes I looked at the result and said, quite simply, I don't like this.
That last part turned out to be important.
Before the website, the context
One of my first requests was to stop before building and look at the instructions themselves.
I didn't want every new session to begin with me explaining the same person and the same website again. I also didn't want a long conversation to be compressed into a generic portfolio specification. The engineering side mattered, but so did the way I wanted the site to feel.
So the repository became the place where we kept the project's memory.
AGENTS.md was the starting point. It told Codex how to work with me, what it could change, what it should preserve, and where to look next. context/00-index.mdx provided the map. Instead of asking the model to load everything for a tiny fix, it directed different tasks towards the relevant context.
The context was organised into ten files:
| File | What it kept track of |
|---|---|
01-project-vision.mdx | Purpose, audience and what belonged on the website |
02-authentic-identity.mdx | Background and the boundary between useful context and publishable information |
03-information-architecture.mdx | Pages, navigation and how someone would find things |
04-content-strategy.mdx | Writing, content formats and publication rules |
05-design-direction.mdx | Visual character, layout and interaction decisions |
06-technical-architecture.mdx | The technical structure and implementation conventions |
07-wordpress-migration.mdx | The existing-site and eventual migration questions |
08-brand-domain.mdx | Naming, identity and domain direction |
09-collaboration-rules.mdx | How the human and the AI should work together |
10-decisions-log.mdx | What changed, who decided it and why |
These were Markdown and MDX documents used as instructions, not content to render on the website.
We also needed to distinguish a decision I had made from something Codex had suggested. Otherwise, an interesting possibility in one session could become a requirement in the next.
The markdown files helped with continuity. But they didn't make the model always correct, and they didn't remove the need to review its work.
Architecture was also deciding what to leave out
The implementation uses Next.js, TypeScript, plain CSS and Markdown content. Git keeps the changes, and the existing GitHub-to-Vercel connection handles deployment when I approve a push.
Contact was a particularly useful lesson.
We had gone down a path involving a custom form, a database, notification services and a booking workflow. At first, I was particularly curious in proceeding with this architecure, because I thought the end product would be a web app that I could then use to polish my CI/CD and gitOps knwwledge; the plan was to take over the deployment from the automated gitHub->Vercel flow and build my own AWS infra(free-tier, if possible) and an ArgoCD flow. But, for that design to be implemented, it required substantial coding effort from the AI(which means a lot of tokens!) and manual integration with resend, and meta business accounts etc. I eventually stopped and questioned why a personal website needed all of that for the behaviour I actually wanted.
For a message, I wanted a button that opened the visitor's email application with my address filled in. For appointments, I already had a Google appointment schedule.
That became the replacement: an email button and an embedded schedule, with a link to open Google's booking page if needed.
Owning the website means being able to change it
While reviewing the code by myselft, I identified a problem: the Home introduction had ended up inside a page component. The website looked fine, but the content boundary was wrong. Changing my words should not require changing application code, and I shouldn't be asking AI everytime I want to edit the content. Remember, being able to maintain the whole site over the command line was a big deal for me.
AI listened, and did the cleanu. It moved the displayed introduction into Markdown while preserving its wording and line breaks. About and articles already had Markdown sources. Navigation, headings, button labels and footer wording now belong in a configuration file. Identity, public links, the canonical domain and the résumé filename are configuration too.
The publication manifest is a separate decision. A file being present in the repository is not permission to display it. The site builds its public content package from explicit selections, and a draft remains excluded even if somebody selects its slug.
Engineering now has room for both articles and projects. Other writings has its own place. I can develop an open-source project, write about the reasoning behind it, and connect the two without treating a project description and an article as the same thing.
Sharing the code without sharing everything
I want the source to accompany this article so someone can look beyond the screenshots.
Making the original repository public would be the wrong shortcut. It contains writing, project context and history that were never intended to become a reusable template. Deleting those files from the latest commit would not remove their earlier versions.
The source version is therefore a separate, clean snapshot: application code, fictional example content, publishing instructions and sanitised context templates. It starts without the private repository's history or deployment connection.
The context templates retain the structure I used with Codex. They are adaptations for someone else to use, not a dump of my personal notes. The same applies to the example writing: it demonstrates the publishing system without distributing my own content.
What I mean by vibe coding, after doing it
The useful part was being able to move quickly from a decision to something I could examine in a browser. I could ask for a change, see its consequences, and revise the decision without implementing every detail myself.
But the responsibility didn't disappear when the code became easier to produce.
I still had to decide what the site was for. I had to recognise when the implementation had become more complicated than the problem. I had to test, reject things, preserve boundaries and decide what was ready to publish.
Codex built a lot of the house. I co-architected it, deciding what kind of place I wanted it to be, what belonged in it, and whether I was comfortable opening the door.