@cmssy/cli 1.0.0 → 9.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +0,0 @@
1
- .block {
2
- margin: 0 auto;
3
- max-width: 42rem;
4
- padding: 3rem 1.5rem;
5
- font-family: system-ui, -apple-system, sans-serif;
6
- }
7
-
8
- .heading {
9
- margin: 0;
10
- font-size: 1.5rem;
11
- font-weight: 700;
12
- }
@@ -1,15 +0,0 @@
1
- import styles from "./{{Pascal}}.module.css";
2
-
3
- type {{Pascal}}Content = {
4
- heading?: string;
5
- };
6
-
7
- export default function {{Pascal}}({ content }: { content: {{Pascal}}Content }) {
8
- const { heading } = content;
9
- if (!heading) return null;
10
- return (
11
- <section className={styles.block}>
12
- <h2 className={styles.heading}>{heading}</h2>
13
- </section>
14
- );
15
- }
@@ -1,11 +0,0 @@
1
- import { defineBlock, fields } from "@cmssy/react";
2
- import {{Pascal}} from "./{{Pascal}}";
3
-
4
- export const {{camel}}Block = defineBlock({
5
- type: "{{type}}",
6
- label: "{{Label}}",
7
- component: {{Pascal}},
8
- props: {
9
- heading: fields.singleLine({ label: "Heading" }),
10
- },
11
- });
@@ -1,19 +0,0 @@
1
- import { buildCmssyMetadata, createCmssyPage } from "@cmssy/next";
2
- import { cmssy } from "@/cmssy.config";
3
- import { blocks } from "@/cmssy/blocks";
4
- import { CmssyEditor } from "@/cmssy/editor";
5
-
6
- // SEO comes from the page's cmssy fields (title/description) + workspace
7
- // branding (OG image), resolved server-side.
8
- export async function generateMetadata({
9
- params,
10
- }: {
11
- params: Promise<{ path?: string[] }>;
12
- }) {
13
- const { path } = await params;
14
- return buildCmssyMetadata(cmssy, path);
15
- }
16
-
17
- // One catch-all route renders every cmssy page. Passing `editor` lets the cmssy
18
- // editor frame and edit this site; published requests render published content.
19
- export default createCmssyPage(cmssy, blocks, { editor: CmssyEditor });
@@ -1,5 +0,0 @@
1
- import { createDraftRoute } from "@cmssy/next";
2
- import { cmssy } from "@/cmssy.config";
3
-
4
- // The cmssy editor hits this route (with the draftSecret) to enter preview mode.
5
- export const GET = createDraftRoute(cmssy);
@@ -1,131 +0,0 @@
1
- .hero {
2
- --c-bg: #ffffff;
3
- --c-fg: #0a0a0a;
4
- --c-primary: #7c3aed;
5
- --c-primary-fg: #ffffff;
6
- --c-muted: #f4f4f5;
7
- --c-muted-fg: #71717a;
8
- --c-border: #e4e4e7;
9
-
10
- position: relative;
11
- overflow: hidden;
12
- background: linear-gradient(
13
- 135deg,
14
- var(--c-muted),
15
- var(--c-bg) 50%,
16
- var(--c-muted)
17
- );
18
- color: var(--c-fg);
19
- font-family:
20
- system-ui,
21
- -apple-system,
22
- sans-serif;
23
- }
24
-
25
- .inner {
26
- margin: 0 auto;
27
- max-width: 48rem;
28
- padding: 6rem 1.5rem;
29
- text-align: center;
30
- }
31
-
32
- .badge {
33
- display: inline-block;
34
- margin-bottom: 1.5rem;
35
- border-radius: 9999px;
36
- background: color-mix(in srgb, var(--c-primary) 12%, transparent);
37
- padding: 0.375rem 1rem;
38
- font-size: 0.875rem;
39
- font-weight: 500;
40
- color: var(--c-primary);
41
- }
42
-
43
- .title {
44
- margin: 0;
45
- font-size: clamp(2.25rem, 5vw, 3.75rem);
46
- font-weight: 700;
47
- letter-spacing: -0.025em;
48
- line-height: 1.1;
49
- }
50
-
51
- .highlight {
52
- background: linear-gradient(90deg, var(--c-primary), var(--c-fg));
53
- -webkit-background-clip: text;
54
- background-clip: text;
55
- color: transparent;
56
- }
57
-
58
- .subheading {
59
- margin: 1.5rem auto 0;
60
- max-width: 36rem;
61
- font-size: 1.125rem;
62
- color: var(--c-muted-fg);
63
- }
64
-
65
- .actions {
66
- margin-top: 2.5rem;
67
- display: flex;
68
- flex-direction: column;
69
- align-items: center;
70
- justify-content: center;
71
- gap: 1rem;
72
- }
73
-
74
- @media (min-width: 640px) {
75
- .actions {
76
- flex-direction: row;
77
- }
78
- }
79
-
80
- .buttonPrimary,
81
- .buttonSecondary {
82
- display: inline-flex;
83
- height: 3rem;
84
- align-items: center;
85
- justify-content: center;
86
- border-radius: 0.375rem;
87
- padding: 0 2rem;
88
- font-size: 1rem;
89
- font-weight: 500;
90
- text-decoration: none;
91
- transition:
92
- opacity 0.2s,
93
- background-color 0.2s;
94
- }
95
-
96
- .buttonPrimary {
97
- background: var(--c-primary);
98
- color: var(--c-primary-fg);
99
- }
100
-
101
- .buttonPrimary:hover {
102
- opacity: 0.9;
103
- }
104
-
105
- .buttonSecondary {
106
- border: 1px solid var(--c-border);
107
- color: var(--c-fg);
108
- }
109
-
110
- .buttonSecondary:hover {
111
- background: var(--c-muted);
112
- }
113
-
114
- .media {
115
- margin-top: 4rem;
116
- overflow: hidden;
117
- border-radius: 0.75rem;
118
- border: 1px solid var(--c-border);
119
- box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
120
- }
121
-
122
- .mediaFrame {
123
- position: relative;
124
- aspect-ratio: 16 / 9;
125
- }
126
-
127
- .video {
128
- width: 100%;
129
- height: 100%;
130
- object-fit: cover;
131
- }
@@ -1,100 +0,0 @@
1
- import Image from "next/image";
2
- import { CmssyLink } from "@cmssy/next/client";
3
- import styles from "./Hero.module.css";
4
-
5
- type HeroContent = {
6
- badgeText?: string;
7
- heading?: string;
8
- headingHighlight?: string;
9
- subheading?: string;
10
- primaryButtonText?: string;
11
- primaryButtonUrl?: string;
12
- secondaryButtonText?: string;
13
- secondaryButtonUrl?: string;
14
- media?: string;
15
- };
16
-
17
- const isVideo = (src: string) => /\.(mp4|webm|ogg)$/i.test(src);
18
-
19
- export default function Hero({ content }: { content: HeroContent }) {
20
- const {
21
- badgeText,
22
- heading,
23
- headingHighlight,
24
- subheading,
25
- primaryButtonText,
26
- primaryButtonUrl = "#",
27
- secondaryButtonText,
28
- secondaryButtonUrl = "#",
29
- media,
30
- } = content;
31
-
32
- if (!heading && !headingHighlight) return null;
33
-
34
- return (
35
- <section className={styles.hero}>
36
- <div className={styles.inner}>
37
- {badgeText && <span className={styles.badge}>{badgeText}</span>}
38
-
39
- <h1 className={styles.title}>
40
- {heading}
41
- {headingHighlight && (
42
- <>
43
- {heading ? " " : ""}
44
- <span className={styles.highlight}>{headingHighlight}</span>
45
- </>
46
- )}
47
- </h1>
48
-
49
- {subheading && <p className={styles.subheading}>{subheading}</p>}
50
-
51
- {(primaryButtonText || secondaryButtonText) && (
52
- <div className={styles.actions}>
53
- {primaryButtonText && (
54
- <CmssyLink
55
- href={primaryButtonUrl}
56
- className={styles.buttonPrimary}
57
- >
58
- {primaryButtonText}
59
- </CmssyLink>
60
- )}
61
- {secondaryButtonText && (
62
- <CmssyLink
63
- href={secondaryButtonUrl}
64
- className={styles.buttonSecondary}
65
- >
66
- {secondaryButtonText}
67
- </CmssyLink>
68
- )}
69
- </div>
70
- )}
71
-
72
- {media && (
73
- <div className={styles.media}>
74
- <div className={styles.mediaFrame}>
75
- {isVideo(media) ? (
76
- <video
77
- src={media}
78
- autoPlay
79
- muted
80
- loop
81
- playsInline
82
- className={styles.video}
83
- />
84
- ) : (
85
- <Image
86
- src={media}
87
- alt={heading ?? ""}
88
- fill
89
- sizes="(max-width: 768px) 100vw, 768px"
90
- style={{ objectFit: "cover" }}
91
- priority
92
- />
93
- )}
94
- </div>
95
- </div>
96
- )}
97
- </div>
98
- </section>
99
- );
100
- }
@@ -1,21 +0,0 @@
1
- import { defineBlock, fields } from "@cmssy/react";
2
- import Hero from "./Hero";
3
-
4
- // A simple content block: plain scalar fields, no loader. The component renders
5
- // nothing until a heading is set, so an empty block is invisible on the page.
6
- export const heroBlock = defineBlock({
7
- type: "hero",
8
- label: "Hero",
9
- component: Hero,
10
- props: {
11
- badgeText: fields.singleLine({ label: "Badge" }),
12
- heading: fields.singleLine({ label: "Heading", required: true }),
13
- headingHighlight: fields.singleLine({ label: "Heading highlight" }),
14
- subheading: fields.multiLine({ label: "Subheading" }),
15
- primaryButtonText: fields.singleLine({ label: "Primary button text" }),
16
- primaryButtonUrl: fields.link({ label: "Primary button URL" }),
17
- secondaryButtonText: fields.singleLine({ label: "Secondary button text" }),
18
- secondaryButtonUrl: fields.link({ label: "Secondary button URL" }),
19
- media: fields.media({ label: "Media (image or video)" }),
20
- },
21
- });
@@ -1,5 +0,0 @@
1
- import { heroBlock } from "@/blocks/hero/block";
2
-
3
- // The single source of truth for which blocks this site can render. The editor
4
- // reads each block's schema over the SDK bridge, so they appear in the picker.
5
- export const blocks = [heroBlock];
@@ -1,10 +0,0 @@
1
- "use client";
2
-
3
- import { CmssyLazyEditor } from "@cmssy/react/client";
4
- import type { CmssyEditorProps } from "@cmssy/next";
5
-
6
- // The editor lazy-loads your block registry on the client, so server-only
7
- // code (block loaders) is never bundled for the browser.
8
- export function CmssyEditor(props: CmssyEditorProps) {
9
- return <CmssyLazyEditor {...props} load={() => import("./blocks")} />;
10
- }
@@ -1,8 +0,0 @@
1
- import type { CmssyNextConfig } from "@cmssy/next";
2
-
3
- export const cmssy: CmssyNextConfig = {
4
- workspaceSlug: process.env.CMSSY_WORKSPACE_SLUG ?? "",
5
- draftSecret: process.env.CMSSY_DRAFT_SECRET ?? "",
6
- // apiUrl: process.env.CMSSY_API_URL,
7
- // editorOrigin: process.env.CMSSY_EDITOR_ORIGIN,
8
- };
@@ -1,4 +0,0 @@
1
- # Your workspace slug (Settings -> Headless in the cmssy dashboard)
2
- CMSSY_WORKSPACE_SLUG=
3
- # Draft/preview secret, generated per workspace (Settings -> Headless)
4
- CMSSY_DRAFT_SECRET=
@@ -1,8 +0,0 @@
1
- /** @type {import('next').NextConfig} */
2
- const nextConfig = {
3
- images: {
4
- remotePatterns: [{ protocol: "https", hostname: "assets.cmssy.io" }],
5
- },
6
- };
7
-
8
- export default nextConfig;
@@ -1,32 +0,0 @@
1
- import { NextResponse, type NextRequest } from "next/server";
2
- import {
3
- applyCmssyCsp,
4
- CMSSY_EDIT_HEADER,
5
- isCmssyEditRequest,
6
- } from "@cmssy/next";
7
- import { cmssy } from "@/cmssy.config";
8
-
9
- // Next.js "proxy" (formerly middleware). It does two things:
10
- // 1. Detects cmssy edit mode (`?cmssyEdit=1`) and exposes it to server
11
- // components via the CMSSY_EDIT_HEADER (stripped from inbound requests
12
- // first so a client can't forge it).
13
- // 2. Applies the CSP `frame-ancestors` so the cmssy editor can frame this
14
- // site in edit mode. editorOrigin defaults to the cmssy admin.
15
- export function proxy(request: NextRequest) {
16
- const editMode = isCmssyEditRequest(request);
17
-
18
- const requestHeaders = new Headers(request.headers);
19
- requestHeaders.delete(CMSSY_EDIT_HEADER);
20
- if (editMode) requestHeaders.set(CMSSY_EDIT_HEADER, "1");
21
-
22
- const response = NextResponse.next({ request: { headers: requestHeaders } });
23
- if (editMode) {
24
- applyCmssyCsp(response, { editorOrigin: cmssy.editorOrigin });
25
- }
26
- return response;
27
- }
28
-
29
- export const config = {
30
- // Skip Next internals, the API routes, and files with an extension.
31
- matcher: ["/((?!_next/|api/|.*\\..*).*)"],
32
- };