Files
hudozka/docs/plans/20260403-pocketbase-migration.md
T
tmshv ed3f93de53 PB + Writer (#287)
* add pb models

* api rules has updated to view public

* pb setup is completed

* add migrate script

* add pb migrations

* ignore storage

* add pocketbase SDK dependency

* change Tag.id and PageCardDto.id to string for PocketBase

* add DocV1 content block types

* add PB client singleton and PB record types

* rewrite factory for PocketBase record types

* rewrite api.ts for PocketBase SDK

* remove unused Strapi files, add PB to config

* mark Task 7 complete in plan

* feat: verify build, tests, and lint pass with PocketBase API layer

* move completed plan: 2026-04-06-pocketbase-api-layer.md

* scaffold hudozka-writer with Vite 8, React 19, TS 5.9, Tiptap

* add PocketBase client and DocV1 types to writer

* add Login component for PocketBase superuser auth

* add App shell with auth gate and page loader

* add DocV1 <-> Tiptap serialization layer

* mark Task 5 complete in writer redesign plan

* add custom Tiptap nodes for DocV1 block types

* add Tiptap editor with toolbar and save to PocketBase

* add image picker with browse and upload

* feat: verify writer build and complete integration task

* move completed plan: 2026-04-06-hudozka-writer-redesign.md

* add local env

* rm textblock from writer

* add writer editor improvements design spec

* add writer editor improvements implementation plan

* feat: use @tiptap/markdown for text block serialization

* feat: add global markdown/rendered toggle

* feat: add BlockMenu component for block type selection

* feat: add hover + button for block insertion

* feat: add slash commands for block insertion

* feat: add interactive file block editor with FilePicker

* feat: show resolved page titles in card grid block

* move completed plan: 2026-04-07-writer-editor-improvements.md

* writer ui improved

* pages migration

* spec: draft/publish workflow for hudozka-writer

* spec: rename draft_doc to draft in spec

* plan: writer draft/publish implementation

* plan has moved

* gitignores

* plans upd

* feat(writer): update PbPage type for draft/publish workflow

* feat(writer): add save/publish/discard handlers with dirty tracking

* feat(writer): add DraftBanner component

* feat(writer): add Publish button and update toolbar layout

* feat(writer): add published toggle and update duplicate for new schema

* docs: mark manual verification steps as skipped in writer draft/publish plan

* move completed plan: 20260407-writer-draft-publish.md

* feat(writer): add BlockActions component for inline block menus

* feat(writer): add draggable NodeViews for text blocks

* feat(writer): use BlockActions in custom block NodeViews

* feat(writer): replace floating BlockInsert with inline BlockActions

* fix(writer): ensure all block wrappers have position: relative for BlockActions

* chore: mark manual verification tasks as skipped in writer block actions plan

* move completed plan: 20260408-writer-block-actions.md

* writer update

* refactor(writer): simplify BlockActions to always-visible delete + drag handle

* feat(writer): add BlockInsert component for inserting blocks between nodes

* feat(writer): redesign block sidebar with always-visible actions and insert button

* move completed plan: 20260408-writer-block-actions-redesign.md

* add spec: textblock container redesign for writer editor

* feat(writer): add TextBlock container node definition

* feat(writer): replace DraggableXxx wrappers with TextBlock container

* feat(writer): update Editor extensions for TextBlock container

* feat(writer): add split button to BlockActions for text blocks

* feat(writer): update serialization for TextBlock container

* feat(writer): update BlockMenu and SlashCommands for TextBlock

* fix(writer): use Fragment.from() for replaceWith calls in BlockActions and SlashCommands

* move completed plan: 20260408-textblock-container.md

* add air
2026-04-12 19:02:03 +03:00

5.6 KiB

PocketBase Migration Plan

Based on verified live data from hudozka.tmshv.com.

Verified Data Volume

Entity Count
Pages 316
Tags 70
Home cards 17
Menu items 4

Part 1: PocketBase Setup (manual)

See 20260403-pocketbase-setup-guide.md.


Part 2: Migration Script

Script location: modules/migrate-to-pocketbase/

What it does

  1. Fetches all data from Strapi (hudozka.tmshv.com):

    • GET /pages?_limit=100&_start={n} (4 batches)
    • GET /tags
    • GET /home
    • GET /menu
  2. Creates 70 tag records in PocketBase, builds strapiTagId -> pbTagId map.

  3. Collects all unique Strapi media used as images (covers + hudozka.image blocks). For each:

    • Downloads file from hudozkacdn.tmshv.com
    • Reads dimensions with sharp, computes blurhash
    • Creates images record with file, alt, caption, width, height, blur, filename
    • Builds strapiMediaId -> pbImageId map
  4. Collects all unique Strapi media used as documents (hudozka.document blocks). For each:

    • Downloads file from hudozkacdn.tmshv.com
    • Creates files record with file, title, mime, size, filename (preview left empty)
    • Builds strapiMediaId -> pbFileId map
  5. For each of 316 pages:

    • Resolves cover to pbImageId via image map
    • Converts content[] from Strapi component format to simplified JSON blocks:
      • hudozka.text -> { type: "text", text }
      • hudozka.image -> { type: "image", image: pbImageId, wide, caption }
      • hudozka.document -> { type: "document", file: pbFileId, title }
      • hudozka.embed -> { type: "embed", src }
      • hudozka.card-grid -> { type: "card-grid", items: [{ page: strapiPageId, layout }] }
    • Creates page record with cover + tags relations + content JSON
  6. Second pass: replaces Strapi page IDs in card-grid blocks with PocketBase page IDs.

  7. Creates 2 kv records:

    • key: "home" with card list (PocketBase page IDs + layouts)
    • key: "menu" with menu items (PocketBase page IDs) + homeLabel
  8. Verification: counts check, spot-check, HTTP HEAD on file URLs.

Environment

Requires STRAPI_URL (default https://hudozka.tmshv.com) and POCKETBASE_URL + POCKETBASE_EMAIL + POCKETBASE_PASSWORD env vars.


Part 3: App Changes

Only src/remote/ changes. src/types.ts stays unchanged.

New file: src/remote/pb.ts

PocketBase client singleton. Reads POCKETBASE_URL from env.

Rewrite: src/remote/types.ts

Replace Strapi* types with Pb* types matching PocketBase record shape + new content block types.

Rewrite: src/remote/api.ts

Same exported function signatures, PocketBase SDK calls instead of raw fetch:

Function Current New (PocketBase SDK)
getUrls() GET /pages?_limit=100&_start={n} pb.collection("pages").getFullList({ fields: "slug" })
getPageBySlug(slug) GET /pages?slug={slug} pb.collection("pages").getFirstListItem('slug="..."', { expand: "cover,tags" }) + resolve image/file IDs from content via prefetched maps
getHomeCards() GET /home pb.collection("kv").getFirstListItem('key="home"') + fetch pages
getMenu() GET /menu pb.collection("kv").getFirstListItem('key="menu"') + fetch pages
getRecentPages(n) GET /pages?_sort=date:DESC&_limit={n} pb.collection("pages").getList(1, n, { filter: "date!=''", sort: "-date" })

Rewrite: src/remote/factory.ts

Transform functions accept PocketBase records, output identical app types. Key changes:

  • At build start, prefetch all images and files records once → in-memory Map<id, record>
  • Content blocks reference image/file IDs; resolved via the maps (no per-page expand)
  • Pages fetched with expand: "cover,tags" only
  • File URLs via pb.files.getURL(record, record.file)
  • Blurhash read from image record (blur field) — no runtime sharp calls needed
  • content is already clean JSON (no __component prefix)
  • asItem() from lib.ts no longer needed
  • createPicFromMedia() -> createPicFromImageRecord(imageRecord)
  • Text processing (markdownToHtml + typograf) stays identical

Update: next.config.ts

Add PocketBase host to images.remotePatterns.

New dependency

pocketbase (JS SDK)

Files summary

File Action
src/remote/pb.ts New — PocketBase client
src/remote/types.ts Rewrite — Pb* types
src/remote/api.ts Rewrite — PocketBase SDK calls
src/remote/factory.ts Rewrite — new input shapes
src/remote/image.ts Remove — blurhash precomputed in migration
src/remote/lib.ts Remove or simplify
src/types.ts No changes
next.config.ts Update — remotePatterns
.env.example Update — add POCKETBASE_URL
package.json Update — add pocketbase dependency