Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .claude/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"version": "0.0.1",
"configurations": [
{
"name": "portfolio-dev",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"port": 3000
}
]
}
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,16 @@ skills-lock.json

# Personal files — kept on this computer only, never published
claudecode_jumpstart.docx

# Resumes — contain personal contact info; never publish to the public repo
*Resume*
*resume*

# Private folder — everything in here stays on this computer, never published
Private Random Stuff/

# Personal photo used on the resume — keep private
headshot.*

# Session handoff notes — local only, never published
SESSION_TURNOVER.md
5 changes: 5 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!-- BEGIN:nextjs-agent-rules -->
# This is NOT the Next.js you know

This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
<!-- END:nextjs-agent-rules -->
30 changes: 30 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!-- managed-by: phased-workflow -->
# Portfolio — Francisco Cardenas

@AGENTS.md

## Active phase
**Perspective-room redesign** (ADR-0002). **Phase 1: Room shell & camera — done** (signed off 2026-06-20; left-wall glitch fixed, global pull-back, left→right tour order — ADR-0006). Next: **Phase 2 — Hero objects: poster + flag** (planned, not started).

## Pointers
- Plan: [docs/00_plan.md](docs/00_plan.md)
- Decision log: [docs/decisions/](docs/decisions/)
- Current turnover: [docs/artifacts/handoffs/2026-06-20_phase1-closeout.md](docs/artifacts/handoffs/2026-06-20_phase1-closeout.md)

## Phase index
| # | Name | Status | Closeout date | Phase file |
|---|------|--------|---------------|------------|
| 1 | Room shell & camera | done | 2026-06-20 | [docs/01_room-shell-and-camera.md](docs/01_room-shell-and-camera.md) |
| 2 | Hero objects: poster + flag | planned | — | tracked in [docs/00_plan.md](docs/00_plan.md) |
| 3 | Furnish & populate sections | planned | — | tracked in [docs/00_plan.md](docs/00_plan.md) |
| 4 | Lighting, polish, responsive, a11y | planned | — | tracked in [docs/00_plan.md](docs/00_plan.md) |
| 5 | Content finalize & ship | planned | — | tracked in [docs/00_plan.md](docs/00_plan.md) |

## Standing rules
- **Full planning, hands-on execution (ADR-0003, supersedes ADR-0001):** locked plan + phases + decision log + handoffs, but build in the main session (no orchestration subagents) for the live-preview design loop. Commit per phase.
- Redesign = looks-3D perspective room assembled in the browser (CSS 3D), NOT real-time 3D (ADR-0002).
- All paths use forward slashes.
- Free-tier services only (Vercel hobby); CC0 assets only — no paid SaaS without an ADR.
- Don't commit/push/deploy until Francisco says so.
- Turbopack cache goes stale on CSS/font edits — stop server, `rm -rf .next`, restart.
- `Private Random Stuff/` is git-ignored (résumés, references, raw textures) — never commit it.
184 changes: 0 additions & 184 deletions Francisco Cardenas - Portfolio (standalone).html

This file was deleted.

57 changes: 54 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,56 @@
# Projects
# Francisco Cardenas — Portfolio

Personal portfolio website.
Personal portfolio website — **"The Drawing Set"**, an interactive architectural
drawing sheet you drag across, with a slide-out detail panel and a one-page résumé view.

🚧 **Under construction** — building with Next.js.
Built with Next.js, React, TypeScript, and Tailwind CSS.

## Run locally

```
npm install
npm run dev
```

Open http://localhost:3000.

## Edit content (the easy part)

**Almost everything you'd want to change — your name, wording, jobs, skills,
links, and which photo goes where — lives in ONE file:**

```
src/content/site.ts
```

Open it, change the text between the `"quotes"`, save, and the site updates. You
do not need to touch any other file for normal edits.

## Edit images

Photos live in:

```
public/images/
```

To swap a photo, drop the new image into `public/images/` and update the matching
path in `src/content/site.ts`. To replace a photo without changing any code, give
the new file the **same filename** as the old one.

