smoodly 0.0.59 → 0.0.61
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 +3 -1
- package/dist/admin/files.generated.js +1 -1
- package/dist/admin/ui/theme.js +1 -1
- package/dist/api-client.js +5 -3
- package/dist/astro/index.js +3 -3
- package/dist/cli/push.js +2 -3
- package/dist/env.js +3 -2
- package/dist/push.d.ts +7 -0
- package/dist/push.js +8 -0
- package/dist/space-kind.d.ts +2 -0
- package/dist/space-kind.js +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/collections/defining.md +57 -0
- package/docs/collections/entry-pages.md +168 -0
- package/docs/collections/ordering.md +47 -0
- package/docs/collections/queries.md +173 -0
- package/docs/content-modeling/changing-schemas.md +79 -0
- package/docs/content-modeling/custom-section.md +94 -0
- package/docs/content-modeling/marks.md +97 -0
- package/docs/content-modeling/overview.md +55 -0
- package/docs/content-modeling/page-types.md +237 -0
- package/docs/content-modeling/sections.md +264 -0
- package/docs/content-modeling/styles-and-settings.md +184 -0
- package/docs/content-modeling/zones.md +80 -0
- package/docs/fields/choices.md +42 -0
- package/docs/fields/conditional.md +72 -0
- package/docs/fields/link.md +31 -0
- package/docs/fields/list-and-object.md +58 -0
- package/docs/fields/media.md +103 -0
- package/docs/fields/overview.md +56 -0
- package/docs/fields/reference-and-tags.md +62 -0
- package/docs/fields/richtext.md +168 -0
- package/docs/fields/text.md +152 -0
- package/docs/frameworks/astro.md +110 -0
- package/docs/frameworks/nextjs.md +147 -0
- package/docs/getting-started/content-from-code.md +263 -0
- package/docs/getting-started/deploying.md +131 -0
- package/docs/getting-started/export-and-import.md +73 -0
- package/docs/getting-started/first-page.md +98 -0
- package/docs/getting-started/install.md +108 -0
- package/docs/getting-started/keys.md +40 -0
- package/docs/getting-started/project-structure.md +142 -0
- package/docs/getting-started/working-together.md +42 -0
- package/docs/globals/defining.md +99 -0
- package/docs/globals/header-and-footer.md +117 -0
- package/docs/index.md +83 -0
- package/docs/languages/language-switcher.md +103 -0
- package/docs/languages/locales.md +119 -0
- package/docs/languages/localized-fields.md +61 -0
- package/docs/media/images-and-crops.md +131 -0
- package/docs/media/library.md +40 -0
- package/docs/pages/drafts-and-publishing.md +44 -0
- package/docs/pages/page-tree.md +51 -0
- package/docs/pages/paths-and-slugs.md +74 -0
- package/docs/pages/seo.md +126 -0
- package/docs/pages/version-history.md +23 -0
- package/docs/reference/upgrading.md +312 -0
- package/package.json +4 -3
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# Upgrading
|
|
2
|
+
|
|
3
|
+
Update the package and deploy. Your content model lives in your code and every build pushes it to your space: there is no migration to run.
|
|
4
|
+
|
|
5
|
+
## When the schema moves
|
|
6
|
+
|
|
7
|
+
Nothing to run. A space's content lives in Smoodly's service, and your content model lives in your code: every build pushes it to the space (a Next site's `prebuild` runs `smoodly push`, an Astro build does it itself), and so does the dev server. Update `smoodly`, build and deploy; restart the dev server after an upgrade. `npx smoodly --version` prints the version you have.
|
|
8
|
+
|
|
9
|
+
The `migrate` and `rebuild` commands are gone, and so is the build's schema check. Up to 0.0.51 a site's content lived in a Postgres schema it migrated itself; that history is in git, in this page as of v0.0.51.
|
|
10
|
+
|
|
11
|
+
The sections below name each version's changes to your code. Going up several versions at once, work through each section between your version and the new one, oldest first. A version without a section needs no change in your code.
|
|
12
|
+
|
|
13
|
+
## Upgrading to 0.0.36
|
|
14
|
+
|
|
15
|
+
0.0.36 changes what a read returns and closes public reads.
|
|
16
|
+
|
|
17
|
+
| Before | After |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `item.entry.fields.title`, `item.entry.id` | `item.fields.title`, `item.id` |
|
|
20
|
+
| entry page view `({ entry, path, locale, locales })` | `({ entry })`, with `entry.path`, `entry.locale`, `entry.locales` |
|
|
21
|
+
| a reference in a section or an entry, `f.ref` or `f.refList`: `a.slug`, `a.name` plus your own path helper | `a.fields.name`, `a.path` |
|
|
22
|
+
| `getGlobal(...)` spread into the view, every global (the Lorem starter's header in `PageFrame.tsx`, and the `contact` prop the layout passes to `FooterView`) | `{ fields, settings, styles }`: `<HeaderView {...header.fields} settings={header.settings} styles={header.styles} />`, and `contact?.fields` |
|
|
23
|
+
| a reference's `path` used as a string | `string \| null`: a reference to an entry without an address has none |
|
|
24
|
+
| `entry.fields as ArticleFields`, the Lorem starter's hand-written field types, a reference's `a.fields` included | `as unknown as ArticleFields` where a component takes the hand-written type; elsewhere drop the cast, `fields` is typed from the collection |
|
|
25
|
+
| `getPage(...).record`, `.tree`, `.tree.meta` | a page item with `seo` |
|
|
26
|
+
| page registration `meta: { seo: true }` | `seo: true` |
|
|
27
|
+
| `createSmoodlyAdmin({ …, content })` | `createSmoodlyAdmin({ …, presence })` |
|
|
28
|
+
| reading content with the publishable key | not possible; a route in your app over `q` |
|
|
29
|
+
| `publicContent()` in `smoodly/server.ts`, with `publicContentConfig` and `ContentConfig` | `presence()`, returning `presenceConfig(smoodlyEnv())`, typed `Promise<PresenceConfig>` (both from `smoodly`) |
|
|
30
|
+
| a global in the layout: `<Footer {...footer} />` | `<Footer {...footer.fields} settings={footer.settings} styles={footer.styles} />` |
|
|
31
|
+
| dropping missing references: `.filter(Boolean)` | `.filter((p) => p !== null)`, which TypeScript narrows |
|
|
32
|
+
|
|
33
|
+
Also new: `where` filters the version shown and works on localized fields, references resolve as deep as their field says everywhere, and a collection can turn on `seo`. The [Next.js guide](../frameworks/nextjs.md#content-in-the-browser) shows the route that replaces a browser read.
|
|
34
|
+
|
|
35
|
+
## Upgrading to 0.0.38
|
|
36
|
+
|
|
37
|
+
0.0.38 has no schema change. It replaces the starter's `stores()` with two functions in `smoodly/server.ts`, and the site needs one variable less.
|
|
38
|
+
|
|
39
|
+
| Before | After |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `stores()` in a seed or a script | `content()`, the [content API](../getting-started/content-from-code.md) |
|
|
42
|
+
| `stores()` and `adminAuth()` in `smoodly/ops.ts` | `adminDeps()`, which carries `auth`; delete the `adminAuth` export from `smoodly/server.ts` |
|
|
43
|
+
| the starter's own `scripts/seed.ts` | it ran once, at install: delete it, the `seed` line in `package.json`, and in `AGENTS.md` the `npm run seed` line and the "Seed through the stores" rule |
|
|
44
|
+
| hand-built tree nodes cast to `PageTree` | `node(Section, fields)` |
|
|
45
|
+
| the site requires all three variables | the site requires `SMOODLY_URL` and `SMOODLY_SECRET_KEY`; the admin also `SMOODLY_PUBLISHABLE_KEY` |
|
|
46
|
+
|
|
47
|
+
In `smoodly/server.ts`, replace the exported `stores()` with these two (the stores built inside `bound()` stay), and add `createSmoodlyContent` and `type SmoodlyContent` to the import from `smoodly/admin`:
|
|
48
|
+
|
|
49
|
+
File: `smoodly/server.ts`
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
export function adminDeps() {
|
|
53
|
+
smoodlyEnv("admin"); // the admin signs in with the publishable key: a missing one is named here, not on a live page
|
|
54
|
+
const { pages, entries, assets, members, auth, site } = bound();
|
|
55
|
+
// …
|
|
56
|
+
return { pages, entries, assets, members, auth, href, projector: site.projector };
|
|
57
|
+
}
|
|
58
|
+
// …
|
|
59
|
+
export function content(): SmoodlyContent {
|
|
60
|
+
const { pages, entries, assets, members, site } = bound();
|
|
61
|
+
return createSmoodlyContent({ config, pages, entries, assets, members, href, projector: site.projector });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { node } from "smoodly";
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`smoodly/ops.ts` then took everything from `adminDeps()`; the file is gone since the admin became one route (below).
|
|
68
|
+
|
|
69
|
+
A fixed page or a collection's list page that has no record yet is now served from code, so a page type added after install no longer waits for an editor to open *Pages*. Cached reads are keyed by the package version and your content model, so an upgrade never serves a page cached in the old shape.
|
|
70
|
+
|
|
71
|
+
## Upgrading to 0.0.40
|
|
72
|
+
|
|
73
|
+
0.0.40 has no schema change and nothing breaks. Every page and entry now gets a canonical link, and a page its Open Graph URL, both built from `metadataBase`. One change is worth making in your root layout:
|
|
74
|
+
|
|
75
|
+
| Before | After |
|
|
76
|
+
|---|---|
|
|
77
|
+
| `metadataBase: new URL(process.env.SITE_URL \|\| "http://localhost:3000")`, or no `metadataBase` in a site installed before 0.0.35 | `metadataBase: siteUrl()` in the root layout's `metadata`, with `import { siteUrl } from "smoodly"` |
|
|
78
|
+
|
|
79
|
+
`siteUrl()` names `SITE_URL` when it lacks `https://`, where the old line failed every page with a bare "Invalid URL", and warns once in production when it is unset. Also new: `content().pages.list()`, and an unreachable `SMOODLY_URL` is named in the error.
|
|
80
|
+
|
|
81
|
+
## Upgrading to 0.0.44
|
|
82
|
+
|
|
83
|
+
0.0.44 has no schema change and nothing breaks. One change in `smoodly/server.ts` lets `next build` run without the keys, for a CI or a host that builds without secrets: the read helpers wait for a request before they read the environment. (0.0.44 shipped the gate as `connection()` from `next/server`; the excerpts below show today's `buildGate()` from `smoodly/next`, which 0.0.50 renamed it to.)
|
|
84
|
+
|
|
85
|
+
File: `smoodly/server.ts`
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
export const q = (): Queries =>
|
|
89
|
+
new Proxy({} as Queries, {
|
|
90
|
+
get: (_, name) => async (...args: unknown[]) => {
|
|
91
|
+
await buildGate();
|
|
92
|
+
return (bound().q as unknown as Record<string | symbol, (...a: unknown[]) => unknown>)[name](...args);
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Do the same for the four render helpers, `renderSmoodlyPath`, `smoodlyMetadata`, `renderSmoodlyPage` and `smoodlyPageMetadata`, the gate first:
|
|
98
|
+
|
|
99
|
+
File: `smoodly/server.ts`
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
export const renderSmoodlyPath: Renderer["renderSmoodlyPath"] = async (...args) => { await buildGate(); return bound().renderer.renderSmoodlyPath(...args); };
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Upgrading to 0.0.46
|
|
106
|
+
|
|
107
|
+
0.0.46's delivery tables and their rebuild belonged to the Postgres schema, and nothing of them is left to do.
|
|
108
|
+
|
|
109
|
+
Astro ships: `npx create-smoodly-app --framework astro` makes a new Astro site. Nothing changes for a Next.js site beyond the steps below. 0.0.46 also changes how a site registers its content model: the config registers schemas, and a new file lists the components. The config then loads without React, so the CLI, a script and an agent can read it.
|
|
110
|
+
|
|
111
|
+
Components now import from `smoodly/react`, and schemas from `smoodly`. The root entry loads no React, so an Astro project installs none; `react` is an optional peer dependency of the package.
|
|
112
|
+
|
|
113
|
+
1. Move each schema into a file beside its component: `export const heroSchema = …` goes from `Hero.tsx` to `Hero.schema.ts`, and `Hero.tsx` imports it. Do the same for elements and page types. A schema file imports no component.
|
|
114
|
+
2. List schemas where components were listed: `smoodly/sections.ts`, `smoodly/elements.ts` and `pages` in `smoodly/config.ts`. Entry pages leave the config.
|
|
115
|
+
3. Pass schemas to `z.locked()`, `z.sections()`, `z.freeform()`, `smoodly.toolset()`, `smoodly.global({ section })` and `node()`.
|
|
116
|
+
4. Create `smoodly/views.ts` with every component, the entry pages included, and move `RichText` there from the config's `custom`:
|
|
117
|
+
|
|
118
|
+
File: `smoodly/views.ts`
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
export const views = () =>
|
|
122
|
+
defineViews(config, {
|
|
123
|
+
sections: [Hero, PageHero, ImageText, Points, FavouriteArticles, People, Quote, Header, Footer],
|
|
124
|
+
elements: [Callout, Cta],
|
|
125
|
+
pages: [HomePage, ArticlesPage, StandardPage, ArticlePage, NewsPage, NewsPostPage],
|
|
126
|
+
RichText,
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
5. In `smoodly/richtext.tsx`, import the element components directly, since `smoodly/elements.ts` now lists schemas: `createRichText({ elements: [Callout, Cta], … })`. An element with a view but missing here is named on the first render.
|
|
131
|
+
6. In `smoodly/server.ts`, build the stores and the site from the config and hand the renderer the views:
|
|
132
|
+
|
|
133
|
+
File: `smoodly/server.ts`
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
const { pages, entries, assets, members, published } = createSupabaseStores(db, config);
|
|
137
|
+
// …
|
|
138
|
+
const site = createSmoodlySite(siteOptions(config, () => ({ pages, entries, assets, published })));
|
|
139
|
+
// …
|
|
140
|
+
const renderer = createPageRenderer({ site, ...views(), href });
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
In the same file, `adminDeps()` and `content()` hand the operations the site's projector. A publish then writes the finished document of every page and entry it changes, and a live page reads it in one lookup:
|
|
144
|
+
|
|
145
|
+
File: `smoodly/server.ts`
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
const { pages, entries, assets, members, auth, site } = bound();
|
|
149
|
+
// The projector: a publish writes the finished documents a live page reads.
|
|
150
|
+
return { pages, entries, assets, members, auth, href, projector: site.projector };
|
|
151
|
+
// …
|
|
152
|
+
const { pages, entries, assets, members, site } = bound();
|
|
153
|
+
return createSmoodlyContent({ config, pages, entries, assets, members, href, projector: site.projector });
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
7. In every component file and in `smoodly/views.ts`, change `from "smoodly"` to `from "smoodly/react"`. Schema files, the config, `smoodly/server.ts` and scripts keep `"smoodly"`. A pairing line left on the root fails to compile: `smoodly.section` is no longer there.
|
|
157
|
+
|
|
158
|
+
A component left where a schema belongs is named: `smoodly: pass the schema, not the component — "hero" is registered by its schema (heroSchema), and its component goes to defineViews.` A schema with no component is named on the first render.
|
|
159
|
+
|
|
160
|
+
Names now need to be unique per kind only: a section and a collection may share one. Sections and elements share a namespace, as do collections and globals.
|
|
161
|
+
|
|
162
|
+
The admin now ships prebuilt in the package, and one route file serves it:
|
|
163
|
+
|
|
164
|
+
1. Create `app/(smoodly)/admin/[[...segments]]/route.ts`:
|
|
165
|
+
|
|
166
|
+
File: `app/(smoodly)/admin/[[...segments]]/route.ts`
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
import { createAdminRoute } from "smoodly/next";
|
|
170
|
+
import { config } from "@/smoodly/config";
|
|
171
|
+
import { adminDeps, presence } from "@/smoodly/server";
|
|
172
|
+
|
|
173
|
+
export const { GET, POST } = createAdminRoute(() => ({ config, ...adminDeps(), presence }));
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
2. Delete `app/(smoodly)/admin/[[...segments]]/page.tsx`, `app/(smoodly)/admin/layout.tsx`, `smoodly/admin.tsx` and `smoodly/ops.ts`.
|
|
177
|
+
3. Nothing else imports from `smoodly/admin/next`: that entry is gone. `smoodly/admin` is unchanged.
|
|
178
|
+
|
|
179
|
+
Your app no longer compiles the admin, so a build is faster and an admin fix needs only the package update. The admin's font is served by your own site; it no longer asks Google Fonts for it.
|
|
180
|
+
|
|
181
|
+
## Upgrading to 0.0.48
|
|
182
|
+
|
|
183
|
+
A site in live mode changes nothing. Static mode is new and opt-in for Astro: set `output: "static"` in `astro.config` and follow [Deploying › Static](../getting-started/deploying.md#static).
|
|
184
|
+
|
|
185
|
+
Next, [Export and import](../getting-started/export-and-import.md).
|
|
186
|
+
|
|
187
|
+
## Upgrading to 0.0.50
|
|
188
|
+
|
|
189
|
+
0.0.50 has no schema change. Live pages on Next.js are now served from Next's route cache: `next build` still needs no keys, each address renders on its first visit and stays cached until a publish expires it. Three edits in files the installer wrote for you:
|
|
190
|
+
|
|
191
|
+
- The two route files become one. Delete `app/(site)/page.tsx` and `app/(site)/[...path]/page.tsx` (under `app/[locale]` on a multilingual site) and create `app/(site)/[[...path]]/page.tsx` from [Next.js](../frameworks/nextjs.md#the-route-file). The `generateStaticParams` export is what turns the cache on.
|
|
192
|
+
- In `smoodly/server.ts`, replace every `await connection()` with `await buildGate()`, imported from `smoodly/next`, and drop the `next/server` import. The gate still keeps `next build` off the database; at run time it no longer forces a render per request.
|
|
193
|
+
- A page, a section or a layout under the CMS route that reads cookies, headers or search params must move to a route file of its own, or it answers a 500 in production.
|
|
194
|
+
|
|
195
|
+
Do the first two together: with the new route file, a `connection()` left anywhere in `smoodly/server.ts` answers 500 on every public page in production, and `next dev` will not show it.
|
|
196
|
+
|
|
197
|
+
A renamed page's old address still answers a permanent redirect, now without the request's query string: the cached answer cannot read it.
|
|
198
|
+
|
|
199
|
+
## Upgrading to 0.0.52
|
|
200
|
+
|
|
201
|
+
There is no upgrade to 0.0.52 from an installed 0.0.51 site: up to 0.0.51 a site ran its own Postgres and Supabase, and nothing imports that database into a space. Make the site again with `npx create-smoodly-app@latest` into a new folder, on a project made in the [dashboard](https://app.smoodly.io), move your components, sections and config across, and enter or seed the content in the new space. The sections below say what changed in a site's code between the two versions, for that move.
|
|
202
|
+
|
|
203
|
+
0.0.52 moves a site's content into Smoodly's service, a space per site, and every build pushes the site's content model to its space. The admin's operations move to Smoodly's API, a service of its own, and the admin route on your site keeps the page and its files and gains two routes the API uses: one that expires the tags a publish names, signed with the API's own key, and one that turns on draft mode for the editor's browser. The operations endpoint under `/admin/_smoodly/op` is gone.
|
|
204
|
+
|
|
205
|
+
- Your env names the space by its id, `sp_…`, and its two keys, `sk_…` and `pk_…`, from the project at smoodly.io ([Keys](../getting-started/keys.md)). `SMOODLY_API_URL`, the address of Smoodly's API, is `https://api.smoodly.io` unless you set it.
|
|
206
|
+
- On Next.js, add `"prebuild": "smoodly push"` to `package.json`'s scripts: each build gives the space the content model and the site's address (`SITE_URL`). An Astro build pushes by itself.
|
|
207
|
+
- In `smoodly/server.ts`, `adminDeps()` no longer hands over the stores and the sign-in check; it returns the API's address, the space (the API keeps a space's admin routes under it) and the delivery mode. The API signs its calls to your site with its own key, which the admin route fetches from the API and checks:
|
|
208
|
+
|
|
209
|
+
File: `smoodly/server.ts`
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
export function adminDeps() {
|
|
213
|
+
const env = smoodlyEnv("admin"); // the admin talks to SMOODLY_API_URL, which also tells it where editors sign in
|
|
214
|
+
return { apiUrl: env.apiUrl, spaceId: env.spaceId, delivery: "live" as const };
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Drop `supabaseAdminAuth` and `AdminAuth` from the `smoodly/admin` import, and the `auth` the old `bound()` built (`supabaseAdminAuth`, `AdminAuth`, `AuthConfig`, `gateAdminOp`, `createAdminOps`, `runAdminOp`, `ensureFixedNodes`, `ensureGlobalItems` and `localContentTransport` are gone from it; `SignInConfig` names what `GET /v1/auth` answers).
|
|
219
|
+
|
|
220
|
+
The admin asks the API where editors sign in (`GET /v1/auth`), so the site no longer holds the Auth project's values: delete `publicAuth()` from `smoodly/server.ts`, and `signIn: publicAuth()` from the route file:
|
|
221
|
+
|
|
222
|
+
File: `app/(smoodly)/admin/[[...segments]]/route.ts`
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
export const { GET, POST } = createAdminRoute(() => ({ config, ...adminDeps(), presence }));
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
`SMOODLY_PUBLISHABLE_KEY`, when set, is now the space's publishable key (`pk_…`).
|
|
229
|
+
|
|
230
|
+
Media files move into Smoodly's service as well: a file of up to 100 MB (25 MB unless `media.maxSize` says more; an image 20 MB at most) uploads from the admin, with its progress shown, or through `content().media`. An export holding files over 4 MB now imports. `withDownload` is gone from the `smoodly` import: an SVG is served as an attachment by the API itself.
|
|
231
|
+
|
|
232
|
+
Images are served from Smoodly's media host, `media.smoodly.io`, cut to the framed area at the width the layout needs, in AVIF or WebP, with no image optimizer on your side ([Images and crops](../media/images-and-crops.md)):
|
|
233
|
+
|
|
234
|
+
- Delete `SMOODLY_URL` from your env files and your host's settings: a site names no media host.
|
|
235
|
+
- On Next.js, delete `images: smoodlyImages()` and its import from `next.config.ts`: `smoodly/image/config`, `smoodlyImages`, `isPrivateHost`, `nextLoader`, `imageUrl` and `ImageLoader` are gone. `SmoodlyImage` no longer uses `next/image`: drop its `loader` and `unoptimized` props.
|
|
236
|
+
- On Astro, the integration no longer sets `image.remotePatterns`, and `<Image>` no longer goes through `/_image`; it takes no `unoptimized`.
|
|
237
|
+
- `f.image({ crops: { desktop: "16:9", mobile: "4:5" } })` names crops for art direction, and the new `media` prop on `Image` and `SmoodlyImage` says where each applies: `media={{ mobile: "(max-width: 767px)" }}`.
|
|
238
|
+
- An image's quality and its widest width can be set for the site (`media: { quality, maxWidth }` in `defineConfig`), a field (`f.image({ quality, maxWidth })`) or a placement (the `quality` and `maxWidth` props); nothing to change if you set none ([Quality and width](../media/images-and-crops.md#quality-and-width)).
|
|
239
|
+
|
|
240
|
+
Editors sign in at smoodly.io: `/admin` has no sign-in form of its own. It sends the editor to smoodly.io and back, and holds a session for this site's space alone, which Sign out ends without signing them out of smoodly.io. Nothing to set on your site, and the admin no longer depends on Supabase: drop `@supabase/supabase-js` from your `package.json` unless your own code uses it.
|
|
241
|
+
|
|
242
|
+
Your site's reads move to the API too: the site opens no database.
|
|
243
|
+
|
|
244
|
+
- The live site and the admin need `SMOODLY_SPACE_ID` and `SMOODLY_SECRET_KEY`.
|
|
245
|
+
- In `smoodly/server.ts`, `bound()` builds the reads from the API instead of the stores, and `content()` posts to the API:
|
|
246
|
+
|
|
247
|
+
File: `smoodly/server.ts`
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
const site = createSmoodlyApi({ ...apiEnv(), config });
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
File: `smoodly/server.ts`
|
|
254
|
+
|
|
255
|
+
```ts
|
|
256
|
+
return createSmoodlyContent({ config, href, transport: apiTransport(apiEnv()) });
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Drop `createSmoodlyClient`, `createSupabaseStores`, `createSmoodlySite` and `siteOptions` from the `smoodly` import, and the `client()` export with them.
|
|
260
|
+
|
|
261
|
+
Editing presence moves to the API as well: the admin opens one connection per tab to Smoodly's API, and your Supabase project's Realtime is no longer used. `presenceConfig(env)` answers at once with the API's address and the space, so `presence()` in `smoodly/server.ts` is typed `PresenceConfig`, not a promise:
|
|
262
|
+
|
|
263
|
+
File: `smoodly/server.ts`
|
|
264
|
+
|
|
265
|
+
```ts
|
|
266
|
+
export function presence(): PresenceConfig {
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
A seed now writes through the API, so the API must answer while it runs. On Astro there is nothing to change: the integration reads over the API by itself.
|
|
270
|
+
|
|
271
|
+
A publish now answers at once and reaches the site a moment later: the API builds the pages it changed and every page that depends on them, clears its edge copies, then calls your site's revalidate route. The admin shows *Publishing…* in its rail until that lands. A script that publishes through `content()` gets the same answer; `GET /v1/spaces/{space}/status` with the secret key says how many deliveries are still pending.
|
|
272
|
+
|
|
273
|
+
## Upgrading to 0.0.53
|
|
274
|
+
|
|
275
|
+
Nothing in your code changes: `npm install smoodly@0.0.53` (and `create-smoodly-app@0.0.53` for new sites) and deploy. 0.0.53 is the clean after the hosted service: every file says today's shape, and a few things a site never reached since 0.0.52 are gone from the package's public surface, since members are managed at smoodly.io: `memberErrors`, `InviteInput` and `InviteResult` from `smoodly`, `MembersListResult.consoleUrl` and the `invite`, `setRole` and `remove` members operations from `smoodly/admin`, and the `MemberStore` write methods. The admin reads the dashboard's address from the service.
|
|
276
|
+
|
|
277
|
+
For a new site: the installer's seed succeeds on its first run against a fresh space (its reads are draft reads, never an edge copy), and every template's `.gitignore` lists `.vercel/`, so a local build with the Vercel adapter is never committed as prebuilt output. An existing site adds `.vercel/` to its `.gitignore` by hand.
|
|
278
|
+
|
|
279
|
+
## Upgrading to 0.0.54
|
|
280
|
+
|
|
281
|
+
Nothing in your code changes. The editor gains the structure view (the switch at the top right turns the canvas into a card per section, dragged to reorder), undo and redo (Cmd+Z, Shift+Cmd+Z, the two arrows at the top right) and copying a section to another page (a card's ⋯ menu in the structure view). Update `smoodly`, build and deploy.
|
|
282
|
+
|
|
283
|
+
## Upgrading to 0.0.55
|
|
284
|
+
|
|
285
|
+
Nothing in your code changes. In the editor, the structure view shows one *Add section* per zone, at its end, and the Page Outline's rows carry the same ⋯ menu as the structure cards (Copy, Paste before, Paste after, Remove) in place of the ×. Update `smoodly`, build and deploy.
|
|
286
|
+
|
|
287
|
+
## Upgrading to 0.0.56
|
|
288
|
+
|
|
289
|
+
Nothing in your code changes, and one thing in your environment: the package, the installer and every new site now name Node 22.12 or newer (Astro 7's floor). What a site meets after the update:
|
|
290
|
+
|
|
291
|
+
- Publish checks references on entries and globals too: an entry or a global cannot go live in a language while one of its reference fields points at an entry that is unpublished there, and a page whose child is still published in that language cannot be unpublished. The message names what to publish or unpublish first.
|
|
292
|
+
- On the live site a list ordered by `updatedAt` follows the publish time, and an entry's `updatedAt` is its last publish; in draft mode both follow the last save. Editing an old post no longer moves it to the top of a public list until it is published again.
|
|
293
|
+
- A link field takes only what the site renders (`https://`, `http://`, `mailto:`, `tel:`, a path, `#` or `?`), marked as the editor types and refused at publish. The custom CSS box refuses `image-set()`, `image()` and `src()` beside `url()`.
|
|
294
|
+
- A new section's required select or radio stores its first option, as the form shows it.
|
|
295
|
+
- On Astro, the editor's preview cookie ends twelve hours after it was set; opening the admin sets a new one.
|
|
296
|
+
- In Astro, an element view inside richtext gets `styles` as it does in React, and a view's `aspect` narrower than the image's cut scales `sizes` by the frame, so the browser picks a candidate for what it shows.
|
|
297
|
+
- The installer takes every prompt's default when it runs without a terminal, expands a leading `~/`, takes a folder holding only `.git`, and makes the initial commit before it pushes the schema and seeds the content.
|
|
298
|
+
|
|
299
|
+
Update `smoodly`, build and deploy.
|
|
300
|
+
|
|
301
|
+
## Upgrading to 0.0.59
|
|
302
|
+
|
|
303
|
+
Nothing in your code changes, and every order stays as it is. `locales` in the config takes a new optional `order`: `"shared"` (the default) keeps one order of pages and of manually ordered entries for every language, `"perLocale"` gives each language its own; see [Locales and routing](../languages/locales.md#one-order-or-one-per-language). A collection takes `admin: { showInNav: true }` to sit in the admin's main navigation instead of the *Collections* menu; see [Defining a collection](../collections/defining.md#entries-in-the-admin). A collection's list in the admin shows 20 entries a page (100 or 500 on the editor's choice) and filters by title, and `getEntries` / `getLiveCollection` take `offset` beside `limit`; see [Queries](../collections/queries.md#paging-a-list). In the admin, a page's ⋯ menu has *Duplicate…*, and fields have a visible edge in the dark theme. An export made before this version does not import into a space on it: export again after upgrading.
|
|
304
|
+
|
|
305
|
+
## Upgrading to 0.0.61
|
|
306
|
+
|
|
307
|
+
Nothing in your code changes. Two things are new:
|
|
308
|
+
|
|
309
|
+
- A site can read a **preview space**, a copy of production a project adds once it is live ([Deploying](../getting-started/deploying.md#a-preview-space)). Its id and keys carry `preview` (`sp_preview_…`), which older versions refuse as not a Smoodly key: update before you point a site at one.
|
|
310
|
+
- The push names the space it reached. The build log's line is now `Pushed schema version 4 to the production space sp_…` (it was `Pushed schema version 4 to sp_…`), and the dev server prints the same once. Change any script that reads that line.
|
|
311
|
+
|
|
312
|
+
Update `smoodly`, build and deploy.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "smoodly",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.61",
|
|
4
4
|
"description": "Open-source, code-first CMS for Astro and Next.js: define a component once, it becomes a typed, editable building block.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -62,11 +62,12 @@
|
|
|
62
62
|
},
|
|
63
63
|
"files": [
|
|
64
64
|
"dist",
|
|
65
|
-
"bin"
|
|
65
|
+
"bin",
|
|
66
|
+
"docs"
|
|
66
67
|
],
|
|
67
68
|
"scripts": {
|
|
68
69
|
"build:admin": "tsx scripts/build-admin.ts",
|
|
69
|
-
"build": "node scripts/write-version.mjs && rm -rf dist && tsc -p tsconfig.build.json && node scripts/copy-astro.mjs && npm run build:admin",
|
|
70
|
+
"build": "node scripts/write-version.mjs && rm -rf dist && tsc -p tsconfig.build.json && node scripts/copy-astro.mjs && npm run build:admin && node scripts/build-docs.mjs",
|
|
70
71
|
"prepublishOnly": "npm run build",
|
|
71
72
|
"pretest": "node scripts/write-version.mjs && npm run -s build:admin",
|
|
72
73
|
"test": "vitest run",
|