carlos@cesaints: ~/projects/holding-website.md — zsh

Command: cat projects/holding-website.md

projects/holding-website.md · 1.6 KB

A creative holding's website with an admin panel, secret-link proposals and invoices

The three-language website of a creative holding and the internal panel behind it: diagnosis requests, audience measured without cookies, SEO per page and language, accounts with roles and an audit trail. The panel produces sales proposals, which become private pages opened by a secret link, with an optional password, an expiry date and a view counter, and the printable invoices derived from them. The same house's static landing page, with no dependencies and under the strictest possible security policy, completes the case.

open the demoa simulation of the system with fictional data · 7 screens

Role
Sole engineer, from product to operations
Period
Jul 2026 – Sep 2026
What I did

Me: Architecture, authentication and roles, the data model, the whole panel, the secret-link flow for proposals and invoices, audience measurement, the landing page and deployment.

Private project, described without identifying the client, product or company.

Diagram

Site, panel and secret-link documents in one project

Everything runs on Cloudflare Workers, via OpenNext. The site is pre-rendered in Portuguese, English and Spanish, and a diagnosis request goes to the data, reached through Drizzle, with D1, KV and R2. The panel, with roles by capability, Argon2id, CSRF and an audit log, uses the same data and publishes proposals and invoices as pages opened by a secret link, with an optional password and an expiry date; a revoked link answers like a missing one. The client opens the document without an account. The static landing page, with no dependencies and a CSP of default-src 'none', is published by the site itself.

Context

A creative holding with several lines of work needed a site that explained the house’s method in three languages and turned visits into diagnosis requests. Behind the site, the sales team needed to send proposals and invoices that looked like the house’s own documents, without loose e-mail attachments and without asking the client to create an account.

What I built

  • The site. Prerendered pages in Portuguese, English and Spanish, with translated slugs, hreflang, structured data and a diagnosis form validated by a schema on the server.
  • The panel. Leads, audience, SEO per page and language, accounts with four roles (viewer, editor, admin and owner) and an audit trail of every action.
  • Proposals and invoices by secret link. The editor builds the proposal in blocks (deliverables, scope, markets, clauses and timeline) and publishes it with an optional password, an expiry date and a view counter. The invoice is born from the proposal, inherits the client, the currency and one item per market, and comes out as a sheet ready to print.
  • The landing page. A static page in three languages that converts through a single path: a chat that opens with a ready message in the visitor’s language and the campaign source attached.

What I would do differently

I would run a smoke test against the production build from the very first deploy. The hash library worked on my machine and failed on the edge runtime, and login stayed broken in production until I investigated. I would also write the test that treats Server Actions as public endpoints before the first action, instead of consolidating four diverging guards later.

Constraints

  • Three languages with the same pages, translated slugs and SEO per language.
  • Sales documents that only whoever received the link can open, with no account, no caching and no indexing.
  • Audience measured without tracking cookies and without storing IP addresses.
  • Site and panel on an edge runtime, with in-house authentication.
  • A single technical person to build and run it.

Decisions

A secret link instead of a client account

Context
The client has to open the proposal and the invoice without creating an account, and a guessable or cached link would expose commercial values.
Choice
A random 24-character token (about 143 bits) generated on publishing, an optional password with its own lockout per document, a reading cookie derived from the hash and scoped to the document's path, and a state machine that answers 404 for a revoked, draft or nonexistent link without confirming that it exists.
Gains
  • The client opens it without signing up, and revoking cuts access immediately.
  • Telemetry records the document id, never the token.
Costs
  • Whoever has the link, and the password when there is one, can read the document; the link can be forwarded.
  • Republishing after a revocation creates a new token, and the link has to be sent again.

In-house authentication, with one guard per kind of entry point

Context
The panel has four roles and runs on an edge runtime. Session checks had spread into four copies that already disagreed with each other.
Choice
Argon2id, sessions stored in the database with the id equal to the hash of the cookie token, 8-hour expiry, lockout after 5 failures for 15 minutes, a forced password change, CSRF and capability-based roles. One guard for pages, which redirects, and another for actions, which only refuses.
Gains
  • A single place to review each access rule.
  • A database leak does not hand out valid sessions.
Costs
  • In-house authentication needs continuous review, without the safety net of an off-the-shelf provider.

Server Actions treated as public endpoints