## How it's organized

- `src/content/site.ts` — all the editable text, links, and image paths.
- `src/components/Portfolio.tsx` — the interactive blueprint design (you rarely edit this).
- `src/app/globals.css` — the colors and styles. The four color themes are at the very top.
- `src/app/layout.tsx` — fonts and the browser tab title.

## Build

```
npm run build
```

## Deploy

Hosted on Vercel. Every push to `main` redeploys the live site automatically.
82 changes: 82 additions & 0 deletions docs/00_plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Portfolio — Plan

> **Redesign in progress (ADR-0002).** The site is being rebuilt from a flat 2D elevation into a
> perspective room. Running full planning, hands-on execution (ADR-0003).

## Product summary
Francisco Cardenas's personal **portfolio website** — a **room you peer into**, rendered with real
perspective depth and warm, cozy evening light, that an employer scrolls through to **focus on and
inspect personal objects** which tell his story (who he is, work he's done, goals ahead). Personal
but professional. For: employers and recruiters in civil engineering / construction. **v1 success =
live on Vercel, reads convincingly as a real lived-in room on desktop and mobile, gives a glimpse of
Francisco while staying professional, LinkedIn + email correct.**

## Look & feel (from ADR-0002 + Q&A 2026-06-19)
- **Approach:** perspective room *assembled in the browser* — looks 3D, but not real-time 3D.
- **Camera:** fixed corner-of-room view; scrolling glides/zooms focus between objects.
- **Mood:** warm evening — lamps & string lights, soft shadows, cozy.
- **Detail:** lived-in but curated (personal, still reads professional).
- **Color:** the 4-theme system is dropped; one basic warm/cozy scheme for now (Francisco, 2026-06-19; revisit later).
- **References:** `Private Random Stuff/Rooms/` (Life is Strange / Edith Finch energy — *look only,
not content*). Honest target: a stylized-realistic interpretation, not a pixel-match to AAA renders.
- **Keep:** the Spider-Verse poster; a realistic Colombian flag; all current sections.

## Stack
- Runtime / language: Node + TypeScript
- Framework: Next.js (unconventional version — see AGENTS.md; read `node_modules/next/dist/docs/` first)
- Styling: plain CSS (`src/app/globals.css`) — perspective via **CSS 3D transforms**; no UI library, no WebGL
- Dev server: Turbopack
- Database: none — content static in `src/content/site.ts`
- Auth: none
- Hosting / deployment: Vercel (hobby / free tier)
- Repo: github.com/BootySaturn/Projects (origin/main)
- Assets: CC0 only (Poly Haven, ambientCG, similar). Source maps/cutouts, downscale to web tiles
(sharp) into `public/textures/` & `public/images/`. Originals stay in git-ignored `Private Random Stuff/`.

## Data model
Static only. Text/links live in `src/content/site.ts`. No database, no CMS, no user data.

## Browser / device targets
Modern evergreen browsers, desktop + mobile responsive.

## Cross-cutting decisions
- Budget: free tier only (Vercel hobby); CC0 assets only.
- Data sensitivity: none beyond public contact info (email, LinkedIn — confirmed public 2026-06-18).
- Regulatory / offline / i18n: none.
- Accessibility: target **WCAG 2.1 AA** (alt text, contrast, keyboard navigation) — Phase 4.
- Workflow: full planning + decision log + handoffs; **hands-on execution in the main session**
(ADR-0003). Go-all-in on usage. Commit per phase; push/deploy only on Francisco's say-so.

## Out of scope (v1)
- Real-time / free-roam 3D (game engine, WebGL)
- CMS / accounts / analytics / blog / contact-form backend
- i18n / localization

## Definition of Done (project-wide)
- [ ] Reads convincingly as a real, lived-in perspective room (depth + warm light) on desktop AND mobile.
- [ ] Every section reachable by focusing/inspecting its object; poster + realistic flag present.
- [ ] LinkedIn + email correct and live. (confirmed 2026-06-18)
- [ ] WCAG 2.1 AA basics: alt text, readable contrast, keyboard-navigable.
- [ ] No leftover `TODO`/`FIXME` in shipped code; assets reasonably optimized for web.
- [ ] README explains what the site is + how to run/deploy.
- [ ] Committed, pushed, deployed live on Vercel.

## Phase list
| # | Name | Objective | Complexity | Status |
|---|------|-----------|-----------|--------|
| 1 | Room shell & camera | Build the perspective room shell (walls + floor in CSS 3D, warm lighting) and the fixed-camera, scroll-to-focus navigation. **De-risks the approach.** | L | done (2026-06-20) |
| 2 | Hero objects: poster + flag | Place the Spider-Verse poster and a realistic Colombian flag on the wall in correct perspective; wire the inspect/zoom-into-object interaction. | M | planned |
| 3 | Furnish & populate sections | Add the remaining room objects (sourced CC0 furniture/props) mapped to the sections; each opens its content. | L | planned |
| 4 | Lighting, polish, responsive, a11y | Final lighting/shadow/depth pass, mobile layout, performance (asset budgets), accessibility. | M | planned |
| 5 | Content finalize & ship | Lock content/copy, README, commit, push, deploy to Vercel. | S | planned |

> Phase files: `docs/0N_<name>.md`. Phase 1 skeleton at [docs/01_room-shell-and-camera.md](01_room-shell-and-camera.md).
> Prior v1 polish (photo brick/wood, poster, fabric flag, zoom-into-object interaction) carries
> forward as inputs/assets to the redesign.

## Deferred questions
| # | Question | Status / revisit |
|---|----------|------------------|
| 1 | Exact object → section mapping (which item opens which section) | OPEN — Claude proposes in Phase 3, Francisco tweaks |
| 2 | Which personal props to include | RESOLVED (2026-06-19) — carry over the existing objects (bed, desk, dresser, shelf, hard hat, skates, soccer ball, window, door, etc.); Francisco will revise later |
| 3 | Color themes | RESOLVED (2026-06-19) — drop the 4-theme system; use one basic warm/cozy scheme for now, revisit later |
143 changes: 143 additions & 0 deletions docs/01_room-shell-and-camera.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Phase 1: Room shell & camera

## Locked plan
(Frozen at plan time. Design changes during execution are recorded as ADRs in `docs/decisions/`.)

### Objective
Build a convincing perspective **room shell** (walls + floor in real depth) with warm cozy lighting,
and the **fixed-camera, scroll-to-focus** navigation — proving the assembled-perspective approach
(ADR-0002) before any furnishing.

### Inputs
- ADR-0002 (perspective room), ADR-0003 (workflow mode), ADR-0004 (materials + desktop-first), Q&A answers (2026-06-19).
- References: `Private Random Stuff/Rooms/Room 1–3.jpg` (look only).
- Existing assets: existing scene/scroll engine in `src/components/Portfolio.tsx`; zoom-into-object
interaction + globals.css. NOTE (ADR-0004): the brick/wood photo textures are **dropped** — do not
reuse them.
- CC0 sources only if plain CSS material can't sell a normal nice room (Poly Haven, ambientCG).

### Skills to load
- `frontend-design` (aesthetic direction for the perspective scene + lighting).

### Steps
1. Spike a CSS 3D room shell: back wall + one side wall + floor as planes under a shared
`perspective`, fixed corner camera. Confirm depth reads correctly (de-risk gate).
2. Surface the planes as a **normal nice room** (ADR-0004): painted/plaster walls in a warm neutral
+ a tasteful plain floor, done with CSS color/gradient/shadow (no brick/wood photo tiles). Add
warm evening lighting (directional gradients, soft contact shadow at wall/floor, lamp/string-light glow).
3. Replace the flat horizontal pan with a **scroll-driven focus** controller: scrolling moves the
camera focus/zoom between a set of named focus points (placeholder anchors for now).
4. Remove the 4-theme system (RESOLVED 2026-06-19) — strip the Field/Dusk × Light/Dark toggles and
per-theme vars; settle on one basic warm/cozy scheme.

### Tests that must pass
- No console errors; dev server renders the room shell.
- Scroll moves focus smoothly between placeholder anchors; reduced-motion respected.

### Acceptance criteria (functional and visual)
- Functional: the empty room shell renders with real perspective depth; scroll-to-focus works on
desktop (primary, per ADR-0004) and does not break on mobile.
- Visual: reads as a believable corner of a warm, cozy room (depth + light), not a flat panel —
judged in the live preview against the references' *feel*.

### Definition of done
Project-wide DoD (shell-relevant items) plus: the perspective approach is validated (or an ADR
records a pivot away from CSS 3D), and the scroll-to-focus mechanism is in place.

### Complexity / token weight
L — the riskiest phase (validates the whole approach). Hands-on in the main session with frequent
preview checks.

### Estimated time
1–2 sessions.

### Dependencies on other phases
- Depends on: none (first redesign phase).
- Required by: Phase 2 (objects placed on the shell), Phase 3 (furnishing).

## Execution log
(Append-only during execution.)

### 2026-06-19 — built & validated in the live preview
- **Scene layer rebuilt** (`src/components/Portfolio.tsx`, `src/app/globals.css`): replaced the flat
horizontal-pan "Drawing Set" scene with a CSS-3D room. `.stage` holds the `perspective`
(1180px, `perspective-origin: 37% 39%` → corner view); `.camera` (preserve-3d) is the moving rig;
`.room` (preserve-3d) carries five inward-facing surfaces (back / left / right walls + floor +
ceiling). First built with the outward-facing cube formula → every non-back face showed its
**backface** (mirrored text); fixed by rebuilding faces inward (`translate… rotate…`).
- **Materials (ADR-0004):** painted warm-greige walls + plain wood floor (subtle CSS plank gradient),
warm key-light + lamp glow, contact shadows at the wall/floor seams, camera vignette. No brick/wood
photo textures.
- **Scroll-to-focus camera:** rAF engine eases a float focus index; wheel / arrows+PageUp/Dn+Home/End /
vertical drag all drive it; the camera lerps between per-anchor targets (`--cam-x/y/z/ry/rx`); the
focus rail + the active anchor's glow track it; `prefers-reduced-motion` skips the easing.
- **Themes removed (ADR-0004):** the 4 `[data-palette][data-theme]` blocks + the Field/Dusk × Light/Dark
toggles + `layout.tsx` `data-*` attrs are gone; one warm cozy `:root` scheme. Résumé fast-lane kept &
de-themed.
- **Anchor placement (execution decision, not a plan change):** the fixed corner camera frames the
**back wall** cleanly; the left wall is grazing-angle and the floor/right-wall placeholders
foreshorten/fly off-screen. So all six placeholder anchors sit on the back wall for Phase 1. The rig
already supports `rx`/`ry`, so Phase 2 can move real objects onto the side walls / floor with a
look-down or turn and tune per-object cameras then.
- **Verified (preview, ~961px desktop):** no console errors; all 6 anchors on-screen at full size;
scroll/keys/rail all glide the camera + update focus; résumé opens/closes; mobile (375px) renders
without breaking. Screenshots reviewed.

### 2026-06-19 — feedback pass: bigger room, pulled back, camera turns between walls
- **Francisco feedback:** liked the render; wanted the camera *farther back*, the view *less straight-on*,
and the room *larger* — then envisioned scrolling that can "go between all the walls" once real objects
are added.
- **Bigger / farther back / angled (look pass 1):** enlarged the room (`--rw/rh/rd` ≈ +30%), raised
perspective to 1340px, and gave `.room` a base `rotateY(-14deg) rotateX(4deg)` so the back wall recedes
into a three-quarter corner instead of sitting flat (one-point) to the camera. Mobile dims scaled to match.
- **Camera turns between walls (ADR-0005):** the engine now lerps yaw/pitch (`--cam-ry/rx`) as well as
translate/zoom, so each anchor's camera **turns to face its wall**. Redistributed the six placeholders:
3 on the back wall, 1 on the **left** wall, 2 on the **right** wall.
Verified by measurement sweep at ~961px: all six frame on-screen at full height (no slivers); screenshots
of the back-wall establishing view and the right-wall turned view confirm the tour feel.
- **Floor cleared (Francisco feedback):** the floor placeholder read weakly as a flat label, so Involvement
moved up onto the **right wall** (beside Skills — keeps Skills→Involvement a smooth same-wall turn). The
floor is now clean ambiance/depth; real floor presence in Phase 2 should be standing furniture, not a
flat plaque (ADR-0005).
- **Known caveats (carried to Phase 2, see ADR-0005):** per-object framing is viewport-width sensitive
(tuned at 961px); flat floor labels read weakly (real floor = standing 3D furniture). Preview screenshot
tool renders a different viewport than `eval` reads, so framing was validated via DOM measurement.

### 2026-06-20 — feedback pass: left-wall glitch fixed, pulled back, left→right tour order (ADR-0006)
- **Education "glitch through the wall" fixed.** The left-wall stop was turning the room the wrong way
(`rry:+46`), swinging the wall's **backface** to camera → a mirrored, full-screen wall. Turned the room
the correct way instead (toward the wall, `rry:-55`) so its painted inner face reads square-on; re-framed
(`cam x:420 y:50 z:240`). Verified in the preview: marker reads forward, no clip-through, no console errors.
- **Global pull-back for breathing room.** Added one knob — `--pull` (≈ `-250px`, outermost transform on
`.camera`) — that steps every view back at once (space to furnish in Phase 2) without re-tuning anchors.
Structural CSS change → cleared `.next` and restarted (Turbopack stale-CSS gotcha).
- **Left→right tour order.** The lettered sections were scattered out of sequence, so scrolling zig-zagged.
Laid the six stops across the walls in order: **About = left wall (landing)**, Education/Experience/Skills
= back wall L→R, Involvement/Contact = right wall back→front. Scrolling A→F now sweeps the room with no
backtracking. Verified by stepping the focus rail + screenshots at each end.
- **Francisco signed off** on all three (left-wall fix, spacing, scroll order) in the live preview, 2026-06-20.

### Tests that must pass — status
- No console errors; room shell renders — **pass.**
- Scroll moves focus smoothly between anchors; reduced-motion respected — **pass.**

## Closeout
**Status: complete.** Francisco signed off in the live preview on 2026-06-20.

- **Tests that must pass — both pass** (verified in the preview this session):
- No console errors; the room shell renders. ✓
- Scroll/keys/drag/rail glide the camera smoothly between anchors; `prefers-reduced-motion` skips the
easing. ✓
- **Acceptance criteria — met:** reads as a believable warm, cozy corner of a room with real perspective
depth (not a flat panel); scroll-to-focus tours the walls and frames each placeholder; works on desktop
(primary, ADR-0004) and renders on mobile without breaking. The perspective approach (ADR-0002) is
**validated** — Phase 1's de-risk goal is achieved.
- **Decisions landed:** ADR-0005 (camera travels & turns between walls); ADR-0006 (left→right tour order,
left wall via room-rotation, global pull-back).
- **Tech debt carried to Phase 2:**
- Per-object camera framing is **viewport-width sensitive** (tuned ~961px) — harden when real objects land.
- Facing mechanism is **mixed** (left wall = room rotation, right wall = camera yaw) — fine, could unify later.
- Flat floor labels read weakly — real floor presence should be **standing 3D furniture**, not plaques.
- Stray `public/poster-preview.html` (a recovered Spider-Verse poster preview) — **not** committed with
Phase 1; evaluate as a **Phase 2 input** (poster) or delete.
- **Auto-compactions this phase: 0** (threshold ~25%/250K).
Loading