feat(examples): make lumibase the default client in nextjs-blog + quickstart (EN/VI) - #474
Open
khuepm wants to merge 2 commits into
Open
feat(examples): make lumibase the default client in nextjs-blog + quickstart (EN/VI)#474khuepm wants to merge 2 commits into
khuepm wants to merge 2 commits into
Conversation
Switch the Next.js blog example from the GraphQL plugin to the REST
surface of the `lumibase` package, installed as a real runtime
dependency instead of `workspace:*`, so the directory can be copied
outside the monorepo and installed from the registry.
- `createLumiClient(...).with(legacyRest())` replaces `.with(graphql())`;
pages use `items('posts').list()` / `.detail(id)`.
- Content fields now read from `row.data.*` (REST returns `ItemRow`),
and sorting uses the structural column name `-created_at`.
- 404 from `detail()` maps to `notFound()` via `LumiError.status`.
- Add the missing root layout — without it the example could not build
standalone at all.
- Add `lumibase.config.json` plus `types` / `types:check` scripts and
commit the generated `src/lumibase-types.d.ts`.
- Document the read-only credential, the server-only token rule and the
`@lumibase/sdk` compatibility path in the README.
The tutorial presented raw `fetch` as Option A and the SDK as Option B,
and the SDK sample documented an API that does not exist
(`createClient(...).items(c).readMany(...)`).
- Step 6 is now the `lumibase` package: `createLumiClient` +
`legacyRest()`, `items('posts').list()` / `.detail(id)`, with the
`.data` nesting and `-created_at` sorting called out, and `LumiError`
mapped to `notFound()`. Plain `fetch` moves to an appendix.
- New Step 7 covers `lumibase types` / `--check` in CI, and records that
typegen needs a staff-user token: the endpoint sits behind the Studio
access wall, so an API key gets 403 even with `schema:read`.
- Step 4 gains a least-privilege policy/role chain for the API key; the
`status` field is removed from Step 3 because it is a built-in column.
- Compatibility contracts updated to the real SDK surface; both locales
re-verified against source and re-stamped (verified_on 1.0.0-rc.1).
The code-fences parity waiver is scoped and explained in both files:
the blocks are byte-identical apart from translated trailing comments,
which check-parity does not strip.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Làm cho
lumibasetrở thành client mặc định của example Next.js và của tutorial quickstart, đồng thời khiếnexamples/nextjs-blogthật sự chạy được độc lập ngoài monorepo.Trước PR này example dùng plugin GraphQL với
@lumibase/sdk: workspace:*(không cài được từ registry), còn tutorial dạyfetchtrước SDK và mô tả một API không tồn tại:createClient(...).items(c).readMany(...).Closes #334. Bằng chứng nghiệm thu đầy đủ: #334 (comment)
Loại thay đổi
feat— Tính năng mớidocs— Cập nhật tài liệuPhase / Feature liên quan
Lane A — A03 (#334), parent #331. Contract consumer theo A02 (#332, PR #468). Bằng chứng chuyển sang #448.
✅ Definition of Done (DoD)
Code Quality
pnpm typecheck18/18 successful; thêmtsc --noEmitexit 0 ở thư mục tạm ngoài workspaceexamples/*nằm ngoài pnpm workspace nên không có suite riêngArchitecture & Docs
architecture.md— n/a, không đổi cấu trúc hệ thốngapps/cms/openapi.yaml— n/a, không thêm/sửa endpoint nàopackages/sdktypes — n/a, không đổi API; PR này chỉ dùng SDK hiện códocs/en/tutorials/nextjs-quickstart.md+docs/vi/...(bắt buộc song ngữ), đãparity→ 0 problems,verify→ 26 claims 0 stale,stamp-pair --verified→ cả haiversion: 3, hash khớp8517ebf6d2842ff5,detect148/148 up-to-dateTesting
1.0.0-rc.1(serve.ts, docker mode) trên DB riênglumibase_a03Runtime Compatibility
Security
X-Lumi-Site→401, không trả nội dung site khác.next/static;.env.exampleghi rõ không dùngNEXT_PUBLIC_Database / Migrations
Conventional Commits
feat(examples): make lumibase the default client in nextjs-blogdocs(tutorials): teach the SDK first in the Next.js quickstart (EN+VI)Screenshots / Recordings
Không có UI mới. Bằng chứng là output build thật, trích từ
next buildở thư mục tạm ngoài repo:Đúng 2 id
publishedđược prerender; itemdraftkhông xuất hiện.Rollback Plan
Revert 2 commit (
221ab4c4,d417b617). Không có migration, không có thay đổi runtime/API, không đụng lockfile hay workflow — nên rollback không ảnh hưởng production.examples/*nằm ngoài pnpm workspace nên không tác động build của repo.Notes for Reviewers
Đã nghiệm thu thật (không phải suy luận)
CMS
1.0.0-rc.1chạy thật trên DB riêng, seed collectionpostsvới 2 itempublished+ 1draft, API key gắn role → policyreadvới rule{"status":{"_eq":"published"}}.pnpm pack(KHÔNG phảinpm pack— chỉ pnpm rewriteworkspace:*→1.0.0-rc.1, khớppnpm publishtrongrelease.yml). Copy example ra thư mục tạm →npm install <2 tarball>→ không cònworkspace:*, không symlink vào monorepo.404.404· ghi403· sai site401· không token401.revalidate = 60.types --check: schema khớp → exit 0; thêm fieldsubtitle(drift có chủ đích) → exit 1; xoá → exit 0 trở lại.createLumiClient/legacyRest/LumiErrorimport từ@lumibase/sdkvà từlumibaselà cùng object (===true), cùng trả về 2 bài published.🔴 Ba điểm reviewer cần quyết
Bug CMS ngoài phạm vi PR (DoS). Request với
X-Lumi-Sitekhông tồn tại trả401đúng, nhưng lượt ghi audit log sau đó vi phạm FKlumibase_audit_log_site_id_lumibase_sites_id_fk(23503) và làm chết cả process. Trigger được từ xa bằng 1 header sai. Không thuộc grant A03 nên không sửa ở đây.Typegen không dùng được API key.
GET /api/v1/typegen/schemanằm sauSTUDIO_ACCESS_PATH_PREFIXES(apps/cms/src/middleware/studio-access.ts) vốn đòi user principal → API key bị403kể cả khi policy đã cấpschema:read. Đã ghi rõ trong README + tutorial EN/VI, nhưng cần xác nhận đây là chủ ý hay là gap.Sửa claim sai có sẵn trong tutorial:
createClient(...).items(c).readMany(...)chưa từng tồn tại trong SDK. Hai locale hash khớp nhau vẫn cùng mô tả một API không có thật — đúng kịch bản mà CLAUDE.md cảnh báo.Lệch nhỏ so với exact-file grant (cố ý, cần biết)
src/app/layout.tsx(mới) — grant không liệt kê, nhưng thiếu root layout thì example không build được độc lập (page.tsx doesn't have a root layout). Không thêm thì tiêu chí "chạy độc lập" không thể đạt.lumibase.config.jsonthay vìlumibase.config.tsnhư grant ghi — CLI chỉ đọc.json(CONFIG_FILENAMEtrongpackages/cli/src/config.ts),.tssẽ bị bỏ qua.src/lumibase-types.d.ts(mới) — output typegen, commit đểtypes --checkcó cái mà so.check-parity: allow code-fences(kèm lý do, ở cả hai locale): các code block giống hệt từng byte, chỉ khác comment cuối dòng đã dịch;check-paritystrip comment cả dòng nhưng không strip comment cuối dòng. Đã diff kiểm chứng sau khi bỏ comment cuối dòng → không còn khác biệt.Không đụng tới
Không sửa CMS/MCP/harness, SDK/CLI/scaffolder, root lockfile/manifests/workflows, hay docs getting-started.
git statusxác nhậnpnpm-lock.yaml,package.json,turbo.jsonsạch.Một cảnh báo còn lại
next@^15.5.19→npm auditbáo 2 lỗi (1 high), đều làpostcsstransitive, chỉ hết khi lên Next 16 (major, ngoài grant). Không tự nâng — để coordinator quyết.