create-smoodly-app 0.0.13 → 0.0.15
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 +38 -10
- package/dist/index.js +39 -15
- package/package.json +3 -2
- package/templates/blank/AGENTS.md +50 -0
- package/templates/blank/CLAUDE.md +1 -0
- package/templates/blank/README.md +75 -0
- package/templates/{next/app → blank/app/(site)}/[...path]/page.tsx +2 -2
- package/templates/blank/app/(site)/layout.tsx +25 -0
- package/templates/blank/app/globals.css +47 -0
- package/templates/blank/components/elements/Button.tsx +26 -0
- package/templates/blank/components/pages/Home.tsx +22 -0
- package/templates/blank/components/pages/Page.tsx +25 -0
- package/templates/blank/components/pages/Post.tsx +21 -0
- package/templates/blank/components/sections/Text.tsx +39 -0
- package/templates/{next → blank}/package.json +1 -1
- package/templates/blank/scripts/seed.ts +72 -0
- package/templates/blank/smoodly/collections.ts +26 -0
- package/templates/blank/smoodly/config.ts +35 -0
- package/templates/blank/smoodly/elements.ts +5 -0
- package/templates/blank/smoodly/sections.ts +5 -0
- package/templates/{next → blank}/smoodly/server.ts +17 -13
- package/templates/blank/smoodly/shared.ts +16 -0
- package/templates/blank/smoodly/toolsets.ts +14 -0
- package/templates/blank/supabase/migrations/00000000000000_smoodly.sql +518 -0
- package/templates/blank-intl/AGENTS.md +50 -0
- package/templates/blank-intl/CLAUDE.md +1 -0
- package/templates/blank-intl/README.md +76 -0
- package/templates/blank-intl/app/[locale]/layout.tsx +42 -0
- package/templates/blank-intl/app/globals.css +47 -0
- package/templates/blank-intl/components/elements/Button.tsx +26 -0
- package/templates/blank-intl/components/pages/Home.tsx +22 -0
- package/templates/blank-intl/components/pages/Page.tsx +25 -0
- package/templates/blank-intl/components/pages/Post.tsx +21 -0
- package/templates/blank-intl/components/sections/Text.tsx +39 -0
- package/templates/blank-intl/messages/en.json +1 -0
- package/templates/{next-intl → blank-intl}/package.json +1 -1
- package/templates/blank-intl/scripts/seed.ts +72 -0
- package/templates/blank-intl/smoodly/collections.ts +26 -0
- package/templates/blank-intl/smoodly/config.ts +38 -0
- package/templates/blank-intl/smoodly/elements.ts +5 -0
- package/templates/blank-intl/smoodly/sections.ts +5 -0
- package/templates/{next-intl → blank-intl}/smoodly/server.ts +17 -13
- package/templates/blank-intl/smoodly/shared.ts +16 -0
- package/templates/blank-intl/smoodly/toolsets.ts +14 -0
- package/templates/blank-intl/supabase/migrations/00000000000000_smoodly.sql +518 -0
- package/templates/blank-intl.tsconfig.json +28 -0
- package/templates/blank.tsconfig.json +28 -0
- package/templates/lorem/AGENTS.md +50 -0
- package/templates/lorem/CLAUDE.md +1 -0
- package/templates/{next → lorem}/README.md +5 -4
- package/templates/lorem/_gitignore +5 -0
- package/templates/lorem/app/(site)/[...path]/page.tsx +15 -0
- package/templates/{next/app → lorem/app/(site)}/layout.tsx +11 -11
- package/templates/lorem/app/(site)/page.tsx +11 -0
- package/templates/lorem/app/(smoodly)/admin/[[...segments]]/page.tsx +1 -0
- package/templates/lorem/app/(smoodly)/admin/layout.tsx +1 -0
- package/templates/{next → lorem}/app/globals.css +4 -0
- package/templates/{next-intl → lorem}/components/elements/Callout.tsx +1 -1
- package/templates/{next → lorem}/components/elements/Cta.tsx +1 -1
- package/templates/{next → lorem}/components/pages/Article.tsx +3 -2
- package/templates/{next → lorem}/components/pages/Articles.tsx +7 -7
- package/templates/{next-intl → lorem}/components/pages/Page.tsx +11 -1
- package/templates/{next → lorem}/components/sections/ImageText.tsx +1 -1
- package/templates/{next → lorem}/components/sections/Points.tsx +1 -1
- package/templates/lorem/next.config.ts +8 -0
- package/templates/lorem/package.json +27 -0
- package/templates/{next-intl → lorem}/scripts/seed.ts +30 -5
- package/templates/lorem/smoodly/admin.tsx +6 -0
- package/templates/lorem/smoodly/ops.ts +11 -0
- package/templates/lorem/smoodly/richtext.tsx +7 -0
- package/templates/lorem/smoodly/server.ts +96 -0
- package/templates/lorem/tsconfig.json +41 -0
- package/templates/lorem-intl/AGENTS.md +50 -0
- package/templates/lorem-intl/CLAUDE.md +1 -0
- package/templates/{next-intl → lorem-intl}/README.md +2 -1
- package/templates/lorem-intl/_gitignore +5 -0
- package/templates/lorem-intl/app/(smoodly)/admin/[[...segments]]/page.tsx +1 -0
- package/templates/lorem-intl/app/(smoodly)/admin/layout.tsx +15 -0
- package/templates/lorem-intl/app/[locale]/[...path]/page.tsx +18 -0
- package/templates/{next-intl → lorem-intl}/app/[locale]/layout.tsx +5 -6
- package/templates/lorem-intl/app/[locale]/page.tsx +15 -0
- package/templates/{next-intl → lorem-intl}/app/globals.css +4 -0
- package/templates/{next → lorem-intl}/components/elements/Callout.tsx +1 -1
- package/templates/{next-intl → lorem-intl}/components/elements/Cta.tsx +1 -1
- package/templates/{next-intl → lorem-intl}/components/pages/Article.tsx +3 -2
- package/templates/{next-intl → lorem-intl}/components/pages/Articles.tsx +7 -7
- package/templates/{next → lorem-intl}/components/pages/Page.tsx +11 -1
- package/templates/{next-intl → lorem-intl}/components/sections/ImageText.tsx +1 -1
- package/templates/{next-intl → lorem-intl}/components/sections/Points.tsx +1 -1
- package/templates/lorem-intl/i18n/navigation.ts +6 -0
- package/templates/lorem-intl/i18n/request.ts +24 -0
- package/templates/lorem-intl/i18n/routing.ts +17 -0
- package/templates/lorem-intl/next.config.ts +11 -0
- package/templates/lorem-intl/package.json +28 -0
- package/templates/lorem-intl/proxy.ts +11 -0
- package/templates/{next → lorem-intl}/scripts/seed.ts +30 -5
- package/templates/lorem-intl/smoodly/admin.tsx +6 -0
- package/templates/lorem-intl/smoodly/ops.ts +11 -0
- package/templates/lorem-intl/smoodly/richtext.tsx +7 -0
- package/templates/lorem-intl/smoodly/server.ts +97 -0
- package/templates/lorem-intl/tsconfig.json +41 -0
- package/templates/lorem-intl.tsconfig.json +28 -0
- package/templates/lorem.tsconfig.json +28 -0
- /package/templates/{next → blank}/_gitignore +0 -0
- /package/templates/{next/app → blank/app/(site)}/page.tsx +0 -0
- /package/templates/{next → blank}/app/(smoodly)/admin/[[...segments]]/page.tsx +0 -0
- /package/templates/{next → blank}/app/(smoodly)/admin/layout.tsx +0 -0
- /package/templates/{next → blank}/next.config.ts +0 -0
- /package/templates/{next → blank}/smoodly/admin.tsx +0 -0
- /package/templates/{next → blank}/smoodly/ops.ts +0 -0
- /package/templates/{next → blank}/smoodly/richtext.tsx +0 -0
- /package/templates/{next → blank}/tsconfig.json +0 -0
- /package/templates/{next-intl → blank-intl}/_gitignore +0 -0
- /package/templates/{next-intl → blank-intl}/app/(smoodly)/admin/[[...segments]]/page.tsx +0 -0
- /package/templates/{next-intl → blank-intl}/app/(smoodly)/admin/layout.tsx +0 -0
- /package/templates/{next-intl → blank-intl}/app/[locale]/[...path]/page.tsx +0 -0
- /package/templates/{next-intl → blank-intl}/app/[locale]/page.tsx +0 -0
- /package/templates/{next-intl → blank-intl}/i18n/navigation.ts +0 -0
- /package/templates/{next-intl → blank-intl}/i18n/request.ts +0 -0
- /package/templates/{next-intl → blank-intl}/i18n/routing.ts +0 -0
- /package/templates/{next-intl → blank-intl}/next.config.ts +0 -0
- /package/templates/{next-intl → blank-intl}/proxy.ts +0 -0
- /package/templates/{next-intl → blank-intl}/smoodly/admin.tsx +0 -0
- /package/templates/{next-intl → blank-intl}/smoodly/ops.ts +0 -0
- /package/templates/{next-intl → blank-intl}/smoodly/richtext.tsx +0 -0
- /package/templates/{next-intl → blank-intl}/tsconfig.json +0 -0
- /package/templates/{next → lorem}/components/ArticleCard.tsx +0 -0
- /package/templates/{next → lorem}/components/articles.ts +0 -0
- /package/templates/{next → lorem}/components/pages/Home.tsx +0 -0
- /package/templates/{next → lorem}/components/sections/FavouriteArticles.tsx +0 -0
- /package/templates/{next → lorem}/components/sections/Footer.tsx +0 -0
- /package/templates/{next → lorem}/components/sections/Header.tsx +0 -0
- /package/templates/{next → lorem}/components/sections/Hero.tsx +0 -0
- /package/templates/{next → lorem}/components/sections/PageHero.tsx +0 -0
- /package/templates/{next → lorem}/components/sections/People.tsx +0 -0
- /package/templates/{next → lorem}/components/sections/Quote.tsx +0 -0
- /package/templates/{next → lorem}/components/strings.ts +0 -0
- /package/templates/{next → lorem}/messages/en.json +0 -0
- /package/templates/{next → lorem}/public/images/about_main.jpg +0 -0
- /package/templates/{next → lorem}/public/images/article_photo.jpg +0 -0
- /package/templates/{next → lorem}/public/images/hero_image.jpg +0 -0
- /package/templates/{next → lorem}/public/images/home_section_2.jpg +0 -0
- /package/templates/{next → lorem}/smoodly/collections.ts +0 -0
- /package/templates/{next → lorem}/smoodly/config.ts +0 -0
- /package/templates/{next → lorem}/smoodly/elements.ts +0 -0
- /package/templates/{next → lorem}/smoodly/sections.ts +0 -0
- /package/templates/{next → lorem}/smoodly/shared.ts +0 -0
- /package/templates/{next → lorem}/smoodly/toolsets.ts +0 -0
- /package/templates/{next → lorem}/supabase/migrations/00000000000000_smoodly.sql +0 -0
- /package/templates/{next-intl → lorem-intl}/components/ArticleCard.tsx +0 -0
- /package/templates/{next-intl → lorem-intl}/components/articles.ts +0 -0
- /package/templates/{next-intl → lorem-intl}/components/pages/Home.tsx +0 -0
- /package/templates/{next-intl → lorem-intl}/components/sections/FavouriteArticles.tsx +0 -0
- /package/templates/{next-intl → lorem-intl}/components/sections/Footer.tsx +0 -0
- /package/templates/{next-intl → lorem-intl}/components/sections/Header.tsx +0 -0
- /package/templates/{next-intl → lorem-intl}/components/sections/Hero.tsx +0 -0
- /package/templates/{next-intl → lorem-intl}/components/sections/PageHero.tsx +0 -0
- /package/templates/{next-intl → lorem-intl}/components/sections/People.tsx +0 -0
- /package/templates/{next-intl → lorem-intl}/components/sections/Quote.tsx +0 -0
- /package/templates/{next-intl → lorem-intl}/components/strings.ts +0 -0
- /package/templates/{next-intl → lorem-intl}/messages/en.json +0 -0
- /package/templates/{next-intl → lorem-intl}/messages/fi.json +0 -0
- /package/templates/{next-intl → lorem-intl}/public/images/about_main.jpg +0 -0
- /package/templates/{next-intl → lorem-intl}/public/images/article_photo.jpg +0 -0
- /package/templates/{next-intl → lorem-intl}/public/images/hero_image.jpg +0 -0
- /package/templates/{next-intl → lorem-intl}/public/images/home_section_2.jpg +0 -0
- /package/templates/{next-intl → lorem-intl}/smoodly/collections.ts +0 -0
- /package/templates/{next-intl → lorem-intl}/smoodly/config.ts +0 -0
- /package/templates/{next-intl → lorem-intl}/smoodly/elements.ts +0 -0
- /package/templates/{next-intl → lorem-intl}/smoodly/sections.ts +0 -0
- /package/templates/{next-intl → lorem-intl}/smoodly/shared.ts +0 -0
- /package/templates/{next-intl → lorem-intl}/smoodly/toolsets.ts +0 -0
- /package/templates/{next-intl → lorem-intl}/supabase/migrations/00000000000000_smoodly.sql +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// The starter's content, written through the stores (never raw inserts:
|
|
2
|
+
// the refs index and publish integrity are part of the point). Ships in
|
|
3
|
+
// the scaffold; create-smoodly-app runs `npm run seed` after the first
|
|
4
|
+
// editor. Idempotent: exits once the home page exists in the default
|
|
5
|
+
// locale. Writes the same copy into every configured locale, whatever
|
|
6
|
+
// their codes, so every locale's "/" resolves.
|
|
7
|
+
// Run: npm run seed (needs .env.local and a Supabase stack).
|
|
8
|
+
import next from "@next/env";
|
|
9
|
+
import type { PageTree } from "smoodly";
|
|
10
|
+
const { loadEnvConfig } = next;
|
|
11
|
+
|
|
12
|
+
loadEnvConfig(process.cwd());
|
|
13
|
+
|
|
14
|
+
const { config } = await import("../smoodly/config");
|
|
15
|
+
const { stores } = await import("../smoodly/server");
|
|
16
|
+
const { pages, entries } = stores();
|
|
17
|
+
|
|
18
|
+
const DEFAULT = config.locales.default;
|
|
19
|
+
const OTHERS = config.locales.supported.filter((l) => l !== DEFAULT);
|
|
20
|
+
|
|
21
|
+
if (await pages.resolvePath(DEFAULT, "/")) {
|
|
22
|
+
console.log(`Already seeded — "home" exists in "${DEFAULT}".`);
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Richtext is TipTap JSON, the stored format; RichText renders it.
|
|
27
|
+
type Node = Record<string, unknown>;
|
|
28
|
+
const p = (s: string): Node => ({ type: "paragraph", content: [{ type: "text", text: s }] });
|
|
29
|
+
const button = (label: string, href: string): Node => ({ type: "element", attrs: { name: "button", fields: { label, href }, styles: {} } });
|
|
30
|
+
const doc = (...content: Node[]) => ({ type: "doc", content });
|
|
31
|
+
|
|
32
|
+
// --- the site item: name and tagline, published in every locale ------
|
|
33
|
+
|
|
34
|
+
const site = await entries.create("site", { name: "My site", tagline: "Built with Smoodly" }, { locale: DEFAULT });
|
|
35
|
+
await entries.setStatus("site", site.id, DEFAULT, "published");
|
|
36
|
+
for (const locale of OTHERS) {
|
|
37
|
+
await entries.addLocale("site", site.id, locale, { from: DEFAULT });
|
|
38
|
+
await entries.setStatus("site", site.id, locale, "published");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// --- the home page: one Text section ---------------------------------
|
|
42
|
+
|
|
43
|
+
const tree = {
|
|
44
|
+
meta: { description: "A new site, built with Smoodly." },
|
|
45
|
+
zones: {
|
|
46
|
+
body: [
|
|
47
|
+
{
|
|
48
|
+
id: "node-hello",
|
|
49
|
+
type: "text",
|
|
50
|
+
fields: {
|
|
51
|
+
title: "Hello",
|
|
52
|
+
body: doc(
|
|
53
|
+
p("This is your home page. Open the admin to edit this text, add sections, create pages and write posts."),
|
|
54
|
+
p("Everything you see is defined in components/ and registered in smoodly/. The README says where things are."),
|
|
55
|
+
button("Open the admin", "/admin"),
|
|
56
|
+
),
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
} as unknown as PageTree;
|
|
62
|
+
|
|
63
|
+
const home = await pages.createPage({ locale: DEFAULT, slug: "home", title: "Home", template: "home" });
|
|
64
|
+
await pages.saveDraft(home.id, DEFAULT, tree);
|
|
65
|
+
await pages.publish(home.id, DEFAULT);
|
|
66
|
+
for (const locale of OTHERS) {
|
|
67
|
+
await pages.addLocale(home.id, locale, { from: DEFAULT, title: "Home" });
|
|
68
|
+
await pages.saveDraft(home.id, locale, tree);
|
|
69
|
+
await pages.publish(home.id, locale);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
console.log(`Seeded the blank starter in "${[DEFAULT, ...OTHERS].join('", "')}": the home page and the site item, published.`);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { f, smoodly } from "smoodly";
|
|
2
|
+
import { text } from "./toolsets";
|
|
3
|
+
|
|
4
|
+
// A collection: structured content with its own admin list, served at
|
|
5
|
+
// `path` by its entry page (components/pages/Post.tsx). Fields marked
|
|
6
|
+
// .localized() are stored per locale; the rest are shared across
|
|
7
|
+
// locales. `versions: true` keeps a history per locale. To add a
|
|
8
|
+
// collection: copy this block, add it to `collections`, write its view
|
|
9
|
+
// into a new migration with `collectionSQL` from "smoodly", and apply
|
|
10
|
+
// it (supabase db push, or supabase db reset locally).
|
|
11
|
+
export const posts = smoodly.collection({
|
|
12
|
+
name: "posts",
|
|
13
|
+
title: "Posts",
|
|
14
|
+
titleField: "title",
|
|
15
|
+
path: "posts",
|
|
16
|
+
order: { by: "date", direction: "desc" },
|
|
17
|
+
versions: true,
|
|
18
|
+
fields: {
|
|
19
|
+
title: f.text().localized(),
|
|
20
|
+
slug: f.slug({ from: "title" }),
|
|
21
|
+
date: f.date(),
|
|
22
|
+
body: f.richtext({ toolset: text }).localized(),
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const collections = [posts];
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { defineConfig, f } from "smoodly";
|
|
2
|
+
import { collections } from "./collections";
|
|
3
|
+
import { sections } from "./sections";
|
|
4
|
+
import { shared } from "./shared";
|
|
5
|
+
import { elements } from "./elements";
|
|
6
|
+
import { HomePage } from "@/components/pages/Home";
|
|
7
|
+
import { StandardPage } from "@/components/pages/Page";
|
|
8
|
+
import { PostPage } from "@/components/pages/Post";
|
|
9
|
+
|
|
10
|
+
export { collections, sections, shared, elements };
|
|
11
|
+
|
|
12
|
+
// The registry and the plain settings, one file. Runtime-free: nothing
|
|
13
|
+
// here imports a route file or Next, so a script and the CLI's template
|
|
14
|
+
// build can load it outside the app.
|
|
15
|
+
export const config = defineConfig({
|
|
16
|
+
registry: {
|
|
17
|
+
sections,
|
|
18
|
+
elements,
|
|
19
|
+
collections,
|
|
20
|
+
shared,
|
|
21
|
+
pages: [HomePage, StandardPage, PostPage],
|
|
22
|
+
},
|
|
23
|
+
locales: { default: "en", supported: ["en"] },
|
|
24
|
+
// The record the site root serves.
|
|
25
|
+
homePageSlug: "home",
|
|
26
|
+
// Editors can nest pages three deep.
|
|
27
|
+
pages: { tree: { depth: 3 } },
|
|
28
|
+
// Every section gets this select beside its own styles; the section
|
|
29
|
+
// wrapper emits it as data-tone, and app/globals.css styles it.
|
|
30
|
+
styles: {
|
|
31
|
+
sections: {
|
|
32
|
+
tone: f.select(["paper", "ink"]).default("paper"),
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
});
|
|
@@ -4,21 +4,22 @@
|
|
|
4
4
|
// secret is a service-role key or a cloud write key is invisible here.
|
|
5
5
|
//
|
|
6
6
|
// Lazy on purpose, the site and renderer included: config.ts imports the
|
|
7
|
-
// page shapes, and a page shape may import this file to
|
|
8
|
-
//
|
|
7
|
+
// page shapes, and a page shape may import this file to read through
|
|
8
|
+
// `q` (components/pages/Articles.tsx). That is a cycle, and the
|
|
9
9
|
// admin route enters it from config.ts — so nothing here may read the
|
|
10
10
|
// config at module scope.
|
|
11
11
|
import {
|
|
12
12
|
createSmoodlyClient, createSmoodlySite, smoodlyEnv, SupabaseAssetStore, SupabaseEntryStore, SupabasePageStore, SupabasePathIndex, type SmoodlySite,
|
|
13
13
|
} from "smoodly";
|
|
14
14
|
import { supabaseAdminAuth, type AdminAuth, type AuthConfig } from "smoodly/admin/next";
|
|
15
|
-
import { createPageRenderer, type PageRegistration } from "smoodly/next";
|
|
15
|
+
import { createPageRenderer, createSmoodlyQueries, type PageRegistration } from "smoodly/next";
|
|
16
16
|
import type { SupabaseClient } from "@supabase/supabase-js";
|
|
17
17
|
import { collections, config, elements, sections, shared } from "./config";
|
|
18
18
|
|
|
19
19
|
type Renderer = ReturnType<typeof createPageRenderer>;
|
|
20
|
+
type Queries = ReturnType<typeof createSmoodlyQueries<typeof collections, typeof shared>>;
|
|
20
21
|
type Bound = {
|
|
21
|
-
db: SupabaseClient; pages: SupabasePageStore; entries: SupabaseEntryStore; assets: SupabaseAssetStore; auth: AdminAuth; site: SmoodlySite; renderer: Renderer;
|
|
22
|
+
db: SupabaseClient; pages: SupabasePageStore; entries: SupabaseEntryStore; assets: SupabaseAssetStore; auth: AdminAuth; site: SmoodlySite; renderer: Renderer; q: Queries;
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
let cached: Bound | null = null;
|
|
@@ -43,17 +44,18 @@ function bound(): Bound {
|
|
|
43
44
|
// takes this local closure, not the export, so it never re-enters `bound()`.
|
|
44
45
|
const stores = () => ({ pages, entries, assets });
|
|
45
46
|
// The site layer: (locale, path) → page or entry, and the content API
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
const site = createSmoodlySite({ stores, collections, shared, sections, elements, locales, homePageSlug: config.homePageSlug });
|
|
47
|
+
// `q` wraps below. Not exported — the app reads through `q`, which adds
|
|
48
|
+
// draft awareness and the cache.
|
|
49
|
+
const site = createSmoodlySite({ stores, collections, shared, sections, elements, locales, homePageSlug: config.homePageSlug, pages: config.registry.pages ?? [] });
|
|
50
50
|
const renderer = createPageRenderer({
|
|
51
51
|
site,
|
|
52
52
|
sections,
|
|
53
53
|
pages: (config.registry.pages ?? []) as PageRegistration[],
|
|
54
54
|
href,
|
|
55
55
|
});
|
|
56
|
-
|
|
56
|
+
// The read API (spec 2026-09-11): typed by the registry, draft-aware, cached under tags the admin expires.
|
|
57
|
+
const q = createSmoodlyQueries({ site, collections, shared });
|
|
58
|
+
cached = { db, pages, entries, assets, auth, site, renderer, q };
|
|
57
59
|
return cached;
|
|
58
60
|
}
|
|
59
61
|
|
|
@@ -80,13 +82,15 @@ export function publicAuth(): AuthConfig {
|
|
|
80
82
|
* becomes a locale-prefixing lookup. */
|
|
81
83
|
export const href = (path: string, _locale: string) => path;
|
|
82
84
|
|
|
83
|
-
/** The
|
|
84
|
-
*
|
|
85
|
-
|
|
85
|
+
/** The read API (spec 2026-09-11) for layouts and page views that fetch:
|
|
86
|
+
* `q().getEntries("articles", { locale, limit: 3 })`, `q().getShared("header",
|
|
87
|
+
* { locale })`, `q().getPageTree({ locale })`. Typed by the registry, the
|
|
88
|
+
* live draft in the editor preview, cached under tags the admin expires.
|
|
89
|
+
* Rename it if `q` is not to your taste — this file is yours. */
|
|
90
|
+
export const q = (): Queries => bound().q;
|
|
86
91
|
|
|
87
92
|
/** The two route files call these. */
|
|
88
93
|
export const renderSmoodlyPath: Renderer["renderSmoodlyPath"] = (...args) => bound().renderer.renderSmoodlyPath(...args);
|
|
89
94
|
export const smoodlyMetadata: Renderer["smoodlyMetadata"] = (...args) => bound().renderer.smoodlyMetadata(...args);
|
|
90
95
|
export const renderSmoodlyPage: Renderer["renderSmoodlyPage"] = (...args) => bound().renderer.renderSmoodlyPage(...args);
|
|
91
96
|
export const smoodlyPageMetadata: Renderer["smoodlyPageMetadata"] = (...args) => bound().renderer.smoodlyPageMetadata(...args);
|
|
92
|
-
export const getSmoodlyShared: Renderer["getSmoodlyShared"] = (...args) => bound().renderer.getSmoodlyShared(...args);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Shared content: code-declared singletons, edited once under Globals
|
|
2
|
+
// and read anywhere. `site` is an object item — fields code consumes;
|
|
3
|
+
// the layout reads it through q().getShared("site"). A visual item
|
|
4
|
+
// (`section: SomeSection`) renders through a section instead.
|
|
5
|
+
import { f, smoodly } from "smoodly";
|
|
6
|
+
|
|
7
|
+
export const site = smoodly.shared({
|
|
8
|
+
name: "site",
|
|
9
|
+
title: "Site",
|
|
10
|
+
fields: {
|
|
11
|
+
name: f.text(),
|
|
12
|
+
tagline: f.text().localized(),
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export const shared = [site];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Toolsets are values, not registrations: a richtext field names one.
|
|
2
|
+
// `text` is the starter's one set — the default marks and block nodes,
|
|
3
|
+
// plus the Button element. Elements are embedded by value; the config
|
|
4
|
+
// must also register them (smoodly/elements.ts; defineConfig checks).
|
|
5
|
+
// Relative imports on purpose: collections.ts pulls this file into
|
|
6
|
+
// create-smoodly-app's template build, which runs outside the app.
|
|
7
|
+
import { smoodly } from "smoodly";
|
|
8
|
+
import { Button } from "../components/elements/Button";
|
|
9
|
+
|
|
10
|
+
export const text = smoodly.toolset({
|
|
11
|
+
marks: ["bold", "italic", "link"],
|
|
12
|
+
nodes: ["h2", "h3", "bulletList", "orderedList", "blockquote"],
|
|
13
|
+
elements: [Button],
|
|
14
|
+
});
|