Jak zbudować landing page w Cmssy i Next.js
Krok po kroku: zdefiniuj bloki hero, funkcji i CTA w aktualnym SDK Cmssy we własnej aplikacji Next.js, a potem złóż i opublikuj stronę w edytorze wizualnym.
Co sprawia, że landing page działa
Zanim zaczniesz budować, warto wiedzieć, czego potrzebuje skuteczny landing page:
- Jasna propozycja wartości - odwiedzający w kilka sekund rozumieją, co oferujesz.
- Jedno mocne wezwanie do działania - jedno główne CTA, które się wyróżnia i mówi dokładnie, co zrobić.
- Społeczny dowód słuszności - opinie, logo klientów albo liczby, które budują zaufanie.
- Czysty design - każdy element wspiera cel konwersji.
- Szybkie ładowanie - szybkość liczy się dla odwiedzających i dla pozycji w wyszukiwarce.
Jak działa Cmssy
Cmssy to headless CMS z edytorem wizualnym. Bloki piszesz jako komponenty React we własnej aplikacji przy użyciu @cmssy/react i @cmssy/next, a aplikację wdrażasz sam, na Vercel albo gdziekolwiek indziej. Cmssy przechowuje i dostarcza treść, Twoja aplikacja ją renderuje. Edytor wizualny osadza Twoją działającą stronę, więc redaktorzy przeciągają bloki i edytują tekst na prawdziwej stronie.
Krok 1: Zacznij od przykładu albo podłącz własną aplikację
Najszybciej zaczniesz od działającego przykładu. cmssy-io/examples zawiera samodzielne aplikacje, które renderują publiczny demo workspace bez zakładania konta:
git clone https://github.com/cmssy-io/examples
cd examples/next-storefront
pnpm install
cp .env.example .env.local
pnpm devnext-storefront ma już trzy bloki potrzebne na landing page - hero, value-props i cta-banner - więc możesz podejrzeć gotowe wersje wszystkiego, co jest niżej.
Żeby podłączyć własną aplikację, pozwól CLI skopiować pliki i połączyć ją z workspace'em:
npx create-next-app@latest my-site
cd my-site
npx @cmssy/cli@latest init
pnpm install
npx @cmssy/cli@latest link --token cs_...
pnpm devinit zapisuje rejestr bloków w cmssy/blocks.ts, przykładowy blok w blocks/hero/ i stronę catch-all, która renderuje wszystko, co opublikujesz, przez createCmssyPage z @cmssy/next/server. Każdy plik to zwykły kod w Twoim repozytorium. link zapisuje slugi workspace'u i sekret draftu do .env.local i sprawdza je w API.
Krok 2: Zdefiniuj bloki
Blok to komponent React plus schemat, który czyta edytor. Edytowalne pola deklarujesz przez fields, komponent typujesz przez BlockProps, a jedno i drugie rejestrujesz przez defineBlock. Zamień przykładowe hero na takie z wezwaniem do działania.
blocks/hero/Hero.tsx:
import { fields, type BlockProps } from "@cmssy/react";
export const heroProps = {
heading: fields.text({ label: "Heading", required: true }),
subheading: fields.textarea({ label: "Subheading" }),
ctaText: fields.text({ label: "Button text" }),
ctaUrl: fields.link({ label: "Button URL" }),
};
export default function Hero({ content }: BlockProps<typeof heroProps>) {
const { heading, subheading, ctaText, ctaUrl } = content;
return (
<section>
<h1>{heading}</h1>
{subheading ? <p>{subheading}</p> : null}
{ctaText && ctaUrl ? <a href={ctaUrl}>{ctaText}</a> : null}
</section>
);
}blocks/hero/block.ts:
import { defineBlock } from "@cmssy/react";
import Hero, { heroProps } from "./Hero";
export const heroBlock = defineBlock({
type: "hero",
label: "Hero",
component: Hero,
props: heroProps,
});Komponent dostaje wszystko w jednym propsie content, typowanym ze schematu: heading to string, bo jest wymagane, pozostałe pola mogą być undefined. Lista funkcji to repeater, a każdy element ma własny schemat.
blocks/features/Features.tsx:
import { fields, type BlockProps } from "@cmssy/react";
export const featuresProps = {
heading: fields.text({ label: "Heading" }),
items: fields.repeater({
label: "Features",
itemLabel: "Feature",
maxItems: 6,
itemSchema: {
title: fields.text({ label: "Title", required: true }),
text: fields.textarea({ label: "Text" }),
},
}),
};
export default function Features({ content }: BlockProps<typeof featuresProps>) {
const items = content.items ?? [];
return (
<section>
{content.heading ? <h2>{content.heading}</h2> : null}
<ul>
{items.map((item, index) => (
<li key={index}>
<strong>{item.title}</strong>
{item.text ? <p>{item.text}</p> : null}
</li>
))}
</ul>
</section>
);
}blocks/features/block.ts to to samo wywołanie defineBlock co w hero, z type: "features" i component: Features. Blok CTA napisz tak samo - nagłówek, tekst, tekst przycisku i fields.link - albo skopiuj cta-banner z next-storefront, który jest dokładnie tym. Potem wpisz wszystkie trzy do rejestru.
cmssy/blocks.ts:
import { heroBlock } from "@/blocks/hero/block";
import { featuresBlock } from "@/blocks/features/block";
import { ctaBlock } from "@/blocks/cta/block";
export const blocks = [heroBlock, featuresBlock, ctaBlock];Ta tablica to jedyna lista bloków, które Twoja strona umie wyrenderować. Serwer z niej renderuje, a edytor czyta z niej schemat każdego bloku, więc bloki pojawiają się w edytorze z polami, które zadeklarowałeś. Markup i style są Twoje, więc bloki pasują dokładnie do Twojego design systemu.
Krok 3: Utwórz stronę w Cmssy
W panelu Cmssy utwórz nową stronę i nadaj jej nazwę oraz slug, na przykład /launch. Slug to ścieżka, którą wyrenderuje Twoja aplikacja. Strona startuje pusta - za chwilę wypełnisz ją blokami.
Krok 4: Złóż stronę w edytorze wizualnym
Otwórz stronę w edytorze. Podczas developmentu ustaw w edytorze Dev host na http://localhost:3000; dla wdrożonej strony ustaw Preview URL workspace'u. Edytor osadza Twoją działającą aplikację, więc widzisz prawdziwe komponenty. Przeciągnij bloki Hero, Features i CTA w tej kolejności i kliknij dowolny blok, żeby go edytować - zadeklarowane pola pojawiają się jako kontrolki formularza. Napisz nagłówek, dodaj trzy lub cztery korzyści i ustaw tekst oraz link przycisku.
Krok 5: Dodaj dowód społeczny
Ludzie ufają innym ludziom. Jeśli masz blok z opiniami, logo albo statystykami (next-storefront ma stats-band), wstaw go zaraz po hero, żeby zbudować wiarygodność, zanim poprosisz o konwersję.
Krok 6: Niech pisze agent AI (opcjonalnie)
Panel ma wbudowanego asystenta (Cmd + K), który działa na kluczu modelu, który przynosisz sam, a te same narzędzia są dostępne dla Claude i innych klientów MCP przez serwer MCP. Oba są w każdym planie. Gdy strona jest otwarta w edytorze, asystent może ją wygenerować, przetłumaczyć albo edytować bloki, które masz przed sobą; napisze też tytuł i opis SEO. Edytuje wyłącznie treść, nigdy Twój kod, a zmiany na kanwie pozostają niezapisane, dopóki ich nie zapiszesz. Publikacja należy do kroków, które czekają na Twoje potwierdzenie.
Krok 7: Skonfiguruj SEO
Każda strona ma tytuł SEO i opis meta w każdym języku oraz listę słów kluczowych:
- Tytuł SEO - umieść główne słowo kluczowe i zmieść się w 60 znakach.
- Opis meta - streść stronę w około 155 znakach, z wezwaniem do działania.
- Słowa kluczowe - frazy, których szukają Twoi odbiorcy.
API dostarczania zwraca je razem ze stroną, a Twoja aplikacja wstawia je do metadanych Next.js w generateMetadata. Przykład next-storefront robi to w services/seo.ts.
Krok 8: Opublikuj
Kliknij Publikuj. Treść trafia na żywo przez API dostarczania, a Twoja aplikacja renderuje ją pod ustawionym slugiem, na Twojej domenie i Twoim hostingu. Skieruj webhook content.changed na trasę /api/revalidate w aplikacji (CLI zapisuje ją za Ciebie), a publikacja pojawi się bez ponownego wdrożenia.
Dobre praktyki landing page
- Jeden cel na stronę - każdy landing page powinien mieć jeden cel konwersji.
- Najpierw mobile - testuj na małych ekranach przed wszystkim innym.
- Testuj nagłówki - drobne zmiany nagłówka potrafią wyraźnie ruszyć konwersję.
- Pilnuj czasu ładowania - kompresuj obrazy i wyrzuć skrypty, których strona nie potrzebuje.
- Pilność tylko uczciwa - prawdziwy termin pomaga, fałszywy licznik kosztuje zaufanie.
Następne kroki
- Sklonuj cmssy-io/examples i przejrzyj gotowe bloki w
next-storefront. - Przejdź przewodnik instalacji, żeby podłączyć własną aplikację.
- Przeczytaj, jak definiuje się bloki i jakie są typy pól.
- Skonfiguruj asystenta AI albo serwer MCP.