@@ -28,3 +28,151 @@ npm run build # production build for the custom domain
2828
2929## Project structure
3030- ` src/ ` contains pages (` *.njk ` ), data (` _data/projects.json ` ), includes (` _includes/ ` ), and assets/images copied through to the build.
31+
32+ ## ` projects.json ` reference (project cards + project pages)
33+ - File: ` src/_data/projects.json `
34+ - Each object in the array represents one project used by:
35+ - ` src/portfolio.njk ` (portfolio cards)
36+ - ` src/projects/project-page.njk ` (generated project pages)
37+
38+ ### Common project fields
39+ - ` slug ` (string): used for project page routes (` /projects/<slug>/ ` )
40+ - ` title ` (string): project title shown on cards and project page
41+ - ` image ` (string): default image path (used on portfolio cards and as fallback on project page)
42+ - ` alt ` (string): image alt text
43+ - ` description ` (string): short summary used in portfolio + project page header
44+ - ` tags ` (array of strings): badge tags
45+ - ` currentlyBuilding ` (boolean, optional): if ` true ` , project appears in the “Currently building” section
46+ - ` links ` (array, optional): CTA buttons shown on portfolio/project page
47+ - ` label ` (string)
48+ - ` url ` (string)
49+ - ` newTab ` (boolean, optional; portfolio respects this)
50+
51+ ### Date field (single source of truth)
52+ - ` date ` (object): used for sorting and display formatting (` Mon. Year ` , ` Mon. Year - Mon. Year ` , ` Mon. Year - Present ` )
53+ - Keep ` dates ` (string) if you want a human-readable reference while editing, but the site now uses ` date `
54+
55+ Supported ` date ` shapes:
56+
57+ Single month:
58+ ``` json
59+ "date" : {
60+ "start" : { "month" : 1 , "year" : 2025 }
61+ }
62+ ```
63+
64+ Range:
65+ ``` json
66+ "date" : {
67+ "start" : { "month" : 5 , "year" : 2025 },
68+ "end" : { "month" : 6 , "year" : 2025 }
69+ }
70+ ```
71+
72+ Ongoing:
73+ ``` json
74+ "date" : {
75+ "start" : { "month" : 9 , "year" : 2025 },
76+ "present" : true
77+ }
78+ ```
79+
80+ Year-only (supported):
81+ ``` json
82+ "date" : {
83+ "start" : { "year" : 2023 }
84+ }
85+ ```
86+
87+ ### ` projectPage ` object
88+ - ` projectPage.enabled ` (boolean): controls whether the “Project Page” button appears and whether the page renders full content vs “not available yet”
89+ - ` projectPage.url ` (string, optional/legacy): may still exist in data, but generated pages use ` slug `
90+ - ` projectPage.images ` (array, optional): top-of-page image gallery shown before the project details/sections
91+ - ` projectPage.sections ` (array, optional): content blocks rendered in order on the project page
92+
93+ ### ` projectPage.images ` item format (top-level gallery)
94+ - Each item can be either:
95+ - a string image path, or
96+ - an object with:
97+ - ` src ` (string) (also accepts ` url ` or ` image ` )
98+ - ` alt ` (string, optional)
99+ - ` caption ` (string, optional)
100+
101+ Example:
102+ ``` json
103+ "images" : [
104+ { "src" : " /images/project-1.jpg" , "alt" : " Front view" , "caption" : " Prototype front view" },
105+ { "src" : " /images/project-2.jpg" , "caption" : " Bench test setup" }
106+ ]
107+ ```
108+
109+ ### Allowed ` projectPage.sections ` types
110+ - ` text `
111+ - ` bullets `
112+ - ` keyValue `
113+ - ` gallery `
114+
115+ All section types may include:
116+ - ` title ` (string, optional): rendered as a section heading
117+
118+ #### ` text ` section
119+ ``` json
120+ {
121+ "type" : " text" ,
122+ "title" : " Project Overview" ,
123+ "body" : " Short paragraph..."
124+ }
125+ ```
126+
127+ Fields:
128+ - ` body ` (string)
129+
130+ #### ` bullets ` section
131+ ``` json
132+ {
133+ "type" : " bullets" ,
134+ "title" : " What I Did" ,
135+ "items" : [" Item one" , " Item two" ]
136+ }
137+ ```
138+
139+ Fields:
140+ - ` items ` (array of strings)
141+
142+ #### ` keyValue ` section
143+ ``` json
144+ {
145+ "type" : " keyValue" ,
146+ "title" : " System Architecture" ,
147+ "items" : [
148+ { "label" : " MCU" , "value" : " STM32" },
149+ { "label" : " Bus" , "value" : " SPI" }
150+ ]
151+ }
152+ ```
153+
154+ Fields:
155+ - ` items ` (array of objects)
156+ - ` label ` (string)
157+ - ` value ` (string)
158+
159+ #### ` gallery ` section
160+ ``` json
161+ {
162+ "type" : " gallery" ,
163+ "title" : " Build Photos" ,
164+ "images" : [
165+ { "src" : " /images/photo1.jpg" , "caption" : " Rev A board" },
166+ { "src" : " /images/photo2.jpg" , "caption" : " Testing setup" }
167+ ]
168+ }
169+ ```
170+
171+ Fields:
172+ - ` images ` (array)
173+ - same item format as ` projectPage.images ` (string path or object with ` src ` /` alt ` /` caption ` )
174+
175+ ### Notes / behavior
176+ - Project pages are generated for every project via ` src/projects/project-page.njk ` , but if ` projectPage.enabled ` is false the page shows a “not available yet” message.
177+ - Portfolio ordering is reverse chronological based on ` date.start ` .
178+ - Portfolio cards use a responsive grid (3 columns desktop, then 2, then 1) and keep automatic card height sizing.
0 commit comments