feat: add cv

This commit is contained in:
2026-10-02 17:32:02 +02:00
parent ddbb6f37b5
commit e82561862a
13 changed files with 473 additions and 1 deletions
+38
View File
@@ -19,6 +19,7 @@ picked up automatically. The root only holds what apps share:
| `/diary` | [Diary](#diary) — `layers/diary/` (password protected) |
| `/wishlist` | [Wishlist](#wishlist) — `layers/wishlist/` |
| `/notes` | [Notes](#notes) — `layers/notes/` (password protected) |
| `/cv` | [CV](#cv) — `layers/cv/` |
```bash
pnpm install
@@ -35,6 +36,42 @@ pnpm dev
names that won't clash with another app's (e.g. `DiaryEntry`, not `Entry`).
3. Don't use `~/` inside a layer — it points to the root `app/`. Use relative imports.
# CV
A public CV built from the Baserow CV table (`NUXT_BASEROW_CV_TABLE_ID`). Only rows with `relevant` checked are shown,
latest start first, split into **Experience** and **Education** (`Student` and `Pupil`). An empty `To` means the
entry is still going on: it shows as "today" and its duration is counted until today (Baserow's `Duration` formula is
not used).
The header (name, description per language, photo, email, LinkedIn link) is set in `layers/cv/app/app.config.ts`
under `cv`. LinkedIn blocks scraping, so the photo and description are not fetched from there; put the photo in
`layers/cv/public/`.
A DE / EN switch (remembered in the `cv-lang` cookie, German by default) translates the page's own text: headings,
dates, durations, types, the description. `Area` comes from `area_german` on the German page; the rest of the table's text (`Institution`) is shown as stored.
**Table:** `From`, `To` (dates), `Type` (single select), `Institution`, `Area` (text, English), `area_german` (text, used on the German page, falls back to `Area`), `Place` (single select),
`Grade` (number), `relevant` (boolean), `file` (file; each file is listed under its entry as a download, e.g. a
thesis), `urls` (long text: one link per line, a blank line between groups such as projects; GitHub links show
`owner/repo` with a GitHub icon, others their address; write `Label https://…` for custom text). Rows without `From`
are skipped. Baserow returns file URLs as `http://`, so they are rewritten to
`NUXT_BASEROW_URL`.
```
layers/cv/
nuxt.config.ts baserowCvTableId
app/
app.config.ts cv: name, description, photo, email, linkedin
pages/cv.vue language switch, header, Experience and Education
composables/useCvLang.ts current language and the translated texts
components/CvSection.vue one section: period, duration, area, institution, type, grade
utils/cvDate.ts period and duration, open-ended until today
server/
api/cv/index.get.ts GET relevant entries
utils/cv.ts Baserow row -> CvEntry
shared/types/cv.ts
```
# Notes
Minimal notes: a collapsible list of notes on the left, a WYSIWYG Markdown editor (Nuxt UI `UEditor`) on the right.
@@ -122,6 +159,7 @@ self-hosted Baserow tables.
| `NUXT_BASEROW_REVIEWS_TABLE_ID` | Reviews table |
| `NUXT_BASEROW_NOTES_TABLE_ID` | Notes table |
| `NUXT_BASEROW_WISHLIST_TABLE_ID` | Wishlist table (see [Wishlist](#wishlist)) |
| `NUXT_BASEROW_CV_TABLE_ID` | CV table (see [CV](#cv)) |
| `NUXT_BASEROW_NOTES_APP_TABLE_ID` | Table of the notes app (see [Notes](#notes)), not the diary's notes |
| `NUXT_DIARY_PASSWORD` | Password that unlocks the diary and notes |
| `NUXT_SESSION_SECRET` | Signs the login cookie, at least 32 characters (`openssl rand -hex 32`) |