CLI cmssy
init generuje okablowanie w istniejącej aplikacji, add block tworzy i rejestruje blok, link łączy aplikację z workspace'em i dowodzi, że działa.
Trzy komendy, każda na moment, który kiedyś był robotą ręczną: okablowanie nowej aplikacji, dodanie bloku i podłączenie do workspace'u.
cmssy init
cmssy nigdy nie scaffolduje Twojej aplikacji. Framework jest adapterem, nigdy fundamentem - aplikację tworzysz własnym CLI Next.js, a init dokłada do niej okablowanie cmssy.
npx create-next-app@latest my-site
cd my-site
npx @cmssy/cli initCLI celuje w Next.js z App Routerem i wymaga Node 18.18+. Astro, Remix i React Router są wspierane przez samo SDK - te podpinasz ręcznie, a nie przez init.
Jest idempotentne: plik, który już istnieje, jest pomijany i raportowany jako pominięty, nigdy nadpisywany. Uruchom dwa razy, a drugi przebieg niczego nie zmieni.
Co zapisuje
cmssy.config.ts
proxy.ts
next.config.mjs
env.example
cmssy/blocks.ts rejestr bloków
cmssy/editor.tsx most edytora
blocks/hero/block.ts
blocks/hero/Hero.tsx
blocks/hero/Hero.module.css
app/[[...path]]/page.tsx catch-all route
app/api/draft/route.ts podgląd roboczyZwróć uwagę, czego tam nie ma: żadnego app/sitemap.ts, żadnego app/robots.ts, żadnego route'u /cmssy-edit, żadnego root layoutu ani edytowalnego layoutu.
To jest celowe, a nie brakujące. Te pliki kodują decyzje o Twojej aplikacji - jakie URL-e wystawiasz, jak wygląda Twoje chrome, jak kształtujesz sitemapę - a szablon, który by je zgadywał, byłby zły dla większości projektów. init daje Ci renderującą stronę i route roboczy; resztę dokładasz sam, według route'ów i stron, layoutów i SEO.
Flagi: --dir <ścieżka> celuje w aplikację poza katalogiem roboczym, --force nadpisuje istniejące okablowanie.
cmssy add block
Każdy blok po wygenerowanym hero oznaczał kiedyś ręczne kopiowanie plików i pamiętanie o edycji rejestru.
cmssy add block pricing-table
cmssy add block faq-list --dir ../my-siteWszystkie nazwy wyprowadza z argumentu w kebab-case: pricing-table daje typ pricing-table, etykietę Pricing Table, komponent PricingTable i eksport pricingTableBlock.
Zapisuje pliki bloku i rejestruje go w cmssy/blocks.ts - dodaje import i dopisuje do tablicy blocks, zachowując Twoje formatowanie i istniejące wpisy.
Odmawia tknięcia czegokolwiek niejednoznacznego: nieprawidłowej nazwy, już zarejestrowanego bloku, istniejących plików albo rejestru bez tablicy export const blocks = [...]. Każdy z tych przypadków to głośny błąd z wypisanym krokiem ręcznym - nigdy cichy częściowy zapis.
Wygenerowany blok startuje z wymaganym heading i opcjonalnym text. Zmień propsy i markup, zrestartuj dev server, a edytor podchwyci nowy typ z handshake'u manifestu.
cmssy link
Podłączenie aplikacji do workspace'u oznaczało kiedyś ręczne przeklejanie pięciu wartości między panelem a .env.local - a edytor pozostawał martwy, dopóki każda nie była poprawna.
npx @cmssy/cli link
cmssy link --token cs_... --workspace acme/shop --preview-url https://shop.example.comUwierzytelnia się tokenem API (z --token albo CMSSY_API_TOKEN; .env.local i .env są czytane najpierw, nigdy nie nadpisując zmiennych z powłoki), wybiera workspace, odczytuje draft secret, zapisuje CMSSY_ORG_SLUG, CMSSY_WORKSPACE_SLUG i CMSSY_DRAFT_SECRET do .env.local - scalając, więc istniejące linie i komentarze przeżywają - po czym odpala preflight i wypisuje deep link do edytora.
Odczyt draft secretu wymaga uprawnienia PAGES_EDIT. Jego brak jest raportowany dokładnie jako to.
Preview URL jest współdzielony - localhost jest odrzucany
--preview-url ustawia origin, pod którym edytor osadza Twoją aplikację dla wszystkich w workspace. Wartość localhost jest odrzucana celowo: wskazanie współdzielonego podglądu na Twoją maszynę zepsułoby edytor każdemu współpracownikowi.
Do pracy lokalnej przełącz tryb dev w edytorze cmssy i wpisz tam swój lokalny host. Ten cel jest per użytkownik i nie dotyka niczego współdzielonego. Bez flagi wartość pozostaje niezmieniona.
Sprawdzenia
- Workspace osiągalny -
public.siteConfigodpowiada dla podłączonej organizacji i workspace'u. Rozróżnia złe slugi, problemy sieciowe i workspace ponad limitem. - Draft secret - backend potwierdza, że zapisany sekret się zgadza. Na platformie bez tego pola raportuje
?i idzie dalej. - Deep link do edytora - zawsze wypisywany.
- Link podglądu roboczego - wypisywany, gdy workspace zgłasza preview URL. Wyjście z trybu roboczego:
/api/draft?disable=1.
Statusy są trzy, nie dwa: ✓ zweryfikowane, ✗ zepsute z poprawką w następnej linii i kodem wyjścia 1, oraz ? nie dało się zweryfikować - co nigdy nie blokuje. Ten trzeci stan istnieje, bo "nieznane" i "zepsute" to różne rzeczy, a narzędzie, które je sklei, albo krzyczy bez powodu, albo ukrywa prawdziwą awarię.
Preflight jest też API
Każde sprawdzenie to czysta funkcja w @cmssy/core, wystawiona pod podsceżką, żeby narzędzia deweloperskie nigdy nie trafiły do Twojego bundla produkcyjnego:
import {
checkWorkspaceReachable,
checkDraftSecret,
checkPreviewUrl,
checkFrameAncestors,
buildEditorUrl,
} from "@cmssy/core/preflight";Każda zwraca { status: "ok" | "fail" | "unknown", message, fix? }. Dwie pierwsze rozmawiają z API dostawczym; reszta to czysta logika na stringach. Żadna nie importuje frameworka ani wbudowanego modułu Node'a, więc działają wszędzie - w endpoincie health, w kroku CI, w dashboardzie.
Gdy okablowanie jest zepsute
W developmencie te same sprawdzenia pilnują route'u edycyjnego. Żądanie edytora, które nie przejdzie weryfikacji, nie daje 404 - adapter renderuje stronę diagnostyczną wewnątrz ramki edytora, linia na sprawdzenie: brakujące zmienne środowiskowe i skąd je wziąć, nieosiągalny workspace, niezgodność draft secretu, porównanie preview URL i originy, które musi dopuszczać frame-ancestors.
Pokazuje slug workspace'u i które sprawdzenie padło, nigdy wartości sekretu.
Następne kroki
- Instalacja - co generuje
init, wyjaśnione. - Tworzenie bloków - co zrobić ze zescaffoldowanym blokiem.
- Podgląd roboczy - sekrety, które zapisuje
link.