@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.
- package/README.md +121 -116
- 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
|
-
- [
|
|
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
|
|
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
|
-
|
|
76
|
+
**NOTE** if your Next.js project is using
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
## Getting started
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
### Create your first Val content file
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
Content in Val is always defined in `.val.ts` (or `.js`) files.
|
|
83
83
|
|
|
84
|
-
**
|
|
84
|
+
**NOTE**: the init script will generate an example Val content file (unless you opt out of it).
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
Val content files are _evaluated_ by Val, therefore they have a specific set of requirements:
|
|
87
87
|
|
|
88
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
96
|
+
Once you have created your Val content file, it must be declared in the `val.modules.ts` (or `.js`) file.
|
|
96
97
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
Example:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
import { modules } from "@valbuild/next";
|
|
102
|
+
import { config } from "./val.config";
|
|
100
103
|
|
|
101
|
-
|
|
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
|
-
|
|
113
|
+
// ./examples/val/example.val.ts
|
|
114
|
+
import { s /* s = schema */, c /* c = content */ } from "../../val.config";
|
|
105
115
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
|
|
113
|
-
|
|
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
|
-
|
|
136
|
+
### Using Val in Client Components
|
|
117
137
|
|
|
118
|
-
|
|
138
|
+
In client components you can access your content with the `useVal` hook:
|
|
119
139
|
|
|
120
|
-
|
|
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
|
-
|
|
146
|
+
export default function Home() {
|
|
147
|
+
const { text } = useVal(exampleVal);
|
|
148
|
+
return <main>{text}</main>;
|
|
149
|
+
}
|
|
150
|
+
```
|
|
123
151
|
|
|
124
|
-
|
|
152
|
+
### Using Val in React Server Components
|
|
125
153
|
|
|
126
|
-
|
|
154
|
+
In React Server components you can access your content with the `fetchVal` function:
|
|
127
155
|
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
168
|
+
# Remote Mode
|
|
132
169
|
|
|
133
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
180
|
+
### Environment Variables
|
|
178
181
|
|
|
179
|
-
|
|
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
|
-
|
|
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
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
234
|
+
## Nullable
|
|
245
235
|
|
|
246
|
-
All schema types can be optional.
|
|
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().
|
|
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({
|
|
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
|
|
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}
|
|
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
|
-
|
|
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.
|
|
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.
|
|
48
|
+
"@valbuild/core": "~0.67.1",
|
|
49
49
|
"@valbuild/react": "~0.67.0",
|
|
50
|
-
"@valbuild/server": "~0.67.
|
|
51
|
-
"@valbuild/shared": "~0.67.
|
|
52
|
-
"@valbuild/ui": "~0.67.
|
|
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
|
},
|