BF
← Projects

Armond & Co

Design, development & software architecture · freelance

A luxury market consultancy came to me needing a site that actually ranks and loads fast, not just looks expensive, so I built it on Next.js and TypeScript, with server-side rendering tuned specifically for SEO and Core Web Vitals, and Payload CMS underneath.

The site isn't a single landing page, it's a full editorial operation: a trending carousel, a latest-news grid, an editor's picks section, columnist profiles, articles tagged across six categories (market, finance, fashion, lifestyle, branding, real estate), and an embedded video channel. Every one of those had to become a reusable content type in Payload, not a one-off page, so a new article or columnist slots into the right carousel, grid, and category filter automatically.

The part I'm most proud of isn't visible on the site, it's the newsroom behind it: columnists get their own login and can write and edit their own articles, but they can only submit a piece for review, not publish it. Only an admin can flip an article to published, and the moment a columnist submits one, every admin gets an email so nothing sits unreviewed. A columnist also can't sign someone else's byline, that's locked server-side to their own profile.

New article (draft)
Columnist

Writes and edits their own drafts. Can never publish, and can never sign another columnist's byline.

Admin

The only role that can flip an article to published. Gets an email the moment one is submitted for review.

Published, live on site

On top of that workflow sits the part that mattered most to the client: her admins edit everything themselves, approving articles, adding columnists, swapping the homepage carousel, without ever needing to ping me for a content change.

Admin experience

Building a page itself is drag-and-drop: an admin adds blocks from a library, each with its own thumbnail preview in the picker, reorders them freely, and edits every block's own fields directly, its text, images, colors, even which font a paragraph uses, without touching a line of code.

The admin panel itself adapts to who's logged in: there are two roles, admin and columnist, and a columnist's sidebar only shows what they actually need, their own news entries and their own public profile. Categories and the full user list stay out of their way entirely, even though the underlying access rules already prevent them from touching either.

Every user manages their own account, including their own password, but only an admin can assign roles or link a login to a columnist's public profile, so nobody can promote themselves to admin or start signing someone else's articles.

Before publishing anything, an admin can open a live preview and see exactly how a page or article will render, at mobile, tablet, and desktop breakpoints, right inside the same panel, no separate staging environment needed.

SEO & conversion

SEO wasn't a checkbox here, it was the point: an editorial site lives or dies by how well its articles rank, and every article page is image-heavy, with a hero photo plus inline images. That combination is exactly what tanks Core Web Vitals if you get it wrong, so every article is server-rendered with per-page metadata for search engines, and images run through Next.js's built-in optimizer instead of shipping full-resolution files to the client.

The last piece ties content back to business: a newsletter signup wired to Substack, and a WhatsApp contact button, so an article that hooks a reader turns into a lead or a subscriber instead of a dead end.

Headless architecture

Payload isn't a separate service somewhere else, it's a library running inside the same Next.js app, on Vercel. Pages call it through Payload's Local API, direct in-process function calls, not an HTTP request over a network to some other backend, which is what most "headless CMS" setups actually do under the hood.

Every collection is fetched through a small caching layer on top of that Local API: results are cached and tagged per collection, and Payload's own hooks call Next.js's revalidateTag the moment something changes, so publishing an article or editing a page invalidates the cache immediately instead of waiting for it to expire. The database is MongoDB, and every uploaded image goes to Vercel Blob storage instead of the filesystem, since Vercel's serverless functions don't keep local files around between requests.