Case Study / Build 08
Client Portal AI Build
A secure consultancy client portal bringing together requests, retained hours, documentation, invoices, and delivery evidence in one simple workspace.
Greg's take
A support portal for client retainers sounds simple until it has to handle requests, shared visibility, billing context, documentation, identity, audit trails, and a reliable data layer.
Most teams solve those pieces with separate tools. The result is a client relationship managed across disconnected systems with no single view.
The production system now runs on a Cloudflare-native architecture: Pages, Access, Workers, D1, and R2. It gives live customers a simple workspace without Jira or Zendesk complexity.
Build milestones
Version 1 production delivery is complete.
Secure Client Portal
Cloudflare Access authentication
Client dashboards
Requests
Threaded comments
Request attachments
Documentation library
Document downloads
Invoice history
Invoice downloads
Retainer tracking
Billing
Activity timeline
Admin portal
Cloudflare D1
Cloudflare R2
Tenant isolation
Production hardening
Security review complete
Red-team review complete
Cloudflare dashboard checks
Governance Pack presentation
Admin audit export
Client analytics
The problem
Support managed by email. No shared visibility.
No client visibility
Clients had no shared view of open requests, progress, or history. Every status update required an email exchange.
No billing transparency
Hours logged, budget consumed, and remaining retainer balance were only visible in spreadsheets that had to be shared manually.
No documentation layer
SOPs, process notes, and technical references existed in files and Notion - not in a client-facing, versioned system.
No shared client instance
Multiple stakeholders from the same client organisation had no shared workspace to see common requests and shared resources.
02 / The system
A business system. Not a portal UI.
The system was built to provide genuine operational value - shared visibility, structured data, Cloudflare Access authentication, tenant isolation, durable documentation, and operational controls - not just a frontend that looks like a portal.
Multi-client shared instance model
Everyone attached to the same client account sees the same requests, status updates, billing summary, documentation, and downloads. No separate admin panel required to share visibility.
Request lifecycle with structured status
Requests move through defined states: submitted, in review, in progress, blocked, completed. Each state change is recorded. Comments are threaded against requests, not floating in email.
Billing and hours visibility
Hours logged against requests are visible to clients in context. Retainer balance, hours consumed, and hours remaining are surfaced at the account level without a finance email.
Documentation system
Durable documentation with metadata and body endpoints. SOPs, technical references, process notes, and file assets live in a client-specific workspace rather than being scattered across email, shared drives, Jira, and Confluence.
Cloudflare Access authentication
Client access stays simple while the security layer remains enterprise-grade: Cloudflare Access, JWT validation, client-specific visibility, and no heavy enterprise tool rollout.
Admin controls and audit logging
Admin view with full request management, status override, hours adjustment, and activity log. Every change is timestamped and attributed.
Product philosophy
Why we built it differently.
Most client portals focus on tickets. This portal focuses on the consultancy relationship.
Clients can immediately see remaining hours, current requests, documentation, invoices, and recent activity without learning Jira, Zendesk, or another heavy delivery platform.
The goal is low operational overhead: enough structure to make delivery visible, with none of the complexity that turns a support workspace into a system clients have to be trained to use.
How it works
Cloudflare-native production stack with low operational overhead.
System architecture
Cloudflare Pages
Production frontend hosting
Cloudflare Access
Authentication, JWT issuance, access control
Workers API
Requests, comments, hours, documents, invoices, admin, activity
Data and file layer
Cloudflare D1
Structured records and tenant data
Cloudflare R2
Attachments and document downloads
Frontend
API
Database
File storage
Identity
04 / Delivery progression
From legacy browser layer to production platform.
Legacy browser-only state was replaced by the production Cloudflare platform in controlled slices. Each completed slice had acceptance criteria and a QA gate before live customer use.
Legacy browser-local layer
CompletedEarly UI state used browser-local storage to validate the workspace model and data structure before the production data layer was wired.
Cloudflare Access / JWT identity layer
CompletedCloudflare Access added as the identity provider for portal.greg-staunton.com. JWT validation middleware built into Workers. Test auth flows verified before any data APIs were wired.
D1 database schema and base Workers API
CompletedD1 schema defined for requests, comments, hours, users, and documents tables. Base Workers API with routing and JWT middleware. Data migration from localStorage state verified in test environment.
Request and comment migration to D1/API
CompletedRequest creation, status changes, and threaded comments moved from localStorage writes to D1 API writes. Frontend updated to use fetch() against Workers API with JWT in headers. QA pass on create, read, update, and delete paths.
Hours logging and documentation endpoints
CompletedHours logging against requests moved to API/D1. Documentation metadata and body endpoints added. Client-facing billing summary calculated server-side and returned via API rather than computed from localStorage.
Production hardening pass
CompletedProduction hardening covered authentication handling, error states, loading states, empty states, and edge case behaviour across request flows.
R2 file attachment foundation
CompletedCloudflare R2 added as the object storage layer for request attachments and document assets. D1 remains the structured database for metadata, users, requests, comments, billing, and audit records.
Cloudflare dashboard checks, evidence, governance, and analytics
NextThe remaining operational items are platform-layer Cloudflare checks, Governance Pack presentation, Admin audit export, and Client analytics.
05 / AI-assisted delivery
How AI was used in this build.
AI assistance was used throughout, but with clear human decision points at architecture, QA, and deployment. The Tanya Build Cockpit provided the structured scaffolding that made each session productive.
Architecture design
AI used for architecture option comparison: localStorage-only vs. D1-backed vs. full Cloudflare stack. Trade-offs documented. Human decision made before build started.
API implementation
Workers API routes generated with AI assistance using structured implementation packets - each route specified with method, auth requirement, request shape, and response contract before code generation.
D1 schema and migration
Schema design reviewed against the data model and access patterns before finalisation. Migration scripts generated and verified in test D1 environment before production deployment.
QA and hardening
AI used to generate QA checklists for each build slice, then human-run against the actual system. Issues found were fixed before the slice was marked complete.
06 / Production hardening
Production security hardening and red-team review complete.
This was not a scanner-only exercise. The review treated the portal as a live production client portal and tested the trust model from the browser, API, database, file storage, and deployment layers.
Automated checks passed, the dependency audit returned no production vulnerabilities, the final red-team/code review found no remaining critical, high, or medium repo-code findings, and live login testing verified the production portal path. The remaining tracked items are Cloudflare dashboard configuration checks outside the repository.
Production authentication boundary verified
Cloudflare Access remains the production authentication boundary, with D1-backed identity and role resolution behind it.
Server-side tenant isolation strengthened
Tenant access is resolved server-side through D1 client assignment rather than browser-held state.
Fallback access paths removed
Legacy browser/session fallback paths and old prototype credential remnants were removed from production paths.
Test fixtures isolated
Review fixtures and non-production data were isolated away from live paths, with real company names removed from tests and review artefacts.
CSV and HTML output hardened
CSV formula-injection protection and HTML quote escaping were added, tested, and included in regression coverage.
File handling tightened
Uploaded filename handling now includes server-side sanitisation and control-character rejection before storage use.
Evidence / Governance
A real business system with real operational constraints.
The Client Portal is the most complex build in the pl8ypus portfolio. It is a production system with live customers using it.
It shows multi-layered system thinking
Identity, API, database, file storage, admin controls, audit logging, and frontend UI all have to work together. The architecture decisions at each layer have to account for the layers above and below.
It shows controlled migration discipline
The successful move from legacy browser-local state to Cloudflare D1 and R2 shows the same migration discipline needed inside real customer environments. Big-bang rewrites are not an option with live users.
It shows AI-assisted delivery at scale
A system of this complexity - six build slices, multiple data models, Cloudflare infrastructure, identity layer - was built with AI assistance throughout. The Tanya Build Cockpit system was the operational scaffold that made it possible.
It is honest about its current state
R2 object storage, D1 records, Access authentication, tenant isolation, repository hardening, and production security review are complete. The remaining tracked work is limited to Cloudflare dashboard checks plus evidence, governance, audit export, and analytics layers.
Real client workflow
Built around Greg's real support and retainer model.
The Client Portal is not a portfolio piece designed to look like a real system. It is built around Greg's real support and retainer workflow - the one used with actual clients. The scope, the feature set, and the data model came from real operational needs, not from a case study brief.
That means the portal handles real requests, real documentation, real billing context, invoice downloads, shared account visibility for real client contacts, and the Cloudflare infrastructure that supports it in production, including D1 for structured records and R2 for file/object storage.
Requests come from real clients
The request lifecycle - submit, in review, in progress, blocked, completed - was designed around how Greg's client retainer support actually works, not a hypothetical workflow.
Billing context is real
Hours logged, retainer balance, and consumed time are surfaced for real client accounts - not placeholder numbers in a mockup designed to look believable.
Documentation is real
SOPs, process notes, and technical references served through the portal are the same documents that would otherwise live in email attachments and shared drives.
Multiple client contacts on the same account
The shared client instance model was designed because real client organisations have more than one person who needs visibility. That constraint shaped the data model from day one.
Delivery was driven by real operational pressure
Each production slice was prioritised by what a real client workflow actually needed - not what made a good portfolio story. Request writes came first because that is what clients use most.
Hardening was done for real users
The production hardening pass covered authentication boundaries, server-side tenant checks, file handling, export safety, escaping, repository hygiene, and live login verification because real users would encounter these paths.
Greg's take
A client portal sounds simple until it has to behave like a real support system. Requests, updates, documents, billing visibility, attachments, admin controls, audit trails, identity, and multiple people from the same organisation who all expect to see the same data.
That is where shallow portal builds break: they look good in a screenshot, handle one user on a good day, and have no plan for when the session expires, the attachment needs to persist, or someone from finance asks why their hours do not match the invoice.
This build moved slice by slice into a Cloudflare-backed production system. Each slice had acceptance criteria. Each delivery step had a verification gate. The latest security review removed legacy remnants, isolated test fixtures, tightened repository posture, and left the production trust model explicit, testable, and reviewable.
The test of a portal is not whether it looks professional in a screenshot. The test is whether a real client with a real question can find their answer without sending an email. That is the bar this build was designed to clear.
Production evidence
Capabilities shown by this build.
Architecture
- Cloudflare-native stack design (Pages + Workers + D1 + R2 + Access)
- Multi-tenant data model with org-level isolation
- JWT-based identity with middleware validation pattern
Build discipline
- Slice-by-slice delivery with working state at every step
- Acceptance criteria defined before each production slice starts
- Production hardening pass as a distinct build phase, not an afterthought
AI-assisted delivery
- AI used at architecture, implementation, QA, and documentation layers
- Structured prompt patterns and project memory maintained across sessions
- Human decision points at every architectural and deployment choice
Operator readiness
- Non-technical clients can manage requests and view billing without training
- Admin controls and audit log designed for operational oversight, not developer use
- System state honest and visible - no hidden complexity or magic behaviour
Interested in a similar build?
For enterprise portal builds, Cloudflare infrastructure, applied AI systems, or marketing operations workflow design.