@valbuild/next 0.67.0 → 0.67.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.
Files changed (2) hide show
  1. package/README.md +121 -116
  2. package/package.json +5 -5
package/README.md CHANGED
@@ -50,7 +50,7 @@ This version of Val is currently an alpha version - the API can be considered re
50
50
  - [String](#string)
51
51
  - [Number](#number)
52
52
  - [Boolean](#boolean)
53
- - [Optional](#optional)
53
+ - [Nullable](#nullable)
54
54
  - [Array](#array)
55
55
  - [Record](#record)
56
56
  - [Object](#object)
@@ -60,7 +60,7 @@ This version of Val is currently an alpha version - the API can be considered re
60
60
 
61
61
  ## Installation
62
62
 
63
- - Make sure you have TypeScript 5+, Next 13.4+ (other meta frameworks will come), React 18.20.+ (other frontend frameworks will come)
63
+ - Make sure you have TypeScript 5+, Next 14+, React 18.20.+
64
64
  - Install the packages (@valbuild/eslint-plugin is recommended but not required):
65
65
 
66
66
  ```sh
@@ -73,146 +73,136 @@ npm install @valbuild/core@latest @valbuild/next@latest @valbuild/eslint-plugin@
73
73
  npx @valbuild/init@latest
74
74
  ```
75
75
 
76
- ### Online mode
76
+ **NOTE** if your Next.js project is using
77
77
 
78
- To make it possible to do online edits directly in your app, head over to [val.build](https://app.val.build), sign up and import your repository.
78
+ ## Getting started
79
79
 
80
- **NOTE**: your content is yours. No subscription (or similar) is required to host content from your repository.
80
+ ### Create your first Val content file
81
81
 
82
- If you do not need to edit content online (i.e. not locally), you do not need to sign up.
82
+ Content in Val is always defined in `.val.ts` (or `.js`) files.
83
83
 
84
- **WHY**: to update your code, we need to create a commit. This requires a server. We opted to create a service that does this easily, instead of having a self-hosted alternative, since time spent is money used. Also, the company behind [val.build](https://val.build) is the company that funds the development of this software.
84
+ **NOTE**: the init script will generate an example Val content file (unless you opt out of it).
85
85
 
86
- #### Online mode configuration
86
+ Val content files are _evaluated_ by Val, therefore they have a specific set of requirements:
87
87
 
88
- Once you have setup your project in [val.build](https://app.val.build), you must configure your application to use this project.
88
+ - they must export a default content definition (`c.define`) where the first argument equals the path of the file relative to the `val.config.ts` file; and
89
+ - they must have a default export that is `c.define; and
90
+ - they can only import Val related files and / or types
89
91
 
90
- To do this, you must set the following environment variables:
92
+ If you use the eslint plugins these requirements will be enforced. You can also validate val files using the @valbuild/cli: `npx -p @valbuild/cli val validate --fix`
91
93
 
92
- - `VAL_API_KEY`: you get this in your project configuration page.
93
- - `VAL_SECRET`: this is a random secret you can generate. It is used for communication between the UX client and your Next.js application.
94
+ ### Adding Val content file to val.modules
94
95
 
95
- In addition, you need to set the following properties in the `val.config` file:
96
+ Once you have created your Val content file, it must be declared in the `val.modules.ts` (or `.js`) file.
96
97
 
97
- - project: This is the fully qualified name of your project. It should look like this: `<team>/<name>`.
98
- - gitBranch: This is the git branch your application is using. In Vercel you can use: `VERCEL_GIT_COMMIT_REF`.
99
- - gitCommit: This is the current git commit your application is running on. In Vercel you can use: `VERCEL_GIT_COMMIT_SHA`
98
+ Example:
99
+
100
+ ```ts
101
+ import { modules } from "@valbuild/next";
102
+ import { config } from "./val.config";
100
103
 
101
- Example of `val.config.ts`:
104
+ export default modules(config, [
105
+ // Add your modules here
106
+ { def: () => import("./examples/val/example.val") },
107
+ ]);
108
+ ```
109
+
110
+ ### Example of a `.val.ts` file
102
111
 
103
112
  ```ts
104
- import { initVal } from "@valbuild/next";
113
+ // ./examples/val/example.val.ts
114
+ import { s /* s = schema */, c /* c = content */ } from "../../val.config";
105
115
 
106
- const { s, c, val, config } = initVal({
107
- project: "myteam/myproject",
108
- gitBranch: process.env.VERCEL_GIT_COMMIT_REF,
109
- gitCommit: process.env.VERCEL_GIT_COMMIT_SHA,
116
+ /**
117
+ * This is the schema for the content. It defines the structure of the content and the types of each field.
118
+ */
119
+ export const schema = s.object({
120
+ /**
121
+ * Basic text field
122
+ */
123
+ text: s.string(),
110
124
  });
111
125
 
112
- export type { t } from "@valbuild/next";
113
- export { s, c, val, config };
126
+ /**
127
+ * This is the content definition. Add your content below.
128
+ *
129
+ * NOTE: the first argument is the path of the file.
130
+ */
131
+ export default c.define("/examples/val/example.val.ts", schema, {
132
+ text: "Basic text content",
133
+ });
114
134
  ```
115
135
 
116
- ## Getting started
136
+ ### Using Val in Client Components
117
137
 
118
- ### Create your first Val content file
138
+ In client components you can access your content with the `useVal` hook:
119
139
 
120
- Content in Val is always defined in `.val.ts` files.
140
+ ```tsx
141
+ // ./app/page.tsx
142
+ "use client";
143
+ import { useVal } from "../val/val.client";
144
+ import exampleVal from "../examples/val/example.val";
121
145
 
122
- **NOTE**: Val also works with `.js` files.
146
+ export default function Home() {
147
+ const { text } = useVal(exampleVal);
148
+ return <main>{text}</main>;
149
+ }
150
+ ```
123
151
 
124
- They must export a default content definition (`c.define`) where the first argument equals the path of the file relative to the `val.config.ts` file.
152
+ ### Using Val in React Server Components
125
153
 
126
- **NOTE**: `val.ts` files are _evaluated_ by Val, therefore they have a specific set of requirements:
154
+ In React Server components you can access your content with the `fetchVal` function:
127
155
 
128
- - They must have a default export that is `c.define`, they must have a `export const schema` with the Schema; and
129
- - they CANNOT import anything other than `val.config` and `@valbuild/core`
156
+ ```tsx
157
+ // ./app/page.tsx
158
+ "use server";
159
+ import { fetchVal } from "../val/val.rsc";
160
+ import exampleVal from "../examples/val/example.val";
161
+
162
+ export default async function Home() {
163
+ const { text } = await fetchVal(exampleVal);
164
+ return <main>{text}</main>;
165
+ }
166
+ ```
130
167
 
131
- ### Example of a `.val.ts` file
168
+ # Remote Mode
132
169
 
133
- ```ts
134
- // ./src/app/content.val.ts
170
+ Enable remote mode to allow editors to update content online (outside of local development) by creating a project at [app.val.build](https://app.val.build).
135
171
 
136
- import { s, c } from "../../../val.config";
172
+ **NOTE**: Your content remains yours. Hosting content from your repository does not require a subscription. However, to edit content online, a subscription is needed — unless your project is a public repository or qualifies for the free tier. Visit the [pricing page](https://val.build/pricing) for details.
137
173
 
138
- export const schema = s.object({
139
- title: s.string().optional(), // <- NOTE: optional()
140
- sections: s.array(
141
- s.object({
142
- title: s.string(),
143
- text: s.richtext({
144
- style: {
145
- bold: true, // <- Enables bold in richtext
146
- },
147
- }),
148
- }),
149
- ),
150
- });
174
+ **WHY**: Updating code involves creating a commit, which requires a server. We offer a hosted service for simplicity and efficiency, as self-hosted solutions takes time to setup and maintain. Additionally, the [val.build](https://val.build) team funds the ongoing development of this library.
151
175
 
152
- export default c.define(
153
- "/src/app/content", // <- NOTE: this must be the same path as the file
154
- schema,
155
- {
156
- title: "My Page",
157
- sections: [
158
- {
159
- title: "Section 1",
160
- text: [
161
- {
162
- tag: "p",
163
- children: [
164
- "Val is",
165
- { tag: "span", styles: ["bold"], children: ["awesome"] },
166
- ],
167
- },
168
- ],
169
- },
170
- ],
171
- },
172
- );
173
- ```
176
+ ## Remote Mode Configuration
174
177
 
175
- ### Use your content
178
+ Once your project is set up in [app.val.build](https://app.val.build), configure your application to use it by setting the following:
176
179
 
177
- In client components you can access your content with the `useVal` hook:
180
+ ### Environment Variables
178
181
 
179
- **NOTE**: Support for React Server Components and server side rendering will come soon.
182
+ - **`VAL_API_KEY`**: Obtain this from your project's configuration page.
183
+ - **`VAL_SECRET`**: Generate a random secret to secure communication between the UX client and your Next.js application.
180
184
 
181
- ```tsx
182
- // ./src/app/page.tsx
183
- "use client";
184
- import { NextPage } from "next";
185
- import { useVal } from "./val/val.client";
186
- import contentVal from "./content.val";
185
+ ### `val.config` Properties
187
186
 
188
- const Page: NextPage = () => {
189
- const { title, sections } = useVal(contentVal);
190
- return (
191
- <main>
192
- {title && (
193
- <section>
194
- <h1>{title}</h1>
195
- </section>
196
- )}
197
- {sections.map((section) => (
198
- <section>
199
- <h2>{section.title}</h2>
200
- <ValRichText
201
- theme={{
202
- style: {
203
- bold: "font-bold",
204
- },
205
- }}
206
- >
207
- {section.text}
208
- </ValRichText>
209
- </section>
210
- ))}
211
- </main>
212
- );
213
- };
187
+ Set these properties in the `val.config` file:
188
+
189
+ - **`project`**: The fully qualified name of your project, formatted as `<team>/<name>`.
190
+ - **`gitBranch`**: The Git branch your application uses. For Vercel, use `VERCEL_GIT_COMMIT_REF`.
191
+ - **`gitCommit`**: The current Git commit your application is running on. For Vercel, use `VERCEL_GIT_COMMIT_SHA`.
192
+
193
+ ### Example `val.config.ts`
194
+
195
+ ```ts
196
+ import { initVal } from "@valbuild/next";
214
197
 
215
- export default Page;
198
+ const { s, c, val, config } = initVal({
199
+ project: "myteam/myproject",
200
+ gitBranch: process.env.VERCEL_GIT_COMMIT_REF,
201
+ gitCommit: process.env.VERCEL_GIT_COMMIT_SHA,
202
+ });
203
+
204
+ export type { t } from "@valbuild/next";
205
+ export { s, c, val, config };
216
206
  ```
217
207
 
218
208
  # Schema types
@@ -241,14 +231,14 @@ import { s } from "./val.config";
241
231
  s.boolean(); // <- Schema<boolean>
242
232
  ```
243
233
 
244
- ## Optional
234
+ ## Nullable
245
235
 
246
- All schema types can be optional. An optional schema creates a union of the type and `null`.
236
+ All schema types can be nullable (optional). A nullable schema creates a union of the type and `null`.
247
237
 
248
238
  ```ts
249
239
  import { s } from "./val.config";
250
240
 
251
- s.string().optional(); // <- Schema<string | null>
241
+ s.string().nullable(); // <- Schema<string | null>
252
242
  ```
253
243
 
254
244
  ## Array
@@ -384,7 +374,7 @@ To add classes to `ValRichText` you can use the theme property:
384
374
  </ValRichText>
385
375
  ```
386
376
 
387
- **NOTE**: if a theme is defined, you must define a mapping for every tag that the you get. What tags you have is decided based on the `options` defined on the `s.richtext()` schema. For example: `s.richtext({ headings: ["h1"]; bold: true; img: true})` forces you to map the class for at least: `h1`, `bold` and `img`:
377
+ **NOTE**: if a theme is defined, you must define a mapping for every tag that the you get. What tags you have is decided based on the `options` defined on the `s.richtext()` schema. For example: `s.richtext({ style: { bold: true } })` requires that you add a `bold` theme.
388
378
 
389
379
  ```tsx
390
380
  <ValRichText
@@ -394,7 +384,7 @@ To add classes to `ValRichText` you can use the theme property:
394
384
  img: null, // either a string or null is required
395
385
  }}
396
386
  >
397
- {content satisfies RichText<{ headings: ["h1"]; bold: true; img: true }>}
387
+ {content}
398
388
  </ValRichText>
399
389
  ```
400
390
 
@@ -404,7 +394,7 @@ To add classes to `ValRichText` you can use the theme property:
404
394
 
405
395
  Vals `RichText` type maps RichText 1-to-1 with semantic HTML5.
406
396
 
407
- If you want to customize the type of elements which are rendered, you can use the `transform` property.
397
+ If you want to customize / override the type of elements which are rendered, you can use the `transform` property.
408
398
 
409
399
  ```tsx
410
400
  <ValRichText
@@ -525,9 +515,9 @@ The `ValImage` component is a wrapper around `next/image` that accepts a Val `Im
525
515
  You can use it like this:
526
516
 
527
517
  ```tsx
528
- const content = useVal(contentVal);
518
+ const content = useVal(contentVal); // schema of contentVal: s.object({ image: s.image() })
529
519
 
530
- return <ValImage src={content.image} alt={content.alt} />;
520
+ return <ValImage src={content.image} />;
531
521
  ```
532
522
 
533
523
  ### Using images in components
@@ -585,7 +575,22 @@ s.union(
585
575
 
586
576
  ## KeyOf
587
577
 
588
- If you need to reference content in another `.val` file you can use the `keyOf` schema.
578
+ You can use `keyOf` to reference a key in a record of a Val module.
579
+
580
+ **NOTE**: currently you must reference keys in Val modules, you cannot reference keys of values nested inside a Val module. This is a feature on the roadmap.
581
+
582
+ ```ts
583
+ const schema = s.record(s.object({ nested: s.record(s.string()) }));
584
+
585
+ export default c.define("/keyof.val.ts", schema, {
586
+ "you-can-reference-me": {
587
+ // <- this can be referenced
588
+ nested: {
589
+ "but-not-me": ":(", // <- this cannot be referenced
590
+ },
591
+ },
592
+ });
593
+ ```
589
594
 
590
595
  ### KeyOf Schema
591
596
 
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "next",
9
9
  "react"
10
10
  ],
11
- "version": "0.67.0",
11
+ "version": "0.67.1",
12
12
  "scripts": {
13
13
  "typecheck": "tsc --noEmit",
14
14
  "test": "jest"
@@ -45,11 +45,11 @@
45
45
  "exports": true
46
46
  },
47
47
  "dependencies": {
48
- "@valbuild/core": "~0.67.0",
48
+ "@valbuild/core": "~0.67.1",
49
49
  "@valbuild/react": "~0.67.0",
50
- "@valbuild/server": "~0.67.0",
51
- "@valbuild/shared": "~0.67.0",
52
- "@valbuild/ui": "~0.67.0",
50
+ "@valbuild/server": "~0.67.1",
51
+ "@valbuild/shared": "~0.67.1",
52
+ "@valbuild/ui": "~0.67.1",
53
53
  "client-only": "^0.0.1",
54
54
  "server-only": "^0.0.1"
55
55
  },