Teraz z AI - twórz strony przez serwer MCP

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 init

CLI 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 roboczy

Zwróć 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-site

Wszystkie 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.

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.com

Uwierzytelnia 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.siteConfig odpowiada 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