Personal site of Donald Morton, built as three independent sites in one repo, deployed to Cloudflare Pages on separate (sub)domains:
| Directory | Stack | Domain | Role |
|---|---|---|---|
portfolio/ |
Hugo / Toha | donaldmorton.net + www.donaldmorton.net |
The homepage: splash + resume sections and blog. A Terminal navbar item links to the terminal. (Timeline lives here for now; final home TBD.) |
terminal/ |
Hugo / terminalCV | terminal.donaldmorton.net |
A CLI-styled companion / easter egg. Type startx to launch the desktop. |
os/ |
Vite / React / ProzillaOS | os.donaldmorton.net |
A graphical pseudo-OS desktop (windows, folders, apps), launched by startx. |
The portfolio's Terminal menu item (customMenus in
portfolio/data/en/site.yaml) opens /terminal.html, which embeds the terminal
in an iframe inside the Toha chrome. The terminal's startx command
(startxLocation in terminal/config.yml) navigates the top window to the
portfolio's /os.html, which embeds the ProzillaOS desktop the same way (a
larger window). Both embed pages — layouts/terminal/list.html and
layouts/os/list.html — define Toha's navbar/content blocks so the iframe
sits on the landing-page background with navbar + footer. The framed sites allow
this via frame-ancestors (terminal/static/_headers, os/public/_headers).
- Hugo extended ≥ 0.146 (
hugo versionshould say+extended) - Go ≥ 1.19 and Node ≥ 16 — required by the Toha portfolio only
- Clone with submodules (the terminal theme is a submodule):
git clone --recurse-submodules git@github.com:malcyon/donaldmorton.net.git # or after a plain clone: git submodule update --init
The whole site (portfolio + embedded terminal) runs locally with one command:
./dev.shThis starts all three dev servers — portfolio on http://localhost:1313,
terminal on http://localhost:1314, and the ProzillaOS desktop on
http://localhost:3000 (Vite) — and stops them all on Ctrl-C. The portfolio's
terminal embed (/terminal.html) and the terminal's startx redirect detect
hugo server (via hugo.IsServer) and automatically point at these localhost
URLs, so no config editing is needed. The first run also installs the portfolio's
npm assets and the os/ dependencies if their node_modules are missing.
To run them separately:
Portfolio (Hugo + Go modules + npm):
cd portfolio
hugo mod npm pack # generate package.json from theme modules
npm install # populates node_modules (fonts, flags, katex)
hugo server -p 1313Terminal (just Hugo):
cd terminal
hugo server -p 1314- Terminal CV / commands:
terminal/config.yml - Portfolio identity & hero:
portfolio/data/en/author.yaml - Portfolio resume sections:
portfolio/data/en/sections/*.yaml - Portfolio images/logos/avatar:
portfolio/assets/images/ - Timeline:
portfolio/data/timeline.yaml(rendered byportfolio/layouts/timeline/list.html+assets/css/timeline.css)
# terminalCV (submodule)
git submodule update --remote terminal/themes/terminalcv
# Toha (Hugo module)
cd portfolio && hugo mod get -u github.com/hugo-toha/toha/v4 && hugo mod tidyThe terminal deliberately keeps as few theme overrides as possible — each
file under terminal/layouts/ shadows the same path in the terminalCV
submodule, so it silently stops receiving upstream changes. Prefer
terminal/config.yml over copying templates. After bumping the submodule
(git submodule update --remote terminal/themes/terminalcv), re-check the files
below against the new theme version and re-apply the changes.
Currently based on terminalCV v3.8.0. Three overrides (largest first — the order to re-check after a theme bump):
-
terminal/layouts/index.html— full copy of the theme'sindex.html(~700 lines) with two changes: the optionalsourcecommand disabled (paired withsource: falseinconfig.yml), and thestartx/exitredirects changed fromwindow.locationtowindow.top.locationso they break out of the/terminal.htmlembed iframe (withstartxtargeting the local portfolio dev server underhugo server). The largest, most fragile override — re-check it first. Re-apply: copy the theme'sindex.html, remove thesourcereferences (the completion list entry, the help-map entry, thevar sourcedefinition, and thecase 'source'handler; keepsource: falseinconfig.yml), and in thestartx/exitcases changewindow.locationtowindow.top.location(wrap startx with thehugo.IsServer → http://localhost:1313/toggle). -
terminal/layouts/partials/head.html— copy of the theme'shead.htmlwith two changes: (a) all jquery.terminal CDN URLs pinned to a matching 2.45.2 (core,less.min.js, CSS) and jQuery pinned to 3.7.1 — the theme mixes unpinned/@latestURLs with pinned ones, and the version skew breaks thelesspager; (b) theautocomplete_menu.js<script>line removed, disabling the live autocomplete dropdown (Tab completion via core jQuery Terminalcompletionstill works). Re-apply: copy the theme'shead.html, pin every jquery.terminal/jQuery URL to a single matching version, and delete theautocomplete_menu.jsline. -
terminal/layouts/posts/single.html— copy of the theme'sposts/single.htmlwith one line changed to support araw: truefront-matter flag (shows a post's markdown source verbatim in a<pre>, like a realcat, instead of rendered HTML). Thisrawflag is ours; the theme has no such concept.- theme:
{{ .Content }} - ours:
{{ if .Params.raw }}<pre>{{ .RawContent }}</pre>{{ else }}{{ .Content }}{{ end }}
Re-apply: copy the theme's
posts/single.htmland swap that line. - theme:
Everything else is configuration, not an override — see terminal/config.yml.
os/ is a standalone Vite + React + TypeScript app built on the
prozilla-os library — not a Hugo
site. It renders a graphical desktop (windows, taskbar, file explorer, apps) and
is what startx opens. Key files:
src/components/App.tsx— mounts<ProzillaOS>; setsystemName/tagLinehere.src/config/appsConfig.ts— which apps appear (add/remove built-ins or custom apps).src/config/skin.ts— wallpaper / theming.
Develop with npm run dev (or ./dev.sh from the repo root, port 3000); build
with npm run build → dist/. See docs.prozilla.dev
for custom apps and seeding the virtual filesystem with folders/files.
Cloudflare Pages gives each project a single build command, so this repo is deployed as three Pages projects (all connected to this same repo, each with its own "Root directory"):
| Project | Root directory | Build command | Output | Custom domain |
|---|---|---|---|---|
| portfolio | portfolio |
npm ci && hugo --minify |
public |
donaldmorton.net + www.donaldmorton.net |
| terminal | terminal |
hugo --minify |
public |
terminal.donaldmorton.net |
| os | os |
npm ci && npm run build |
dist |
os.donaldmorton.net |
Environment variables:
- portfolio + terminal:
HUGO_VERSION=0.162.1,HUGO_EXTENDED=true - portfolio also:
GO_VERSION=1.22(Toha is a Hugo module, fetched via Go at build),NODE_VERSION=18 - os: Node ≥ 20 (Vite 7 requires it; pinned via
os/.node-version)
Notes:
- The output directory is relative to the root directory (Cloudflare serves
terminal/public,portfolio/public, andos/dist). - The terminalCV submodule is cloned by Pages automatically.
- By default all three projects rebuild on every push. To avoid that, set each
project's Build watch paths to its own subdir (e.g.
terminal/*,portfolio/*,os/*). - Fallback if the Pages image's Go ever causes trouble: run
cd portfolio && hugo mod vendor, commit_vendor/, and the portfolio builds with no Go dependency (also pins the theme version).