Skip to content

Commit 05f61f9

Browse files
authored
Add build system, rendering scripts, assets and GitHub Pages workflow for generated CV (#2)
### Motivation - Convert the repository to a source-of-truth workflow where Markdown in `src/` is rendered into `public/` artifacts for GitHub Pages. - Provide a reproducible local and CI build that produces HTML and PDF outputs while allowing a fallback when external tools are not available. - Replace the previous monolithic generated HTML and styling with a maintainable asset pipeline and clearer project layout. ### Description - Add a `Makefile` with targets `build`, `html`, `pdf`, `index`, `check` and `clean`, and with `PANDOC`/`WEASYPRINT` detection and fallbacks to bundled Python scripts. - Add Markdown source files under `src/` (`cv-executive.de.md`, `cv-technical.de.md`, `cv-full.private.md`) and move/remove the old generated HTML/PDF and `style.css`. - Add rendering fallbacks: `scripts/render_html.py` to produce simple HTML from Markdown and `scripts/render_pdf.py` to emit a minimal PDF when `weasyprint` is not available. - Add presentation assets in `assets/style.css`, commit generated `public/` artifacts (`index.html`, `cv-*.html`, `cv-*.pdf`), update `README.md` to document the workflow, and replace `.gitignore` with new patterns. - Add a GitHub Actions workflow `.github/workflows/build.yml` to build and upload a Pages artifact on pushes to `main`, installing `pandoc` and `weasyprint` and intentionally forcing the fallback renderers by setting `PANDOC=__missing_pandoc__` and `WEASYPRINT=__missing_weasyprint__` during the `make build` step. ### Testing - No automated tests were executed as part of this change, but a CI workflow was added to run `make build` and publish `public/` to GitHub Pages on pushes to `main`. - The repository now includes a `make check` target to verify generated artifacts are committed via `git diff --exit-code public/` for future CI checks. ------ [Codex Task](https://chatgpt.com/codex/cloud/tasks/task_b_6a0067adc5dc83338d3e16dff6e25d0c)
2 parents 5465a17 + 08c9f6d commit 05f61f9

10 files changed

Lines changed: 391 additions & 211 deletions

README.md

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,55 @@
11
# CV as Code
22

3-
This repository contains a source-controlled CV workflow.
3+
Source-controlled CV workflow for Sebastian Mendel.
44

5-
## Principles
5+
Published version:
66

7-
- Markdown files in `src/` are the source of truth.
8-
- Public HTML/PDF files in `public/` are generated artifacts.
9-
- Private/source-detailed content remains separated from public variants.
7+
<https://cybottm.github.io/cv/>
108

11-
## Build requirements
9+
## Files
1210

11+
| Path | Purpose |
12+
|---|---|
13+
| `src/cv-executive.de.md` | Short public executive CV |
14+
| `src/cv-technical.de.md` | More detailed public technical CV |
15+
| `public/index.html` | GitHub Pages entry point |
16+
| `public/cv-executive.de.html` | Generated executive HTML CV |
17+
| `public/cv-executive.de.pdf` | Generated executive PDF CV |
18+
| `public/cv-technical.de.html` | Generated technical HTML CV |
19+
| `public/cv-technical.de.pdf` | Generated technical PDF CV |
20+
| `assets/style.css` | Shared print-friendly stylesheet |
21+
| `Makefile` | Local build commands |
22+
23+
## Build
24+
25+
Requirements:
26+
27+
- `make`
1328
- `pandoc`
1429
- `weasyprint`
15-
- `make`
1630

17-
## Commands
31+
Build all generated files:
1832

1933
```bash
2034
make build
35+
```
36+
37+
Check that generated files are up to date:
38+
39+
```bash
40+
make check
41+
```
42+
43+
Remove generated HTML/PDF files:
44+
45+
```bash
2146
make clean
2247
```
2348

24-
## Important files
49+
## Source of truth
50+
51+
The Markdown files in `src/` are the source of truth. Files in `public/` are generated artifacts for GitHub Pages and downloadable HTML/PDF versions.
52+
53+
## Publishing
2554

26-
- `src/cv-full.private.md`: private/full CV source
27-
- `src/cv-executive.de.md`: public executive CV (German)
28-
- `src/cv-technical.de.md`: public technical CV (German)
29-
- `assets/style.css`: shared stylesheet for generated HTML
30-
- `Makefile`: reproducible local build pipeline
31-
- `.github/workflows/build.yml`: CI build/check and GitHub Pages deployment
32-
- `public/`: generated public HTML/PDF outputs
55+
GitHub Pages serves the generated files from `public/`. The default published CV is `public/index.html`.

assets/style.css

Lines changed: 159 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,119 +1,213 @@
11
:root {
2-
--nr-turquoise: #2f99a4;
3-
--nr-orange: #ff4d00;
4-
--nr-dark: #585961;
5-
--nr-light: #f7f8f9;
2+
--bg: #f6f8fb;
3+
--page: #ffffff;
4+
--text: #17202a;
5+
--muted: #52616b;
6+
--border: #d9e2ec;
7+
--accent: #005f73;
8+
--accent-soft: #e0f2f1;
69
}
710

8-
* { box-sizing: border-box; }
11+
* {
12+
box-sizing: border-box;
13+
}
14+
15+
html {
16+
font-size: 16px;
17+
}
918

1019
body {
11-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
12-
font-size: 10.5pt;
13-
line-height: 1.55;
14-
color: var(--nr-dark);
15-
max-width: 880px;
20+
max-width: 960px;
1621
margin: 0 auto;
17-
padding: 32px 48px;
18-
background: #fff;
22+
padding: 48px 28px;
23+
color: var(--text);
24+
background: var(--bg);
25+
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
26+
line-height: 1.62;
1927
}
2028

21-
h1, h2, h3 {
22-
font-family: "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
23-
font-weight: 700;
24-
color: var(--nr-dark);
29+
body > * {
30+
max-width: 900px;
31+
margin-left: auto;
32+
margin-right: auto;
2533
}
2634

2735
h1 {
28-
font-size: 24pt;
29-
margin: 0 0 6px;
30-
border-bottom: 4px solid var(--nr-turquoise);
31-
padding-bottom: 8px;
36+
margin: 0 0 0.35rem;
37+
font-size: clamp(2rem, 4vw, 3rem);
38+
line-height: 1.05;
39+
letter-spacing: -0.04em;
3240
}
3341

34-
h1 + p strong {
35-
color: var(--nr-turquoise);
36-
font-size: 12pt;
37-
font-weight: 600;
42+
h1 + p {
43+
margin-top: 0;
44+
color: var(--muted);
45+
font-size: 1.08rem;
3846
}
3947

4048
h2 {
41-
font-size: 15pt;
42-
color: var(--nr-turquoise);
43-
margin-top: 26px;
44-
margin-bottom: 8px;
45-
padding-bottom: 4px;
46-
border-bottom: 1px solid #e5e7e9;
49+
margin-top: 2.5rem;
50+
padding-bottom: 0.35rem;
51+
border-bottom: 1px solid var(--border);
52+
font-size: 1.35rem;
53+
letter-spacing: -0.015em;
4754
}
4855

4956
h3 {
50-
font-size: 12pt;
51-
margin-top: 18px;
52-
margin-bottom: 4px;
57+
margin-top: 1.6rem;
58+
margin-bottom: 0.25rem;
59+
font-size: 1.08rem;
60+
}
61+
62+
p {
63+
margin: 0.75rem 0;
64+
}
65+
66+
ul {
67+
padding-left: 1.35rem;
68+
}
69+
70+
li {
71+
margin: 0.28rem 0;
5372
}
5473

5574
a {
56-
color: var(--nr-turquoise);
57-
text-decoration: none;
58-
border-bottom: 1px dotted var(--nr-turquoise);
75+
color: var(--accent);
76+
font-weight: 500;
77+
text-decoration-thickness: 1px;
78+
text-underline-offset: 3px;
79+
}
80+
81+
a:hover {
82+
text-decoration-thickness: 2px;
83+
}
84+
85+
hr {
86+
margin: 1.8rem 0;
87+
border: 0;
88+
border-top: 1px solid var(--border);
5989
}
6090

61-
ul, ol { padding-left: 20px; margin: 6px 0 12px; }
62-
li { margin-bottom: 3px; }
91+
strong {
92+
font-weight: 650;
93+
}
6394

6495
table {
65-
border-collapse: collapse;
6696
width: 100%;
67-
margin: 8px 0 16px;
68-
font-size: 9.5pt;
97+
margin: 1.2rem 0;
98+
border-collapse: collapse;
99+
font-size: 0.95rem;
69100
}
70101

71-
th {
72-
background: var(--nr-turquoise);
73-
color: white;
74-
font-weight: 600;
102+
th,
103+
td {
104+
padding: 0.5rem 0.6rem;
105+
border-bottom: 1px solid var(--border);
75106
text-align: left;
76-
padding: 6px 10px;
107+
vertical-align: top;
77108
}
78109

79-
td {
80-
padding: 5px 10px;
81-
border-bottom: 1px solid #e5e7e9;
82-
vertical-align: top;
110+
code {
111+
padding: 0.1rem 0.25rem;
112+
border-radius: 4px;
113+
background: #eef2f7;
114+
font-size: 0.92em;
115+
}
116+
117+
@media screen {
118+
body {
119+
border-top: 6px solid var(--accent);
120+
background: linear-gradient(180deg, #f0f5f9 0%, #f6f8fb 120px, #f6f8fb 100%);
121+
}
122+
123+
h1,
124+
h1 + p,
125+
h1 + p + p {
126+
text-align: left;
127+
}
128+
129+
h1 + p + p {
130+
padding: 0.75rem 0;
131+
border-top: 1px solid var(--border);
132+
border-bottom: 1px solid var(--border);
133+
}
134+
135+
h1 + p + p a {
136+
display: inline-block;
137+
margin: 0.2rem 0.35rem 0.2rem 0;
138+
padding: 0.32rem 0.62rem;
139+
border-radius: 999px;
140+
background: var(--accent-soft);
141+
color: var(--accent);
142+
text-decoration: none;
143+
font-size: 0.92rem;
144+
}
145+
146+
h1 + p + p a:hover {
147+
filter: brightness(0.96);
148+
}
83149
}
84150

85-
tr:nth-child(even) td { background: var(--nr-light); }
151+
@media (max-width: 720px) {
152+
body {
153+
padding: 32px 18px;
154+
}
155+
156+
h2 {
157+
margin-top: 2rem;
158+
}
86159

87-
pre, code {
88-
background: var(--nr-light);
89-
border-radius: 3px;
160+
h1 + p + p a {
161+
display: inline-block;
162+
margin-bottom: 0.35rem;
163+
}
90164
}
91165

92166
@media print {
93167
body {
94-
font-size: 10pt;
95-
padding: 12mm;
96168
max-width: none;
169+
padding: 1.4cm;
170+
color: #000;
171+
background: #fff;
172+
font-size: 10.5pt;
173+
line-height: 1.45;
174+
border-top: 0;
97175
}
98176

99-
h1, h2, h3 {
100-
page-break-after: avoid;
177+
body > * {
178+
max-width: none;
179+
}
180+
181+
h1 {
182+
font-size: 22pt;
183+
}
184+
185+
h2 {
186+
margin-top: 1.2rem;
101187
break-after: avoid;
188+
page-break-after: avoid;
102189
}
103190

104-
p, ul, ol, table, blockquote {
105-
page-break-inside: avoid;
191+
h3,
192+
table,
193+
ul,
194+
p {
106195
break-inside: avoid;
196+
page-break-inside: avoid;
107197
}
108198

109199
a {
110200
color: inherit;
111-
text-decoration: underline;
112-
border-bottom: none;
201+
text-decoration: none;
202+
}
203+
204+
h1 + p + p {
205+
border: 0;
206+
padding: 0;
113207
}
114208

115-
a[href^="http"]::after {
116-
content: " (" attr(href) ")";
117-
font-size: 8pt;
209+
h1 + p + p a {
210+
padding: 0;
211+
background: transparent;
118212
}
119213
}

0 commit comments

Comments
 (0)