158 lines
12 KiB
Markdown
158 lines
12 KiB
Markdown
# Tech Context - 2RE03 Portfolio Site
|
|
|
|
> Technologies, development setup, constraints, dependencies, and tool usage.
|
|
> Last updated: 2026-09-22.
|
|
|
|
## Current State
|
|
A working static-site scaffold exists at the repo root:
|
|
|
|
```
|
|
index.html work.html about.html services.html contact.html case-studies.html
|
|
case-studies/*.html (10 per-project case study detail pages)
|
|
css/bootstrap.min.css css/style.css
|
|
js/bootstrap.bundle.min.js js/main.js js/case-studies.js js/carousel.js
|
|
fonts/Inter-latin.woff2 fonts/SpaceGrotesk-latin.woff2
|
|
img/ 50 files: 45 WebP, `printtiresad.png`, 3 icon assets (`favicon.svg`,
|
|
`favicon.ico`, `apple-touch-icon.png`), and the social card `og-image.png`.
|
|
The 45 WebP cover 10 case-study hero backgrounds, 8 homepage collage tiles,
|
|
and 28 project/screenshot images.
|
|
```
|
|
|
|
No build step and no package manager - it is plain static HTML/CSS/JS.
|
|
|
|
## Reference Stack Seen (in the original `refrence/` build)
|
|
> `refrence/` (temporary source material) was **removed** on 2026-09-10 before the
|
|
> first commit, and is backed up outside the repo at
|
|
> `/home/torrey/2RE03-unused-assets-backup/refrence/`.
|
|
- Hand-authored HTML.
|
|
- Bootstrap 5 (`css/bootstrap.min.css`, `js/popper.min.js`, `js/bootstrap.min.js`)
|
|
- referenced via relative paths that are **not present** in this repo.
|
|
- A custom stylesheet (`css/style.css`) and a custom carousel script
|
|
(`js/series-carousel.js`) - also not present here.
|
|
- Inline JSON `<script type="application/json">` blocks feeding the carousel.
|
|
|
|
## Technologies Used
|
|
- **HTML5** - hand-authored; six pages; semantic landmarks; skip link.
|
|
- **CSS** - Bootstrap 5.3.3 (vendored) + custom `css/style.css`.
|
|
- **JavaScript** - Bootstrap bundle + `js/main.js` (form handling) +
|
|
`js/case-studies.js` (case-study hover preview) + `js/carousel.js`
|
|
(scroll-snap carousels).
|
|
- **Fonts** - Inter + Space Grotesk (variable `woff2`), self-hosted in `fonts/`.
|
|
- **Theme** - palette centered on `#2ee666`, defined as tokens in `:root` in
|
|
`css/style.css`.
|
|
- **Forms** - Web3Forms (AJAX submit via `fetch`).
|
|
|
|
## Development Setup
|
|
- No build step. Serve statically, e.g. `python3 -m http.server` from the repo
|
|
root, then open `http://localhost:8000/`.
|
|
|
|
## Version Control
|
|
- Git repo, default branch `main`.
|
|
- Remote `origin`: `ssh://git@git.2re.top:22222/2re/2RE03-Design.git` (Forgejo at
|
|
`git.2re.top`, SSH on the non-standard port `22222`). Auth is by the SSH key
|
|
`~/.ssh/id_ed25519`; the server returns "does not provide shell access", which
|
|
is normal for Forgejo.
|
|
- `.gitignore` ignores OS/editor cruft only. There is no `refrence/` entry because
|
|
that folder was removed.
|
|
|
|
## Image Pipeline
|
|
- Every production image is **WebP** except `img/printtiresad.png`, which stays PNG
|
|
because every WebP encode of it came out *larger* (the PNG is only 73 KB).
|
|
- Encoding recipe (`cwebp`): long side capped at **1600px**, `-q 82` for opaque
|
|
images, `-q 90 -alpha_q 100` for anything with transparency.
|
|
- Result: `img/` went from ~20 MB to **3.2 MB** (85% smaller) with no visible loss
|
|
(measured SSIM distortion 0.0003 to 0.018, where 0 is identical).
|
|
- The original JPEG/PNG files are kept **outside** the repo at
|
|
`/home/torrey/2RE03-unused-assets-backup/img-webp-originals/`.
|
|
- Most `<img>` tags declare the **display frame**, not the file's native size: the
|
|
carousel cards are a 4:3 box (`.carousel__media`, `object-fit: cover`) so they
|
|
say `800x600`, and the hover-preview thumbnails say `88x66`. Those attributes are
|
|
deliberate and are *not* expected to match the file's own dimensions.
|
|
|
|
## Icon & Social Assets
|
|
- Icon files in `img/`, all derived from the site's own wordmark font:
|
|
- `favicon.svg` - a `#2ee666` rounded tile (`rx` 112 of 512) holding the digit `2` as **outline paths** in brand ink (`#0e1511`), so it renders identically with no client font installed.
|
|
- `favicon.ico` - the same mark rasterized at 48, 32, and 16 px, for older browsers and Windows pinned tabs.
|
|
- `apple-touch-icon.png` - 180x180, square and opaque, because iOS applies its own corner mask.
|
|
- Recipe (build-time only; no script is committed, matching the image pipeline above):
|
|
1. Instance `fonts/SpaceGrotesk-latin.woff2` at `wght=700` with `fontTools.varLib.instancer`. This step is required: the file is a variable font whose default instance is Light (300), so an unmodified read renders the mark too thin beside the site's 700 headings.
|
|
2. Take the `2` glyph's outlines through `fontTools.pens.svgPathPen.SVGPathPen` with a y-flip `TransformPen`, sizing the digit to ~56% of the tile and centring it on its ink bounds.
|
|
3. Rasterize with `rsvg-convert`, then build the `.ico` with `convert -define icon:auto-resize=48,32,16`.
|
|
- Rationale: the full `2RE03` wordmark is unreadable at 16 px and `2RE` is not much better, so the icon uses the single leading digit; ink-on-green mirrors the site's heading-on-green treatment.
|
|
- Every page declares all three with relative paths (`img/...` at the root, `../img/...` in `case-studies/`). There is deliberately **no** separate root-level `favicon.ico` copy; browsers follow the declared tags.
|
|
|
|
### Social card (Open Graph)
|
|
- `img/og-image.png` - **1200x630**, the 1.91:1 size the platforms expect.
|
|
- Built to look like the site's hero rather than a generic card: the 120 degree green gradient, the faint ink dot grid at an 18px pitch, the `DESIGN STUDIO` eyebrow with 0.18em tracking, the `2RE03` wordmark, the hero line, `2re03.com`, and a 130px strip of six real work tiles (`collage-1..6.webp`, cropped to fill) under a green wash of 0.86 to 0.95 so it reads as texture rather than noise.
|
|
- Rendered with PIL from the same instanced fonts (Space Grotesk 700 for the wordmark, Inter 500 for the hero line, Inter 600 for the eyebrow and the domain), with each element placed by its measured ink bounds instead of fixed offsets.
|
|
- Every page declares it as `og:image` together with `og:image:width`, `og:image:height`, `og:image:alt` and `twitter:card=summary_large_image`, on absolute URLs.
|
|
- The same generator can produce a per-project card from a case study's `hero-*.webp` plus its title if that is ever wanted; today every page shares this one card.
|
|
|
|
## Deployment
|
|
- The site is **published at https://2re03.com/** (hosted by the user). Confirmed 2026-09-22.
|
|
- The host serves **`.html` URLs**: `https://2re03.com/work.html` returns 200 while `https://2re03.com/work` returns 404. Canonical and Open Graph URLs therefore use the `.html` form, with the bare root (`https://2re03.com/`) for the homepage.
|
|
- Deploys are **manual**. The icon set and social card went live on 2026-09-22 (commit `8a7c3ea`, uploaded by the user), and the deploy was verified from the outside: `img/favicon.svg` 200 (`image/svg+xml`, 2.1 KB), `img/favicon.ico` 200 (15 KB), `img/apple-touch-icon.png` 200 (3 KB) and `img/og-image.png` 200 (176 KB), every one of the 16 pages returns 200 with exactly one `og:image` and two `rel="icon"` links, `work.html` serves all 26 captions, `services.html` serves the new Workflow band, and all 61 unique local asset paths the pages reference (images, CSS, JS, fonts) return 200 live with no 404s.
|
|
- No build step, so a deploy is a straight copy of the repo root. Uploading the whole folder also puts `memory-bank/` (which now includes the backlog, `memory-bank/todo.md`), `.clinerules/`, and the site files on the server; that is intentional, not accidental.
|
|
|
|
## Dependencies
|
|
- Bootstrap 5.3.3 CSS + JS bundle - vendored locally (no CDN / no runtime).
|
|
- Web3Forms - external form endpoint (`https://api.web3forms.com/submit`) with a
|
|
public access key stored in `contact.html`.
|
|
- No package manager or lockfile.
|
|
|
|
## Technical Constraints
|
|
- `refrence/` was removed before the first commit; keep the site free of any
|
|
references to it (all production assets live under `img/`).
|
|
- Output should be lightweight and static unless a decision says otherwise.
|
|
- Work data should have a single source of truth.
|
|
|
|
## Code Style
|
|
- **Soft wrap, do not hard wrap.** There is no column limit (~80 chars or otherwise). Do not insert line breaks to keep a line short: keep each logical unit (a JS statement, an HTML tag, a CSS rule, a list item, a sentence or paragraph) on one line and let the editor soft wrap it. A line break should mark a structural boundary, never a width boundary.
|
|
- **Applies to** HTML, CSS, JS, and Markdown writing, including the memory bank and its `todo.md`.
|
|
- **Going-forward rule only (set 2026-09-22).** The existing files are hard-wrapped at roughly 80 chars and stay that way. Do not run a reformat pass over them unless the user asks for one.
|
|
|
|
## Tool Usage Patterns
|
|
- **Never edit files outside the project folder.** All writes (create, edit, move,
|
|
delete) stay under `/home/torrey/Documents/Sites/2RE03`. Reading files elsewhere
|
|
is allowed; writing is not. If a task seems to need an outside write, stop and
|
|
ask first, naming the path and the reason. This includes the external asset
|
|
backup at `/home/torrey/2RE03-unused-assets-backup/`.
|
|
- **Never `git commit` or `git push` without explicit approval from the user.** Make
|
|
the edits, verify them, then stop and report; leave the work uncommitted until
|
|
told otherwise. Approval is per action, not standing.
|
|
- Follow project conventions once established; verify each change (validate HTML,
|
|
check asset paths, check responsive behavior) before reporting done.
|
|
- **No Node.js on this machine.** `node` is not installed (found 2026-10-01, which
|
|
supersedes the `node --check` wording in earlier entries). To syntax-check a JS
|
|
file, parse it with the installed **gjs** (SpiderMonkey), which compiles without
|
|
executing:
|
|
`gjs -c 'const Gio=imports.gi.Gio; const [ok,d]=Gio.File.new_for_path("js/main.js").load_contents(null); new Function(new TextDecoder().decode(d));'`
|
|
No output means it parses; a parse error is printed.
|
|
- **Page harness (python3, no browser):** the standing check is tag balance plus
|
|
reference resolution across all 16 pages (root `.html` plus `case-studies/`),
|
|
run with `html.parser`: each start tag is pushed and matched against its end tag
|
|
(void elements skipped), and every local `href`/`src` is resolved from the file's
|
|
own folder. Expect `pages with tag problems: 0` and `unresolved references: none`.
|
|
Site files are then scanned for **any** non-ASCII character, which catches em
|
|
dashes, en dashes, curly quotes and non-breaking spaces in one pass (the only
|
|
legitimate non-ASCII in the site is the `é` in `case-studies/silver-lining.html`).
|
|
|
|
### Screenshots (headless Firefox)
|
|
- **Use `.shots/shoot.sh`.** It shoots any page at both widths and writes a fold
|
|
shot plus a full-page shot into the untracked `.shots/` folder:
|
|
`.shots/shoot.sh services.html work.html` (defaults to `services.html contact.html`;
|
|
add `PORT=9000` if 8199 is taken). It starts its own local server if none is
|
|
running, and `.gitignore` keeps `.shots/` out of the repo.
|
|
- **Why it is built this way** (all three learned the hard way on 2026-10-01):
|
|
1. This machine has no Chrome and its Firefox is a **snap**, which cannot write
|
|
to `/tmp`, so the shots run on a throwaway profile at `.shots/ffprof` inside
|
|
the repo. The real Firefox profile is never touched.
|
|
2. Firefox's `--screenshot` captures **exactly the `--window-size` box and does
|
|
not scroll**, so a full-page shot has to be taken taller than the page and
|
|
then trimmed: `.shots/trim.py` removes the trailing blank rows instead (the
|
|
fold shots are left alone).
|
|
3. `--screenshot` needs an **absolute** path. A relative one is written
|
|
somewhere else, silently, with exit code 0.
|
|
- Shot sizes: 1280px wide (fold 1200, full 5000 tall) and 390px wide (fold 844,
|
|
full 8000 tall), then trimmed to the page's real height. Read the PNGs directly
|
|
(VS Code preview, or `xdg-open .shots/services-1280-full.png`).
|