3.4 KiB
3.4 KiB
Diary
A password-protected diary of reviews (books, movies, albums) and notes, built with Nuxt 4 + Nuxt UI on top of two self-hosted Baserow tables.
pnpm install
cp .env.example .env
pnpm dev
Configuration
| Variable | Purpose |
|---|---|
NUXT_BASEROW_URL |
Baserow instance, no trailing slash |
NUXT_BASEROW_TOKEN |
Database token with read and create access to both tables |
NUXT_BASEROW_REVIEWS_TABLE_ID |
Reviews table |
NUXT_BASEROW_NOTES_TABLE_ID |
Notes table |
NUXT_DIARY_PASSWORD |
Password that unlocks the diary |
NUXT_SESSION_SECRET |
Signs the login cookie, at least 32 characters (openssl rand -hex 32) |
In app/app.config.ts, showCovers: true shows a generated title tile next to each review.
What it does
/is the only page: reviews and notes on one timeline, newest first, grouped by year.- Only entries with text are shown. Long text is collapsed behind "Read more".
- Search matches every word against the kind (
review,note), the medium (book,movie,album), the date (aug 2025,2025-08), the title, the author and the text. Matches in the text are highlighted. - "Log" opens a form with a Note / Review switch.
- Until the password is entered, only a password prompt is shown and every API route except
/api/sessionand/api/loginreturns 401. A correct password sets a signed, http-only cookie valid for 30 days. ChangingNUXT_SESSION_SECRETlogs out every browser.
Code layout
app/
app.vue password gate around the page
pages/index.vue the diary page
components/
DiaryEntry.vue one timeline entry (date, title, text, read more)
LogModal.vue Note / Review switch around the two forms
NoteForm.vue, ReviewForm.vue
PasswordModal.vue
CoverTile.vue generated cover, used when showCovers is on
composables/
useDiary.ts loads reviews + notes, searches, sorts and groups them by year
useSaveEntry.ts shared submit logic of the forms
useLog.ts open/close state of the Log modal
utils/ dates, icons, search highlighting, error messages
types/entry.ts a timeline entry (review or note)
server/
middleware/auth.ts locks /api/* until unlocked
api/ session, login, reviews and notes (GET list, POST create)
utils/
baserow.ts Baserow client: listRows, createRow, listFields
review.ts, note.ts Baserow row -> app type
auth.ts session cookie and password check
validation.ts readValidBody(event, zodSchema)
shared/
types/ Review, Note
utils/medium.ts the review media: label and creator label
utils/schemas.ts zod schemas used by both forms and API
Baserow tables
Reviews: title, date (ISO date), author_or_director, review (long text) and medium
(single select: Book / Movie / Album).
Notes: Datum (date) and Notes (long text).
Rows without a date are skipped. Text is plain text: line breaks are kept and it is never rendered as HTML.
Adding a medium
- Add the option to the
mediumsingle select in Baserow. - Add it to
Mediuminshared/types/review.ts, toMEDIUMSinshared/utils/medium.ts(itslabelmust match the Baserow option) and toMEDIUM_ICONSinapp/utils/icons.ts.