Public portfolio site (GitHub Pages) and evidence of my Solution Architecture development. This repo is the single source of truth for all public pages and shared assets under /assets/*.
- Static HTML pages (root and subfolders like
/about,/case-studies,/lab). - Shared assets: CSS, JS, images, fonts, partials in
/assets/*. - Section stub expansion via
assets/script/sections.jsfor consistent layouts. - CMS markers to define safe, editable regions.
- Static site hosted on GitHub Pages.
- Admin UI (
sa-portfolio-admin-ui) proxies/assets/*from this repo. - A CMS Worker reads/writes via GitHub PRs; no direct writes to
main.
Pages opt in to CMS editing with explicit markers:
<!-- CMS:START hero -->
...
<!-- CMS:END hero -->
<!-- CMS:START main -->
...
<!-- CMS:END main -->
Only content inside those markers is editable by the CMS. Everything else is read-only, which keeps layout and structure stable.
- Section stubs:
data-type="imgText",data-type="split50",data-type="twoCol". - Inline stubs:
div.img-stub(images),div.video-stub(video), anddiv.doc-embed(document embeds). - Rich blocks (accordions, doc cards, portfolio grids) are HTML fragments that the CMS can insert and re-serialize safely.
- The portfolio grid includes an embedded JSON payload for round-trip editing.
- RTE output is sanitized (no inline styles/scripts, no arbitrary iframes); rich content is inserted via tools to keep diffs deterministic.
- Admin preview loads the same partials and scripts as production to keep layout parity.
assets/script/dom-loader.jsinjects shared partials (nav, footer, etc).assets/script/sections.jsexpands.section,.img-stub,.video-stub, and.doc-embedstubs.assets/script/lightbox.jsinitializesjs-lightboxbehavior.
- Edit HTML directly for content and structure changes.
- Reuse section stubs and let
sections.jsexpand them at runtime. - Keep shared styles in
/assets/css/*so the public site and CMS preview stay in sync.
- Production uses the default branch on GitHub Pages.
- Separate Cloudflare Pages projects provide dev/staging with the same Access controls before changes are promoted to production.
devbranch → dev site (https://dev.portfolio.tacsa.co.uk).masterbranch → production site (https://portfolio.tacsa.co.uk).- The CMS worker targets the branch set via
GITHUB_DEFAULT_BRANCH.
- No secrets in the repo; all credentials live in Cloudflare environment settings.
- CMS updates are PR-only, enabling review, audit trails, and rollback.
- Separation of concerns: public site assets live here; admin-only logic lives in the admin repo.
- No arbitrary HTML insertion (CMS writes only validated block/inline stubs).
- No formatters/prettifiers touching CMS content.
- Never normalize whitespace inside
<pre>or<code>. - Serialization must be deterministic and idempotent (load → edit → save → reload).
- Baseline block order is immutable; “current” order is derived.
- Changes ship via version control and CI/CD, not direct edits.
- Asset ownership is centralized to avoid drift between repos.
- Canonical CMS block schema + serialization rules live in
docs/adr. - Key baseline decisions: ADR-013 (blocks), ADR-014 (RTE), ADR-015 (serializer).
- Single source of truth for
/assets/*avoids drift, but couples the admin UI to the public site’s availability. - CMS markers protect layout integrity, but limit edits to defined regions.
- PR-only writes improve auditability, but add a review step before publishing.
- Cloudflare Access gates CMS writes to reduce exposure of the GitHub API.
- Admin UI:
sa-portfolio-admin-ui(CMS front-end).
- Public site (prod): https://portfolio.tacsa.co.uk/
- Public site (dev): https://dev.portfolio.tacsa.co.uk/
- Admin (prod): https://admin.portfolio.tacsa.co.uk/
- Admin (dev): https://dev.admin.portfolio.tacsa.co.uk/
- Why markers? They create a clear editable boundary so the CMS can update content without risking layout/structure regressions.
- Why section stubs? They keep authoring simple while
sections.jsexpands consistent, production-ready markup.