Context
Every export of a Server Actions module becomes an HTTP endpoint. Three listing queries were reachable without a session that way.
Choice
The queries moved to a server-only module, and a test fails any new export without a guard or a declared justification.
Gains
  • The rule no longer depends on the memory of whoever writes the next action.
Costs
  • Every new action has to declare its guard or its justification, one more step in the flow.

Audience without cookies, with the number explained on screen

Context
The team wanted to know who visits the site without tracking cookies or third-party tools, and a number without a definition leads to the wrong decision.
Choice
In-house collection that drops bots and computes a visitor code that changes every day, without storing IP addresses. The visitors metric counted the same person once per day they came back, so it was renamed visitors per day, with a "How we count" box written for people who do not code.
Gains
  • No audience data goes to third parties.
  • The number on screen says exactly what it measures.
Costs
  • The same person cannot be recognized across days, so there is no monthly unique visitor count.

A landing page with no dependencies and no build

Context
The campaign page had to load fast in three languages and run under the strictest possible security policy.
Choice
Plain HTML, CSS and JavaScript, an inline SVG sprite, a CSP with default-src 'none', no unsafe-inline and Trusted Types, and a verification gate before every export into the site, which publishes it.
Gains
  • No third-party requests, no form and no fetch.
  • The gate fails inline script or style, on* handlers, eval and target=_blank without noopener.
Costs
  • Without a framework, language switching and animations are hand-written.
  • The security configuration lives in five places, and the gate has to check all of them.

Stack and why

Next.js 16 and React 19
A prerendered site in three languages and a dynamic panel in one project, with Server Actions for writes.
next-intl
Translated slugs, hreflang and messages in parity across the three languages.
Drizzle with D1 and SQLite
One data access layer that uses D1 in production and local SQLite in development.
Cloudflare Workers via OpenNext (D1, KV, R2)
Automatic deployment on every push to the main branch.
Argon2id in a pure implementation
The edge runtime refuses WebAssembly compiled at run time.
node:test and Playwright
Tests for passwords, contrast, analytics and the Server Actions guard; a browser run through the panel.
HTML, CSS and JavaScript without a framework
The landing page, with no dependencies and no build.

Results

  • A login that had never worked in production, diagnosed and fixed: the hash library compiled WebAssembly at run time, and the replacement kept the hash format, checked by a test against the old library.

    audited private repositoryThe repository's history and password test(Audit of the private repository, Sep 2026)
  • A test fails any exported Server Action without a guard or a justification, after the three queries reachable without a session were fixed.

    audited private repositoryTest and server-only module(Audit of the private repository, Sep 2026)
  • Proposal links with a 24-character token (about 143 bits), an optional password with lockout per document and a 404 for revoked, draft or nonexistent links.

    audited private repositoryCode of the secret-link pages(Audit of the private repository, Sep 2026)
  • A landing page of 115 KB on the first visit, the three fonts included, with no third-party requests.

    self-reportedMeasurement recorded in the project
  • 416 translation keys in parity across the three languages, with translated slugs and hreflang.

    self-reportedThe project's documentation
  • An end-to-end run through the 8 panel screens with a real login and no 5xx errors.

    self-reportedThe project's documentation

Security angle

Attack surface

  • Proposal and invoice pages opened by link, without an account.
  • A panel with leads, accounts, SEO and the audit trail.
  • The public diagnosis form and audience collection.
  • Server Actions, which become public endpoints.

Controls in place

  • A 24-character token, an optional password with lockout per document and a reading cookie scoped to the document's path.
  • Headers that forbid caching and indexing on the documents, and noindex on the whole panel.
  • Argon2id, sessions stored as the token's hash, lockout after failed attempts, a forced password change, CSRF and capability-based roles.
  • One guard for pages, another for actions and a test that fails any unguarded export.
  • An audit trail for logins, roles, SEO, proposals and invoices, with IP addresses stored only as hashes.
  • The document password's hash never reaches the editor in the browser.
  • A landing page with CSP default-src 'none', no unsafe-inline and Trusted Types.

What I would test today

  • Token enumeration and response differences between a revoked and a nonexistent link.
  • An editor or viewer calling the account and audit actions directly.
  • Reusing one proposal's reading cookie on another.

Evidence

  • audited private repositoryAudited private repositories (site and landing page)(Audit of the private repository, Sep 2026)