create-smoodly-app 0.0.44 → 0.0.46
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 +15 -10
- package/dist/index.js +75 -33
- package/package.json +2 -2
- package/templates/astro-blank/AGENTS.md +55 -0
- package/templates/astro-blank/CLAUDE.md +1 -0
- package/templates/astro-blank/README.md +88 -0
- package/templates/astro-blank/_gitignore +5 -0
- package/templates/astro-blank/astro.config.ts +15 -0
- package/templates/astro-blank/package.json +24 -0
- package/templates/astro-blank/scripts/seed.ts +80 -0
- package/templates/astro-blank/src/components/LocaleNav.astro +15 -0
- package/templates/astro-blank/src/components/elements/Button.schema.ts +22 -0
- package/templates/astro-blank/src/components/pages/Home.schema.ts +17 -0
- package/templates/astro-blank/src/components/pages/Page.schema.ts +14 -0
- package/templates/astro-blank/src/components/sections/Text.schema.ts +24 -0
- package/templates/astro-blank/src/elements/button.astro +10 -0
- package/templates/astro-blank/src/entry-pages/posts.astro +23 -0
- package/templates/astro-blank/src/layouts/Layout.astro +25 -0
- package/templates/astro-blank/src/live.config.ts +13 -0
- package/templates/astro-blank/src/page-types/home.astro +15 -0
- package/templates/astro-blank/src/page-types/page.astro +15 -0
- package/templates/astro-blank/src/pages/404.astro +7 -0
- package/templates/astro-blank/src/sections/text.astro +18 -0
- package/templates/astro-blank/src/smoodly/collections.ts +24 -0
- package/templates/astro-blank/src/smoodly/config.ts +28 -0
- package/templates/astro-blank/src/smoodly/elements.ts +5 -0
- package/templates/astro-blank/src/smoodly/globals.ts +18 -0
- package/templates/astro-blank/src/smoodly/sections.ts +5 -0
- package/templates/astro-blank/src/smoodly/toolsets.ts +14 -0
- package/templates/astro-blank/src/styles/global.css +57 -0
- package/templates/astro-blank/supabase/migrations/20260926120000_smoodly_v1.sql +535 -0
- package/templates/astro-blank/supabase/migrations/20260926130000_smoodly_v2.sql +26 -0
- package/templates/astro-blank/supabase/migrations/20260926140000_smoodly_v3.sql +38 -0
- package/templates/astro-blank/supabase/migrations/20260926150000_smoodly_v4.sql +41 -0
- package/templates/astro-blank/supabase/migrations/20260929120000_smoodly_v5.sql +56 -0
- package/templates/astro-blank/supabase/migrations/20260929135523_smoodly_v6.sql +200 -0
- package/templates/astro-blank/supabase/migrations/20260930040956_smoodly_v7.sql +84 -0
- package/templates/astro-blank/supabase/migrations/20261007120000_smoodly_v8.sql +154 -0
- package/templates/astro-blank/supabase/migrations/20261007200000_smoodly_v9.sql +30 -0
- package/templates/{blank/supabase/migrations/20260930041056_smoodly_views.sql → astro-blank/supabase/migrations/20261007200100_smoodly_views.sql} +1 -1
- package/templates/astro-blank/tsconfig.json +17 -0
- package/templates/astro-blank-intl/AGENTS.md +55 -0
- package/templates/astro-blank-intl/CLAUDE.md +1 -0
- package/templates/astro-blank-intl/README.md +89 -0
- package/templates/astro-blank-intl/_gitignore +5 -0
- package/templates/astro-blank-intl/astro.config.ts +17 -0
- package/templates/astro-blank-intl/package.json +24 -0
- package/templates/astro-blank-intl/scripts/seed.ts +80 -0
- package/templates/astro-blank-intl/src/components/LocaleNav.astro +15 -0
- package/templates/astro-blank-intl/src/components/elements/Button.schema.ts +22 -0
- package/templates/astro-blank-intl/src/components/pages/Home.schema.ts +17 -0
- package/templates/astro-blank-intl/src/components/pages/Page.schema.ts +14 -0
- package/templates/astro-blank-intl/src/components/sections/Text.schema.ts +24 -0
- package/templates/astro-blank-intl/src/elements/button.astro +10 -0
- package/templates/astro-blank-intl/src/entry-pages/posts.astro +23 -0
- package/templates/astro-blank-intl/src/layouts/Layout.astro +25 -0
- package/templates/astro-blank-intl/src/live.config.ts +13 -0
- package/templates/astro-blank-intl/src/page-types/home.astro +15 -0
- package/templates/astro-blank-intl/src/page-types/page.astro +15 -0
- package/templates/astro-blank-intl/src/pages/404.astro +7 -0
- package/templates/astro-blank-intl/src/sections/text.astro +18 -0
- package/templates/astro-blank-intl/src/smoodly/collections.ts +24 -0
- package/templates/astro-blank-intl/src/smoodly/config.ts +29 -0
- package/templates/astro-blank-intl/src/smoodly/elements.ts +5 -0
- package/templates/astro-blank-intl/src/smoodly/globals.ts +18 -0
- package/templates/astro-blank-intl/src/smoodly/sections.ts +5 -0
- package/templates/astro-blank-intl/src/smoodly/toolsets.ts +14 -0
- package/templates/astro-blank-intl/src/styles/global.css +57 -0
- package/templates/astro-blank-intl/supabase/migrations/20260926120000_smoodly_v1.sql +535 -0
- package/templates/astro-blank-intl/supabase/migrations/20260926130000_smoodly_v2.sql +26 -0
- package/templates/astro-blank-intl/supabase/migrations/20260926140000_smoodly_v3.sql +38 -0
- package/templates/astro-blank-intl/supabase/migrations/20260926150000_smoodly_v4.sql +41 -0
- package/templates/astro-blank-intl/supabase/migrations/20260929120000_smoodly_v5.sql +56 -0
- package/templates/astro-blank-intl/supabase/migrations/20260929135523_smoodly_v6.sql +200 -0
- package/templates/astro-blank-intl/supabase/migrations/20260930040956_smoodly_v7.sql +84 -0
- package/templates/astro-blank-intl/supabase/migrations/20261007120000_smoodly_v8.sql +154 -0
- package/templates/astro-blank-intl/supabase/migrations/20261007200000_smoodly_v9.sql +30 -0
- package/templates/{blank-intl/supabase/migrations/20260930041056_smoodly_views.sql → astro-blank-intl/supabase/migrations/20261007200100_smoodly_views.sql} +1 -1
- package/templates/astro-blank-intl/tsconfig.json +17 -0
- package/templates/astro-blank-intl.tsconfig.json +24 -0
- package/templates/astro-blank.tsconfig.json +24 -0
- package/templates/astro-lorem/AGENTS.md +55 -0
- package/templates/astro-lorem/CLAUDE.md +1 -0
- package/templates/astro-lorem/README.md +60 -0
- package/templates/astro-lorem/_gitignore +5 -0
- package/templates/astro-lorem/astro.config.ts +15 -0
- package/templates/astro-lorem/package.json +24 -0
- package/templates/astro-lorem/public/images/about_main.jpg +0 -0
- package/templates/astro-lorem/public/images/article_photo.jpg +0 -0
- package/templates/astro-lorem/public/images/hero_image.jpg +0 -0
- package/templates/astro-lorem/public/images/home_section_2.jpg +0 -0
- package/templates/astro-lorem/scripts/seed.ts +405 -0
- package/templates/astro-lorem/src/components/ArticleCard.astro +19 -0
- package/templates/astro-lorem/src/components/articles.ts +42 -0
- package/templates/astro-lorem/src/components/elements/Callout.schema.ts +24 -0
- package/templates/astro-lorem/src/components/elements/Cta.schema.ts +21 -0
- package/templates/astro-lorem/src/components/news.ts +13 -0
- package/templates/astro-lorem/src/components/pages/Articles.schema.ts +20 -0
- package/templates/astro-lorem/src/components/pages/Home.schema.ts +26 -0
- package/templates/astro-lorem/src/components/pages/News.schema.ts +17 -0
- package/templates/astro-lorem/src/components/pages/Page.schema.ts +24 -0
- package/templates/astro-lorem/src/components/sections/FavouriteArticles.schema.ts +17 -0
- package/templates/astro-lorem/src/components/sections/Footer.schema.ts +31 -0
- package/templates/astro-lorem/src/components/sections/Header.schema.ts +21 -0
- package/templates/astro-lorem/src/components/sections/Hero.schema.ts +24 -0
- package/templates/astro-lorem/src/components/sections/ImageText.schema.ts +30 -0
- package/templates/astro-lorem/src/components/sections/PageHero.schema.ts +21 -0
- package/templates/astro-lorem/src/components/sections/People.schema.ts +15 -0
- package/templates/astro-lorem/src/components/sections/Points.schema.ts +21 -0
- package/templates/astro-lorem/src/components/sections/Quote.schema.ts +23 -0
- package/templates/astro-lorem/src/elements/callout.astro +13 -0
- package/templates/astro-lorem/src/elements/cta.astro +15 -0
- package/templates/astro-lorem/src/entry-pages/articles.astro +71 -0
- package/templates/astro-lorem/src/entry-pages/news.astro +29 -0
- package/templates/astro-lorem/src/layouts/Layout.astro +39 -0
- package/templates/astro-lorem/src/live.config.ts +20 -0
- package/templates/astro-lorem/src/messages/en.json +7 -0
- package/templates/astro-lorem/src/messages/fi.json +7 -0
- package/templates/astro-lorem/src/page-types/articlesIndex.astro +24 -0
- package/templates/astro-lorem/src/page-types/home.astro +14 -0
- package/templates/astro-lorem/src/page-types/newsIndex.astro +28 -0
- package/templates/astro-lorem/src/page-types/page.astro +27 -0
- package/templates/astro-lorem/src/pages/404.astro +7 -0
- package/templates/astro-lorem/src/sections/favouriteArticles.astro +26 -0
- package/templates/astro-lorem/src/sections/footer.astro +37 -0
- package/templates/astro-lorem/src/sections/header.astro +27 -0
- package/templates/astro-lorem/src/sections/hero.astro +28 -0
- package/templates/astro-lorem/src/sections/imageText.astro +22 -0
- package/templates/astro-lorem/src/sections/pageHero.astro +20 -0
- package/templates/astro-lorem/src/sections/peopleSection.astro +24 -0
- package/templates/astro-lorem/src/sections/points.astro +33 -0
- package/templates/astro-lorem/src/sections/quote.astro +16 -0
- package/templates/astro-lorem/src/smoodly/collections.ts +63 -0
- package/templates/astro-lorem/src/smoodly/config.ts +48 -0
- package/templates/astro-lorem/src/smoodly/elements.ts +6 -0
- package/templates/astro-lorem/src/smoodly/globals.ts +29 -0
- package/templates/astro-lorem/src/smoodly/sections.ts +18 -0
- package/templates/astro-lorem/src/smoodly/toolsets.ts +16 -0
- package/templates/astro-lorem/src/strings.ts +17 -0
- package/templates/astro-lorem/src/styles/global.css +228 -0
- package/templates/astro-lorem/supabase/migrations/20260926120000_smoodly_v1.sql +535 -0
- package/templates/astro-lorem/supabase/migrations/20260926130000_smoodly_v2.sql +26 -0
- package/templates/astro-lorem/supabase/migrations/20260926140000_smoodly_v3.sql +38 -0
- package/templates/astro-lorem/supabase/migrations/20260926150000_smoodly_v4.sql +41 -0
- package/templates/astro-lorem/supabase/migrations/20260929120000_smoodly_v5.sql +56 -0
- package/templates/astro-lorem/supabase/migrations/20260929135523_smoodly_v6.sql +200 -0
- package/templates/astro-lorem/supabase/migrations/20260930040956_smoodly_v7.sql +84 -0
- package/templates/astro-lorem/supabase/migrations/20261007120000_smoodly_v8.sql +154 -0
- package/templates/astro-lorem/supabase/migrations/20261007200000_smoodly_v9.sql +30 -0
- package/templates/{lorem/supabase/migrations/20260930041056_smoodly_views.sql → astro-lorem/supabase/migrations/20261007200100_smoodly_views.sql} +1 -1
- package/templates/astro-lorem/tsconfig.json +17 -0
- package/templates/astro-lorem-intl/AGENTS.md +55 -0
- package/templates/astro-lorem-intl/CLAUDE.md +1 -0
- package/templates/astro-lorem-intl/README.md +62 -0
- package/templates/astro-lorem-intl/_gitignore +5 -0
- package/templates/astro-lorem-intl/astro.config.ts +17 -0
- package/templates/astro-lorem-intl/package.json +24 -0
- package/templates/astro-lorem-intl/public/images/about_main.jpg +0 -0
- package/templates/astro-lorem-intl/public/images/article_photo.jpg +0 -0
- package/templates/astro-lorem-intl/public/images/hero_image.jpg +0 -0
- package/templates/astro-lorem-intl/public/images/home_section_2.jpg +0 -0
- package/templates/astro-lorem-intl/scripts/seed.ts +405 -0
- package/templates/astro-lorem-intl/src/components/ArticleCard.astro +19 -0
- package/templates/astro-lorem-intl/src/components/articles.ts +42 -0
- package/templates/astro-lorem-intl/src/components/elements/Callout.schema.ts +24 -0
- package/templates/astro-lorem-intl/src/components/elements/Cta.schema.ts +21 -0
- package/templates/astro-lorem-intl/src/components/news.ts +13 -0
- package/templates/astro-lorem-intl/src/components/pages/Articles.schema.ts +20 -0
- package/templates/astro-lorem-intl/src/components/pages/Home.schema.ts +26 -0
- package/templates/astro-lorem-intl/src/components/pages/News.schema.ts +17 -0
- package/templates/astro-lorem-intl/src/components/pages/Page.schema.ts +24 -0
- package/templates/astro-lorem-intl/src/components/sections/FavouriteArticles.schema.ts +17 -0
- package/templates/astro-lorem-intl/src/components/sections/Footer.schema.ts +31 -0
- package/templates/astro-lorem-intl/src/components/sections/Header.schema.ts +21 -0
- package/templates/astro-lorem-intl/src/components/sections/Hero.schema.ts +24 -0
- package/templates/astro-lorem-intl/src/components/sections/ImageText.schema.ts +30 -0
- package/templates/astro-lorem-intl/src/components/sections/PageHero.schema.ts +21 -0
- package/templates/astro-lorem-intl/src/components/sections/People.schema.ts +15 -0
- package/templates/astro-lorem-intl/src/components/sections/Points.schema.ts +21 -0
- package/templates/astro-lorem-intl/src/components/sections/Quote.schema.ts +23 -0
- package/templates/astro-lorem-intl/src/elements/callout.astro +13 -0
- package/templates/astro-lorem-intl/src/elements/cta.astro +15 -0
- package/templates/astro-lorem-intl/src/entry-pages/articles.astro +71 -0
- package/templates/astro-lorem-intl/src/entry-pages/news.astro +29 -0
- package/templates/astro-lorem-intl/src/layouts/Layout.astro +39 -0
- package/templates/astro-lorem-intl/src/live.config.ts +20 -0
- package/templates/astro-lorem-intl/src/messages/en.json +7 -0
- package/templates/astro-lorem-intl/src/messages/fi.json +7 -0
- package/templates/astro-lorem-intl/src/page-types/articlesIndex.astro +24 -0
- package/templates/astro-lorem-intl/src/page-types/home.astro +14 -0
- package/templates/astro-lorem-intl/src/page-types/newsIndex.astro +28 -0
- package/templates/astro-lorem-intl/src/page-types/page.astro +27 -0
- package/templates/astro-lorem-intl/src/pages/404.astro +7 -0
- package/templates/astro-lorem-intl/src/sections/favouriteArticles.astro +26 -0
- package/templates/astro-lorem-intl/src/sections/footer.astro +37 -0
- package/templates/astro-lorem-intl/src/sections/header.astro +27 -0
- package/templates/astro-lorem-intl/src/sections/hero.astro +28 -0
- package/templates/astro-lorem-intl/src/sections/imageText.astro +22 -0
- package/templates/astro-lorem-intl/src/sections/pageHero.astro +20 -0
- package/templates/astro-lorem-intl/src/sections/peopleSection.astro +24 -0
- package/templates/astro-lorem-intl/src/sections/points.astro +33 -0
- package/templates/astro-lorem-intl/src/sections/quote.astro +16 -0
- package/templates/astro-lorem-intl/src/smoodly/collections.ts +63 -0
- package/templates/astro-lorem-intl/src/smoodly/config.ts +48 -0
- package/templates/astro-lorem-intl/src/smoodly/elements.ts +6 -0
- package/templates/astro-lorem-intl/src/smoodly/globals.ts +29 -0
- package/templates/astro-lorem-intl/src/smoodly/sections.ts +18 -0
- package/templates/astro-lorem-intl/src/smoodly/toolsets.ts +16 -0
- package/templates/astro-lorem-intl/src/strings.ts +17 -0
- package/templates/astro-lorem-intl/src/styles/global.css +228 -0
- package/templates/astro-lorem-intl/supabase/migrations/20260926120000_smoodly_v1.sql +535 -0
- package/templates/astro-lorem-intl/supabase/migrations/20260926130000_smoodly_v2.sql +26 -0
- package/templates/astro-lorem-intl/supabase/migrations/20260926140000_smoodly_v3.sql +38 -0
- package/templates/astro-lorem-intl/supabase/migrations/20260926150000_smoodly_v4.sql +41 -0
- package/templates/astro-lorem-intl/supabase/migrations/20260929120000_smoodly_v5.sql +56 -0
- package/templates/astro-lorem-intl/supabase/migrations/20260929135523_smoodly_v6.sql +200 -0
- package/templates/astro-lorem-intl/supabase/migrations/20260930040956_smoodly_v7.sql +84 -0
- package/templates/astro-lorem-intl/supabase/migrations/20261007120000_smoodly_v8.sql +154 -0
- package/templates/astro-lorem-intl/supabase/migrations/20261007200000_smoodly_v9.sql +30 -0
- package/templates/{lorem-intl/supabase/migrations/20260930041056_smoodly_views.sql → astro-lorem-intl/supabase/migrations/20261007200100_smoodly_views.sql} +1 -1
- package/templates/astro-lorem-intl/tsconfig.json +17 -0
- package/templates/astro-lorem-intl.tsconfig.json +24 -0
- package/templates/astro-lorem.tsconfig.json +24 -0
- package/templates/blank/AGENTS.md +23 -16
- package/templates/blank/README.md +20 -15
- package/templates/blank/app/(smoodly)/admin/[[...segments]]/route.ts +8 -0
- package/templates/blank/components/elements/Button.schema.ts +22 -0
- package/templates/blank/components/elements/Button.tsx +2 -20
- package/templates/blank/components/pages/Home.schema.ts +17 -0
- package/templates/blank/components/pages/Home.tsx +2 -16
- package/templates/blank/components/pages/Page.schema.ts +14 -0
- package/templates/blank/components/pages/Page.tsx +2 -14
- package/templates/blank/components/pages/Post.tsx +5 -4
- package/templates/blank/components/sections/Text.schema.ts +24 -0
- package/templates/blank/components/sections/Text.tsx +7 -27
- package/templates/blank/package.json +1 -1
- package/templates/blank/scripts/seed.ts +2 -2
- package/templates/blank/smoodly/config.ts +8 -7
- package/templates/blank/smoodly/elements.ts +4 -4
- package/templates/blank/smoodly/globals.ts +4 -2
- package/templates/blank/smoodly/richtext.tsx +4 -5
- package/templates/blank/smoodly/sections.ts +4 -4
- package/templates/blank/smoodly/server.ts +22 -44
- package/templates/blank/smoodly/toolsets.ts +2 -2
- package/templates/blank/smoodly/views.ts +15 -0
- package/templates/blank/supabase/migrations/20261007120000_smoodly_v8.sql +154 -0
- package/templates/blank/supabase/migrations/20261007200000_smoodly_v9.sql +30 -0
- package/templates/blank/supabase/migrations/20261007200100_smoodly_views.sql +20 -0
- package/templates/blank-intl/AGENTS.md +23 -16
- package/templates/blank-intl/README.md +20 -15
- package/templates/blank-intl/app/(smoodly)/admin/[[...segments]]/route.ts +8 -0
- package/templates/blank-intl/components/elements/Button.schema.ts +22 -0
- package/templates/blank-intl/components/elements/Button.tsx +2 -20
- package/templates/blank-intl/components/pages/Home.schema.ts +17 -0
- package/templates/blank-intl/components/pages/Home.tsx +2 -16
- package/templates/blank-intl/components/pages/Page.schema.ts +14 -0
- package/templates/blank-intl/components/pages/Page.tsx +2 -14
- package/templates/blank-intl/components/pages/Post.tsx +5 -4
- package/templates/blank-intl/components/sections/Text.schema.ts +24 -0
- package/templates/blank-intl/components/sections/Text.tsx +7 -27
- package/templates/blank-intl/package.json +1 -1
- package/templates/blank-intl/scripts/seed.ts +2 -2
- package/templates/blank-intl/smoodly/config.ts +8 -7
- package/templates/blank-intl/smoodly/elements.ts +4 -4
- package/templates/blank-intl/smoodly/globals.ts +4 -2
- package/templates/blank-intl/smoodly/richtext.tsx +4 -5
- package/templates/blank-intl/smoodly/sections.ts +4 -4
- package/templates/blank-intl/smoodly/server.ts +22 -44
- package/templates/blank-intl/smoodly/toolsets.ts +2 -2
- package/templates/blank-intl/smoodly/views.ts +15 -0
- package/templates/blank-intl/supabase/migrations/20261007120000_smoodly_v8.sql +154 -0
- package/templates/blank-intl/supabase/migrations/20261007200000_smoodly_v9.sql +30 -0
- package/templates/blank-intl/supabase/migrations/20261007200100_smoodly_views.sql +20 -0
- package/templates/lorem/AGENTS.md +23 -16
- package/templates/lorem/README.md +3 -3
- package/templates/lorem/app/(smoodly)/admin/[[...segments]]/route.ts +8 -0
- package/templates/lorem/components/elements/Callout.schema.ts +24 -0
- package/templates/lorem/components/elements/Callout.tsx +2 -24
- package/templates/lorem/components/elements/Cta.schema.ts +21 -0
- package/templates/lorem/components/elements/Cta.tsx +2 -21
- package/templates/lorem/components/pages/Article.tsx +1 -1
- package/templates/lorem/components/pages/Articles.schema.ts +20 -0
- package/templates/lorem/components/pages/Articles.tsx +2 -20
- package/templates/lorem/components/pages/Home.schema.ts +26 -0
- package/templates/lorem/components/pages/Home.tsx +2 -26
- package/templates/lorem/components/pages/News.schema.ts +17 -0
- package/templates/lorem/components/pages/News.tsx +2 -17
- package/templates/lorem/components/pages/NewsPost.tsx +1 -1
- package/templates/lorem/components/pages/Page.schema.ts +24 -0
- package/templates/lorem/components/pages/Page.tsx +2 -24
- package/templates/lorem/components/sections/FavouriteArticles.schema.ts +17 -0
- package/templates/lorem/components/sections/FavouriteArticles.tsx +2 -17
- package/templates/lorem/components/sections/Footer.schema.ts +31 -0
- package/templates/lorem/components/sections/Footer.tsx +4 -32
- package/templates/lorem/components/sections/Header.schema.ts +21 -0
- package/templates/lorem/components/sections/Header.tsx +2 -21
- package/templates/lorem/components/sections/Hero.schema.ts +24 -0
- package/templates/lorem/components/sections/Hero.tsx +2 -24
- package/templates/lorem/components/sections/ImageText.schema.ts +30 -0
- package/templates/lorem/components/sections/ImageText.tsx +2 -30
- package/templates/lorem/components/sections/PageHero.schema.ts +21 -0
- package/templates/lorem/components/sections/PageHero.tsx +2 -21
- package/templates/lorem/components/sections/People.schema.ts +15 -0
- package/templates/lorem/components/sections/People.tsx +2 -14
- package/templates/lorem/components/sections/Points.schema.ts +21 -0
- package/templates/lorem/components/sections/Points.tsx +2 -21
- package/templates/lorem/components/sections/Quote.schema.ts +23 -0
- package/templates/lorem/components/sections/Quote.tsx +2 -23
- package/templates/lorem/package.json +1 -1
- package/templates/lorem/scripts/seed.ts +18 -18
- package/templates/lorem/smoodly/collections.ts +2 -2
- package/templates/lorem/smoodly/config.ts +14 -15
- package/templates/lorem/smoodly/elements.ts +5 -5
- package/templates/lorem/smoodly/globals.ts +10 -7
- package/templates/lorem/smoodly/richtext.tsx +5 -5
- package/templates/lorem/smoodly/sections.ts +12 -13
- package/templates/lorem/smoodly/server.ts +22 -44
- package/templates/lorem/smoodly/toolsets.ts +3 -3
- package/templates/lorem/smoodly/views.ts +33 -0
- package/templates/lorem/supabase/migrations/20261007120000_smoodly_v8.sql +154 -0
- package/templates/lorem/supabase/migrations/20261007200000_smoodly_v9.sql +30 -0
- package/templates/lorem/supabase/migrations/20261007200100_smoodly_views.sql +58 -0
- package/templates/lorem-intl/AGENTS.md +23 -16
- package/templates/lorem-intl/README.md +3 -3
- package/templates/lorem-intl/app/(smoodly)/admin/[[...segments]]/route.ts +8 -0
- package/templates/lorem-intl/components/elements/Callout.schema.ts +24 -0
- package/templates/lorem-intl/components/elements/Callout.tsx +2 -24
- package/templates/lorem-intl/components/elements/Cta.schema.ts +21 -0
- package/templates/lorem-intl/components/elements/Cta.tsx +2 -21
- package/templates/lorem-intl/components/pages/Article.tsx +1 -1
- package/templates/lorem-intl/components/pages/Articles.schema.ts +20 -0
- package/templates/lorem-intl/components/pages/Articles.tsx +2 -20
- package/templates/lorem-intl/components/pages/Home.schema.ts +26 -0
- package/templates/lorem-intl/components/pages/Home.tsx +2 -26
- package/templates/lorem-intl/components/pages/News.schema.ts +17 -0
- package/templates/lorem-intl/components/pages/News.tsx +2 -17
- package/templates/lorem-intl/components/pages/NewsPost.tsx +1 -1
- package/templates/lorem-intl/components/pages/Page.schema.ts +24 -0
- package/templates/lorem-intl/components/pages/Page.tsx +2 -24
- package/templates/lorem-intl/components/sections/FavouriteArticles.schema.ts +17 -0
- package/templates/lorem-intl/components/sections/FavouriteArticles.tsx +2 -17
- package/templates/lorem-intl/components/sections/Footer.schema.ts +31 -0
- package/templates/lorem-intl/components/sections/Footer.tsx +4 -32
- package/templates/lorem-intl/components/sections/Header.schema.ts +21 -0
- package/templates/lorem-intl/components/sections/Header.tsx +2 -21
- package/templates/lorem-intl/components/sections/Hero.schema.ts +24 -0
- package/templates/lorem-intl/components/sections/Hero.tsx +2 -24
- package/templates/lorem-intl/components/sections/ImageText.schema.ts +30 -0
- package/templates/lorem-intl/components/sections/ImageText.tsx +2 -30
- package/templates/lorem-intl/components/sections/PageHero.schema.ts +21 -0
- package/templates/lorem-intl/components/sections/PageHero.tsx +2 -21
- package/templates/lorem-intl/components/sections/People.schema.ts +15 -0
- package/templates/lorem-intl/components/sections/People.tsx +2 -14
- package/templates/lorem-intl/components/sections/Points.schema.ts +21 -0
- package/templates/lorem-intl/components/sections/Points.tsx +2 -21
- package/templates/lorem-intl/components/sections/Quote.schema.ts +23 -0
- package/templates/lorem-intl/components/sections/Quote.tsx +2 -23
- package/templates/lorem-intl/package.json +1 -1
- package/templates/lorem-intl/scripts/seed.ts +18 -18
- package/templates/lorem-intl/smoodly/collections.ts +2 -2
- package/templates/lorem-intl/smoodly/config.ts +14 -15
- package/templates/lorem-intl/smoodly/elements.ts +5 -5
- package/templates/lorem-intl/smoodly/globals.ts +10 -7
- package/templates/lorem-intl/smoodly/richtext.tsx +5 -5
- package/templates/lorem-intl/smoodly/sections.ts +12 -13
- package/templates/lorem-intl/smoodly/server.ts +22 -44
- package/templates/lorem-intl/smoodly/toolsets.ts +3 -3
- package/templates/lorem-intl/smoodly/views.ts +33 -0
- package/templates/lorem-intl/supabase/migrations/20261007120000_smoodly_v8.sql +154 -0
- package/templates/lorem-intl/supabase/migrations/20261007200000_smoodly_v9.sql +30 -0
- package/templates/lorem-intl/supabase/migrations/20261007200100_smoodly_views.sql +58 -0
- package/templates/blank/app/(smoodly)/admin/[[...segments]]/page.tsx +0 -1
- package/templates/blank/app/(smoodly)/admin/layout.tsx +0 -15
- package/templates/blank/smoodly/admin.tsx +0 -6
- package/templates/blank/smoodly/ops.ts +0 -11
- package/templates/blank-intl/app/(smoodly)/admin/[[...segments]]/page.tsx +0 -1
- package/templates/blank-intl/app/(smoodly)/admin/layout.tsx +0 -15
- package/templates/blank-intl/smoodly/admin.tsx +0 -6
- package/templates/blank-intl/smoodly/ops.ts +0 -11
- package/templates/lorem/app/(smoodly)/admin/[[...segments]]/page.tsx +0 -1
- package/templates/lorem/app/(smoodly)/admin/layout.tsx +0 -15
- package/templates/lorem/smoodly/admin.tsx +0 -6
- package/templates/lorem/smoodly/ops.ts +0 -11
- package/templates/lorem-intl/app/(smoodly)/admin/[[...segments]]/page.tsx +0 -1
- package/templates/lorem-intl/app/(smoodly)/admin/layout.tsx +0 -15
- package/templates/lorem-intl/smoodly/admin.tsx +0 -6
- package/templates/lorem-intl/smoodly/ops.ts +0 -11
|
@@ -7,11 +7,19 @@ where things are.
|
|
|
7
7
|
|
|
8
8
|
## Rules
|
|
9
9
|
|
|
10
|
-
- **Register
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
- **Register schemas in the config, components in `smoodly/views.ts`.**
|
|
11
|
+
Every section, element and page type is two files: `Name.schema.ts`
|
|
12
|
+
and `Name.tsx`. The schema is listed in its barrel (`sections.ts`,
|
|
13
|
+
`elements.ts`, the config's `pages`; collections and global items in
|
|
14
|
+
`collections.ts`, `globals.ts`) and `smoodly/config.ts` is the one
|
|
15
|
+
registry. The component is listed in `smoodly/views.ts`, an element's
|
|
16
|
+
also in `smoodly/richtext.tsx`; an entry page is listed only in
|
|
17
|
+
`smoodly/views.ts`. A schema with no component, or a component with
|
|
18
|
+
no schema, is a named error on the first render.
|
|
19
|
+
- **A `.schema.ts` file imports no component** and nothing from
|
|
20
|
+
`smoodly/server.ts` or `smoodly/richtext.tsx`. Zones, toolsets, global
|
|
21
|
+
items and `node()` take schemas (`z.locked(heroSchema)`), never
|
|
22
|
+
components.
|
|
15
23
|
- **After a new collection or a `smoodly` upgrade, run `npx smoodly migrate`**
|
|
16
24
|
and apply what it writes (`supabase db push` hosted, `supabase migration up`
|
|
17
25
|
local). It copies the core schema files the package ships and writes a
|
|
@@ -23,16 +31,15 @@ where things are.
|
|
|
23
31
|
the admin's own operations, so validation and publish checks apply and
|
|
24
32
|
a failure throws. Never write rows or call the stores directly. The
|
|
25
33
|
seed is idempotent; run it with `npm run seed`.
|
|
26
|
-
- **
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
is a second root layout. Do not add an `app/layout.tsx`.
|
|
34
|
+
- **The admin is one route.** `app/(smoodly)/admin/[[...segments]]/route.ts`
|
|
35
|
+
serves the admin's page, its files and its operations from the
|
|
36
|
+
`smoodly` package; the folder name must match `admin.path` in the
|
|
37
|
+
config. The admin is prebuilt: nothing of it is compiled into the
|
|
38
|
+
site, and it takes no layout. Server-side pieces such as
|
|
39
|
+
`supabaseAdminAuth` and the content API come from `smoodly/admin`.
|
|
40
|
+
- **One root layout.** The site's layout lives in its route group or
|
|
41
|
+
locale segment. Do not add an `app/layout.tsx`: it would wrap that
|
|
42
|
+
layout in a second `<html>`.
|
|
36
43
|
- **Toolsets and elements.** A richtext field names a toolset
|
|
37
44
|
(`smoodly/toolsets.ts`); a toolset embeds elements by value; the config
|
|
38
45
|
must register those elements too. Files the toolset imports use
|
|
@@ -45,7 +52,7 @@ where things are.
|
|
|
45
52
|
- **Multilingual sites.** Content locales are Smoodly's; URL locales are
|
|
46
53
|
next-intl's. The locale set is `i18n/routing.ts`. UI strings of the
|
|
47
54
|
site's own go through next-intl's messages in `messages/<locale>.json`.
|
|
48
|
-
- **Fixed versus open pages.** A page
|
|
55
|
+
- **Fixed versus open pages.** A page type with a `slug` is fixed: one
|
|
49
56
|
record, created for you, never deleted. Without one it is open: editors
|
|
50
57
|
create as many as they like.
|
|
51
58
|
|
|
@@ -10,36 +10,41 @@ for an agent (or a person) building the site.
|
|
|
10
10
|
|
|
11
11
|
- `app/(site)/page.tsx` — the home page: one line calling renderSmoodlyPath([]).
|
|
12
12
|
- `app/(site)/[...path]/page.tsx` — every other page and every collection entry, at any depth.
|
|
13
|
-
- `app/(site)/layout.tsx` — the site's root layout: `app/globals.css`, the footer line from the `site` item
|
|
13
|
+
- `app/(site)/layout.tsx` — the site's root layout: `app/globals.css`, the footer line from the `site` item. The admin is one route, `app/(smoodly)/admin/[[...segments]]/route.ts`, and takes no layout.
|
|
14
14
|
- `components/pages/` — the page shapes and the entry page: `Home` (fixed at /, one freeform zone), `Page` (open, editors create many), `Post` (the entry page for posts).
|
|
15
|
-
- `components/sections/Text.tsx` — the one section: a title and a richtext body.
|
|
16
|
-
- `components/elements/Button.tsx` — the one element: a link styled as a button, embedded in richtext through `smoodly/toolsets.ts`.
|
|
15
|
+
- `components/sections/Text.schema.ts` and `Text.tsx` — the one section: a title and a richtext body. The schema is listed in `smoodly/sections.ts`, the component in `smoodly/views.ts`.
|
|
16
|
+
- `components/elements/Button.schema.ts` and `Button.tsx` — the one element: a link styled as a button, embedded in richtext through `smoodly/toolsets.ts`.
|
|
17
17
|
- `components/LocaleNav.tsx` — the language links every page view renders from its `locales` map: the same page in the other language, or its home when there is no translation; nothing with one locale.
|
|
18
|
-
- `smoodly/` — the wiring: `config.ts` (the registry and settings), `collections.ts` (posts), `globals.ts` (the site item), `sections.ts
|
|
18
|
+
- `smoodly/` — the wiring: `config.ts` (the registry of schemas and the settings; it imports no component), `collections.ts` (posts), `globals.ts` (the site item), `sections.ts` and `elements.ts` (the schemas the config registers), `views.ts` (the components that render them), `toolsets.ts`, `server.ts` (site layer, renderer, the read API `q`, the content API `content()`), `richtext.tsx` (the bound renderer).
|
|
19
19
|
- `scripts/seed.ts` — the home page and the site item, written through the content API (`content()`). `npm run seed` is idempotent.
|
|
20
20
|
- `app/globals.css` — a reset, a container, the two tones. Replace it.
|
|
21
21
|
- `.env.local` — `SMOODLY_URL`, `SMOODLY_SECRET_KEY`, `SMOODLY_PUBLISHABLE_KEY`.
|
|
22
22
|
|
|
23
23
|
## Add a section
|
|
24
24
|
|
|
25
|
-
Copy `components/sections/Text.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
`
|
|
25
|
+
Copy `components/sections/Text.schema.ts` and `Text.tsx`. In the
|
|
26
|
+
schema file give the schema a new `name` and `title` and declare its
|
|
27
|
+
fields; in the component render them inside `<smoodly.Section>` with
|
|
28
|
+
marks on each field. Then three lists: the schema in `sections` in
|
|
29
|
+
`smoodly/sections.ts`, the component in `sections` in
|
|
30
|
+
`smoodly/views.ts`, and the schema in the `sections` of every zone
|
|
31
|
+
that may hold it in `components/pages/*.schema.ts`. It appears in the
|
|
32
|
+
editor's "+" picker. A schema with no component in `smoodly/views.ts`
|
|
33
|
+
is a named error on the first render.
|
|
30
34
|
|
|
31
35
|
## Add an element
|
|
32
36
|
|
|
33
|
-
Copy `components/elements/Button.
|
|
34
|
-
`elements` in `smoodly/elements.ts` and
|
|
35
|
-
in `smoodly/toolsets.ts` that may embed
|
|
36
|
-
|
|
37
|
+
Copy `components/elements/Button.schema.ts` (relative imports only) and
|
|
38
|
+
`Button.tsx`. Add the schema to `elements` in `smoodly/elements.ts` and
|
|
39
|
+
to the `elements` of the toolset in `smoodly/toolsets.ts` that may embed
|
|
40
|
+
it; add the component to `elements` in `smoodly/views.ts` and in
|
|
41
|
+
`smoodly/richtext.tsx`. It appears in the richtext editor's "/" menu.
|
|
37
42
|
|
|
38
43
|
## Add a collection
|
|
39
44
|
|
|
40
45
|
Copy the `posts` block in `smoodly/collections.ts`, add the new
|
|
41
46
|
collection to `collections`, and write its entry page by copying
|
|
42
|
-
`components/pages/Post.tsx` (
|
|
47
|
+
`components/pages/Post.tsx` (list it in `smoodly/views.ts` under `pages`).
|
|
43
48
|
Then write its read view and order index and apply them:
|
|
44
49
|
|
|
45
50
|
npx smoodly migrate
|
|
@@ -51,7 +56,7 @@ The same command brings the core schema forward after a `smoodly` upgrade.
|
|
|
51
56
|
|
|
52
57
|
Copy the `site` block in `smoodly/globals.ts` and add it to `globals`. An
|
|
53
58
|
object item (`fields`) is read in code with `q().getGlobal("name")`; a
|
|
54
|
-
visual item (`section:
|
|
59
|
+
visual item (`section: someSectionSchema`) renders through its section and can
|
|
55
60
|
be placed on pages from the picker's Global group. Edit both under
|
|
56
61
|
Globals in the admin.
|
|
57
62
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// The admin: its page, the package's files and the operations endpoint, all from this one route. The
|
|
2
|
+
// admin is prebuilt in the `smoodly` package; nothing of it is compiled into the site. The folder name
|
|
3
|
+
// must match `admin.path` in smoodly/config.ts.
|
|
4
|
+
import { createAdminRoute } from "smoodly/next";
|
|
5
|
+
import { config } from "@/smoodly/config";
|
|
6
|
+
import { adminDeps, presence, publicAuth } from "@/smoodly/server";
|
|
7
|
+
|
|
8
|
+
export const { GET, POST } = createAdminRoute(() => ({ config, ...adminDeps(), signIn: publicAuth(), presence }));
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { f, smoodly } from "smoodly";
|
|
2
|
+
|
|
3
|
+
// An Element: a small registered block editors insert inside richtext
|
|
4
|
+
// (the `richtext` context). This one is a link styled as a button;
|
|
5
|
+
// Button.tsx beside it is the component. To add another element, copy
|
|
6
|
+
// both files, list the schema in smoodly/elements.ts and in the toolsets
|
|
7
|
+
// that may embed it (smoodly/toolsets.ts), and the component in
|
|
8
|
+
// smoodly/views.ts and smoodly/richtext.tsx.
|
|
9
|
+
// Relative imports only in this file and in smoodly/toolsets.ts: the
|
|
10
|
+
// template build imports them outside the app, where `@/` has no mapping.
|
|
11
|
+
export const buttonSchema = smoodly.schema.element({
|
|
12
|
+
name: "button",
|
|
13
|
+
title: "Button",
|
|
14
|
+
icon: "→",
|
|
15
|
+
description: "A link styled as a button.",
|
|
16
|
+
contexts: ["richtext"],
|
|
17
|
+
fields: {
|
|
18
|
+
label: f.text().max(60),
|
|
19
|
+
href: f.link(),
|
|
20
|
+
},
|
|
21
|
+
sample: { label: "Read more", href: "/" },
|
|
22
|
+
});
|
|
@@ -1,23 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
// An Element: a small registered block editors insert inside richtext
|
|
4
|
-
// (the `richtext` context). This one is a link styled as a button. Copy
|
|
5
|
-
// this file to add another element, then list it in smoodly/elements.ts
|
|
6
|
-
// and in the toolsets that may embed it (smoodly/toolsets.ts).
|
|
7
|
-
// Relative imports only in this file and in smoodly/toolsets.ts: the
|
|
8
|
-
// template build imports them outside the app, where `@/` has no mapping.
|
|
9
|
-
export const buttonSchema = smoodly.schema.element({
|
|
10
|
-
name: "button",
|
|
11
|
-
title: "Button",
|
|
12
|
-
icon: "→",
|
|
13
|
-
description: "A link styled as a button.",
|
|
14
|
-
contexts: ["richtext"],
|
|
15
|
-
fields: {
|
|
16
|
-
label: f.text().max(60),
|
|
17
|
-
href: f.link(),
|
|
18
|
-
},
|
|
19
|
-
sample: { label: "Read more", href: "/" },
|
|
20
|
-
});
|
|
1
|
+
import { smoodly, type Props } from "smoodly/react";
|
|
2
|
+
import { buttonSchema } from "./Button.schema";
|
|
21
3
|
|
|
22
4
|
function ButtonView({ label, href }: Props<typeof buttonSchema>) {
|
|
23
5
|
return <a className="button" href={href}>{label}</a>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { smoodly, z } from "smoodly";
|
|
2
|
+
import { textSchema } from "../sections/Text.schema";
|
|
3
|
+
|
|
4
|
+
// A page type's schema: its zones and what each allows. Home.tsx beside
|
|
5
|
+
// it places them with <Zone />. `slug` makes it fixed — one record
|
|
6
|
+
// editors can neither delete nor duplicate — and the config's
|
|
7
|
+
// homePageSlug maps that record to "/". The body is a freeform zone over
|
|
8
|
+
// the section schemas listed here.
|
|
9
|
+
export const homeSchema = smoodly.schema.page({
|
|
10
|
+
name: "home",
|
|
11
|
+
title: "Home",
|
|
12
|
+
slug: "home",
|
|
13
|
+
zones: {
|
|
14
|
+
body: z.freeform({ sections: [textSchema], custom: true }),
|
|
15
|
+
},
|
|
16
|
+
seo: true,
|
|
17
|
+
});
|
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
import { smoodly,
|
|
2
|
-
import { Text } from "../sections/Text";
|
|
1
|
+
import { smoodly, Zone, type Props } from "smoodly/react";
|
|
3
2
|
import { LocaleNav } from "../LocaleNav";
|
|
4
|
-
|
|
5
|
-
// A page shape: zones declared, <Zone /> placed, one file. `slug` makes
|
|
6
|
-
// it fixed — one record editors can neither delete nor duplicate — and
|
|
7
|
-
// the config's homePageSlug maps that record to "/". The body is a
|
|
8
|
-
// freeform zone over the sections listed here.
|
|
9
|
-
export const homeSchema = smoodly.schema.page({
|
|
10
|
-
name: "home",
|
|
11
|
-
title: "Home",
|
|
12
|
-
slug: "home",
|
|
13
|
-
zones: {
|
|
14
|
-
body: z.freeform({ sections: [Text], custom: true }),
|
|
15
|
-
},
|
|
16
|
-
seo: true,
|
|
17
|
-
});
|
|
3
|
+
import { homeSchema } from "./Home.schema";
|
|
18
4
|
|
|
19
5
|
function HomeView({ zones, page }: Props<typeof homeSchema>) {
|
|
20
6
|
return (
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { smoodly, z } from "smoodly";
|
|
2
|
+
import { textSchema } from "../sections/Text.schema";
|
|
3
|
+
|
|
4
|
+
// An open page type: no `slug`, so editors create as many as they like,
|
|
5
|
+
// anywhere in the tree the config allows. Page.tsx beside it is the view;
|
|
6
|
+
// its `page` prop is where the page sits (title, path, ancestors, children).
|
|
7
|
+
export const pageSchema = smoodly.schema.page({
|
|
8
|
+
name: "page",
|
|
9
|
+
title: "Page",
|
|
10
|
+
zones: {
|
|
11
|
+
body: z.freeform({ sections: [textSchema], custom: true }),
|
|
12
|
+
},
|
|
13
|
+
seo: true,
|
|
14
|
+
});
|
|
@@ -1,18 +1,6 @@
|
|
|
1
|
-
import { smoodly,
|
|
2
|
-
import { Text } from "../sections/Text";
|
|
1
|
+
import { smoodly, Zone, type Props } from "smoodly/react";
|
|
3
2
|
import { LocaleNav } from "../LocaleNav";
|
|
4
|
-
|
|
5
|
-
// An open page shape: no `slug`, so editors create as many as they like,
|
|
6
|
-
// anywhere in the tree the config allows. `page` is where this one sits
|
|
7
|
-
// (title, path, ancestors, children).
|
|
8
|
-
export const pageSchema = smoodly.schema.page({
|
|
9
|
-
name: "page",
|
|
10
|
-
title: "Page",
|
|
11
|
-
zones: {
|
|
12
|
-
body: z.freeform({ sections: [Text], custom: true }),
|
|
13
|
-
},
|
|
14
|
-
seo: true,
|
|
15
|
-
});
|
|
3
|
+
import { pageSchema } from "./Page.schema";
|
|
16
4
|
|
|
17
5
|
function PageView({ zones, page }: Props<typeof pageSchema>) {
|
|
18
6
|
return (
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { smoodly } from "smoodly";
|
|
1
|
+
import { smoodly } from "smoodly/react";
|
|
2
2
|
import { RichText } from "@/smoodly/richtext";
|
|
3
3
|
import { posts } from "@/smoodly/collections";
|
|
4
4
|
import { LocaleNav } from "../LocaleNav";
|
|
5
5
|
|
|
6
|
-
// The entry page for `posts`, served at /posts/<slug>.
|
|
7
|
-
//
|
|
8
|
-
//
|
|
6
|
+
// The entry page for `posts`, served at /posts/<slug>. An entry page is a
|
|
7
|
+
// view with no schema of its own: it is listed in smoodly/views.ts, not in
|
|
8
|
+
// the config. It receives the entry's fields; the body is richtext rendered
|
|
9
|
+
// by the site's bound RichText, which knows the registered elements.
|
|
9
10
|
export const PostPage = smoodly.entryPage(posts, function PostView({ entry }) {
|
|
10
11
|
const { locale, locales } = entry;
|
|
11
12
|
const post = entry.fields;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { f, smoodly } from "smoodly";
|
|
2
|
+
import { text } from "@/smoodly/toolsets";
|
|
3
|
+
|
|
4
|
+
// A section's schema: a title and a richtext body. Text.tsx beside it is
|
|
5
|
+
// the component. To add another section, copy both files, list the
|
|
6
|
+
// schema in smoodly/sections.ts and the component in smoodly/views.ts,
|
|
7
|
+
// and allow the schema in a page type's zone (components/pages/*.schema.ts).
|
|
8
|
+
// This file imports no component.
|
|
9
|
+
export const textSchema = smoodly.schema.section({
|
|
10
|
+
name: "text",
|
|
11
|
+
title: "Text",
|
|
12
|
+
description: "A title and a body of text.",
|
|
13
|
+
fields: {
|
|
14
|
+
title: f.text(),
|
|
15
|
+
body: f.richtext({ toolset: text }),
|
|
16
|
+
},
|
|
17
|
+
settings: {
|
|
18
|
+
background: f.radio([{ value: "paper", label: "Paper" }, { value: "ink", label: "Ink" }]).default("paper"),
|
|
19
|
+
},
|
|
20
|
+
sample: {
|
|
21
|
+
title: "Hello",
|
|
22
|
+
body: { type: "doc", content: [{ type: "paragraph", content: [{ type: "text", text: "Write something here." }] }] },
|
|
23
|
+
},
|
|
24
|
+
});
|
|
@@ -1,32 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { smoodly, type Props } from "smoodly/react";
|
|
2
2
|
import { RichText } from "@/smoodly/richtext";
|
|
3
|
-
import {
|
|
3
|
+
import { textSchema } from "./Text.schema";
|
|
4
4
|
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// reads — here `background` — is the view's own data attribute.
|
|
11
|
-
export const textSchema = smoodly.schema.section({
|
|
12
|
-
name: "text",
|
|
13
|
-
title: "Text",
|
|
14
|
-
description: "A title and a body of text.",
|
|
15
|
-
fields: {
|
|
16
|
-
title: f.text(),
|
|
17
|
-
body: f.richtext({ toolset: text }),
|
|
18
|
-
},
|
|
19
|
-
settings: {
|
|
20
|
-
background: f.radio([{ value: "paper", label: "Paper" }, { value: "ink", label: "Ink" }]).default("paper"),
|
|
21
|
-
},
|
|
22
|
-
sample: {
|
|
23
|
-
title: "Hello",
|
|
24
|
-
body: { type: "doc", content: [{ type: "paragraph", content: [{ type: "text", text: "Write something here." }] }] },
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// Marks tie the rendered elements to their fields, so the editor can
|
|
29
|
-
// select and inline-edit them on the canvas.
|
|
5
|
+
// The section's component. The section wrapper renders the root element,
|
|
6
|
+
// Smoodly's styles set inline (spacing, width, align) and the node id; a
|
|
7
|
+
// setting the CSS reads — here `background` — is the view's own data
|
|
8
|
+
// attribute. Marks tie the rendered elements to their fields, so the
|
|
9
|
+
// editor can select and inline-edit them on the canvas.
|
|
30
10
|
const m = smoodly.marks(textSchema);
|
|
31
11
|
|
|
32
12
|
function TextView({ title, body, settings, styles }: Props<typeof textSchema>) {
|
|
@@ -14,7 +14,7 @@ loadEnvConfig(process.cwd());
|
|
|
14
14
|
|
|
15
15
|
const { config } = await import("../smoodly/config");
|
|
16
16
|
const { content, node } = await import("../smoodly/server");
|
|
17
|
-
const {
|
|
17
|
+
const { textSchema } = await import("../components/sections/Text.schema");
|
|
18
18
|
const c = content();
|
|
19
19
|
|
|
20
20
|
const DEFAULT = config.locales.default;
|
|
@@ -59,7 +59,7 @@ const tree: PageTree = {
|
|
|
59
59
|
meta: { description: "A new site, built with Smoodly." },
|
|
60
60
|
zones: {
|
|
61
61
|
body: [
|
|
62
|
-
node(
|
|
62
|
+
node(textSchema, {
|
|
63
63
|
title: "Hello",
|
|
64
64
|
body: doc(
|
|
65
65
|
p("This is your home page. Open the admin to edit this text, add sections, create pages and write posts."),
|
|
@@ -3,22 +3,23 @@ import { collections } from "./collections";
|
|
|
3
3
|
import { sections } from "./sections";
|
|
4
4
|
import { globals } from "./globals";
|
|
5
5
|
import { elements } from "./elements";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { PostPage } from "@/components/pages/Post";
|
|
6
|
+
import { homeSchema } from "@/components/pages/Home.schema";
|
|
7
|
+
import { pageSchema } from "@/components/pages/Page.schema";
|
|
9
8
|
|
|
10
9
|
export { collections, sections, globals, elements };
|
|
11
10
|
|
|
12
|
-
// The registry and the plain settings, one file.
|
|
13
|
-
//
|
|
14
|
-
//
|
|
11
|
+
// The registry of schemas and the plain settings, one file. It imports
|
|
12
|
+
// no component, no route file and no Next API, so a script and the CLI
|
|
13
|
+
// can load it outside the app; smoodly/views.ts lists the components
|
|
14
|
+
// that render these schemas.
|
|
15
15
|
export const config = defineConfig({
|
|
16
16
|
registry: {
|
|
17
17
|
sections,
|
|
18
18
|
elements,
|
|
19
19
|
collections,
|
|
20
20
|
globals,
|
|
21
|
-
|
|
21
|
+
// Page types. The entry page is a view: smoodly/views.ts lists it.
|
|
22
|
+
pages: [homeSchema, pageSchema],
|
|
22
23
|
},
|
|
23
24
|
locales: { default: "en", supported: ["en"] },
|
|
24
25
|
// The record the site root serves.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// The
|
|
2
|
-
//
|
|
3
|
-
import {
|
|
1
|
+
// The element schemas a richtext body may embed; smoodly/views.ts lists
|
|
2
|
+
// the components that render them.
|
|
3
|
+
import { buttonSchema } from "@/components/elements/Button.schema";
|
|
4
4
|
|
|
5
|
-
export const elements = [
|
|
5
|
+
export const elements = [buttonSchema];
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Global content: code-declared singletons, edited once under Globals
|
|
2
2
|
// and read anywhere. `site` is an object item — fields code consumes;
|
|
3
|
-
// the layout reads it through q().getGlobal("site")
|
|
4
|
-
//
|
|
3
|
+
// the layout reads it through q().getGlobal("site"), so it is a layout
|
|
4
|
+
// global: it comes with the page's own read. A visual item
|
|
5
|
+
// (`section: someSectionSchema`) renders through a section instead.
|
|
5
6
|
import { f, smoodly } from "smoodly";
|
|
6
7
|
|
|
7
8
|
export const site = smoodly.global({
|
|
@@ -11,6 +12,7 @@ export const site = smoodly.global({
|
|
|
11
12
|
name: f.text(),
|
|
12
13
|
tagline: f.text().localized(),
|
|
13
14
|
},
|
|
15
|
+
layout: true,
|
|
14
16
|
});
|
|
15
17
|
|
|
16
18
|
export const globals = [site];
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
// The site's
|
|
2
|
-
//
|
|
3
|
-
// entry pages import RichText from here, never from the package root.
|
|
1
|
+
// The site's bound RichText: the element components a body may embed,
|
|
2
|
+
// images through <SmoodlyImage>.
|
|
4
3
|
import { createRichText } from "smoodly/richtext";
|
|
5
|
-
import {
|
|
4
|
+
import { Button } from "@/components/elements/Button";
|
|
6
5
|
|
|
7
|
-
export const RichText = createRichText({ elements, sizes: "(min-width: 900px) 720px, 100vw" });
|
|
6
|
+
export const RichText = createRichText({ elements: [Button], sizes: "(min-width: 900px) 720px, 100vw" });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// The
|
|
2
|
-
//
|
|
3
|
-
import {
|
|
1
|
+
// The section schemas the config registers; smoodly/views.ts lists the
|
|
2
|
+
// components that render them.
|
|
3
|
+
import { textSchema } from "@/components/sections/Text.schema";
|
|
4
4
|
|
|
5
|
-
export const sections = [
|
|
5
|
+
export const sections = [textSchema];
|
|
@@ -5,22 +5,22 @@
|
|
|
5
5
|
// SMOODLY_PUBLISHABLE_KEY (the `smoodlyEnv("admin")` calls below); whether the
|
|
6
6
|
// secret is a service-role key or a cloud write key is invisible here.
|
|
7
7
|
//
|
|
8
|
-
// Lazy on purpose
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// config at module scope.
|
|
8
|
+
// Lazy on purpose: a page component imports this file to read through
|
|
9
|
+
// `q` (components/pages/Articles.tsx), and this file imports the
|
|
10
|
+
// components through ./views. That is a cycle, so nothing here reads
|
|
11
|
+
// views() or the env at module scope.
|
|
13
12
|
import {
|
|
14
|
-
createSmoodlyClient, createSmoodlySite,
|
|
13
|
+
createSmoodlyClient, createSmoodlySite, createSupabaseStores, presenceConfig, siteOptions, smoodlyEnv,
|
|
14
|
+
type PresenceConfig, type SmoodlySite, type SupabaseAssetStore, type SupabaseEntryStore, type SupabaseMemberStore, type SupabasePageStore,
|
|
15
15
|
} from "smoodly";
|
|
16
|
-
// The admin
|
|
17
|
-
//
|
|
18
|
-
// shell in every live page's JavaScript.
|
|
16
|
+
// The admin's server pieces: the sign-in check and the content API. No browser code lives in the package's
|
|
17
|
+
// entries; the admin itself is prebuilt and served by app/(smoodly)/admin/[[...segments]]/route.ts.
|
|
19
18
|
import { createSmoodlyContent, supabaseAdminAuth, type AdminAuth, type AuthConfig, type SmoodlyContent } from "smoodly/admin";
|
|
20
|
-
import { createPageRenderer, createSmoodlyQueries
|
|
19
|
+
import { createPageRenderer, createSmoodlyQueries } from "smoodly/next";
|
|
21
20
|
import { connection } from "next/server";
|
|
22
21
|
import type { SupabaseClient } from "@supabase/supabase-js";
|
|
23
|
-
import { collections, config,
|
|
22
|
+
import { collections, config, globals } from "./config";
|
|
23
|
+
import { views } from "./views";
|
|
24
24
|
|
|
25
25
|
type Renderer = ReturnType<typeof createPageRenderer>;
|
|
26
26
|
type Queries = ReturnType<typeof createSmoodlyQueries<typeof collections, typeof globals>>;
|
|
@@ -34,49 +34,27 @@ function bound(): Bound {
|
|
|
34
34
|
if (cached) return cached;
|
|
35
35
|
const env = smoodlyEnv();
|
|
36
36
|
const db = createSmoodlyClient(env);
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
const paths = new SupabasePathIndex(db, config.anchors);
|
|
40
|
-
const locales = config.locales;
|
|
41
|
-
const entries = new SupabaseEntryStore(db, collections, { paths, locales, globals, elements });
|
|
42
|
-
const pages = new SupabasePageStore(db, {
|
|
43
|
-
sections, elements, entries, paths, locales,
|
|
44
|
-
// The custom section's columns toolset, so a column's images count as usage (spec 2026-09-14 §6).
|
|
45
|
-
custom: config.custom,
|
|
46
|
-
homePageSlug: config.homePageSlug,
|
|
47
|
-
// Code-owned addresses by owner: a fixed page's or a collection's path (spec 2026-09-29 nested paths §3).
|
|
48
|
-
addresses: config.addresses,
|
|
49
|
-
tree: config.pages?.tree,
|
|
50
|
-
});
|
|
51
|
-
// The media library: rows in `assets`, bytes in the public `media` bucket.
|
|
52
|
-
const assets = new SupabaseAssetStore(db);
|
|
53
|
-
// The admission table, read by the Members page (spec 2026-09-25 §4).
|
|
54
|
-
const members = new SupabaseMemberStore(db);
|
|
37
|
+
// The stores, read off the config: pages, entries, the media library and the admission table.
|
|
38
|
+
const { pages, entries, assets, members, published } = createSupabaseStores(db, config);
|
|
55
39
|
const auth = supabaseAdminAuth({ authUrl: env.authUrl, authKey: env.authKey, db });
|
|
56
|
-
// The site layer's own view of the stores; nothing outside this file reads them.
|
|
57
|
-
const stores = () => ({ pages, entries, assets });
|
|
58
40
|
// The site layer: (locale, path) → page or entry, and the content API
|
|
59
41
|
// `q` wraps below. Not exported — the app reads through `q`, which adds
|
|
60
42
|
// draft awareness and the cache.
|
|
61
|
-
const site = createSmoodlySite(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
sections,
|
|
65
|
-
elements,
|
|
66
|
-
pages: (config.registry.pages ?? []) as PageRegistration[],
|
|
67
|
-
href,
|
|
68
|
-
});
|
|
43
|
+
const site = createSmoodlySite(siteOptions(config, () => ({ pages, entries, assets, published })));
|
|
44
|
+
// The components, checked against the config's schemas here, on first use.
|
|
45
|
+
const renderer = createPageRenderer({ site, ...views(), href });
|
|
69
46
|
// The read API (spec 2026-09-11): typed by the registry, draft-aware, cached under tags the admin expires.
|
|
70
47
|
const q = createSmoodlyQueries({ site, collections, globals });
|
|
71
48
|
cached = { db, pages, entries, assets, members, auth, site, renderer, q };
|
|
72
49
|
return cached;
|
|
73
50
|
}
|
|
74
51
|
|
|
75
|
-
/** The admin's wiring, for
|
|
52
|
+
/** The admin's wiring, for the admin route only. Scripts write through `content()`. */
|
|
76
53
|
export function adminDeps() {
|
|
77
54
|
smoodlyEnv("admin"); // the admin signs in with the publishable key: a missing one is named here, not on a live page
|
|
78
|
-
const { pages, entries, assets, members, auth } = bound();
|
|
79
|
-
|
|
55
|
+
const { pages, entries, assets, members, auth, site } = bound();
|
|
56
|
+
// The projector: a publish writes the finished documents a live page reads.
|
|
57
|
+
return { pages, entries, assets, members, auth, href, projector: site.projector };
|
|
80
58
|
}
|
|
81
59
|
|
|
82
60
|
/** Write content from code — seeds, migrations, route handlers (spec 2026-09-30 tester findings §1).
|
|
@@ -84,8 +62,8 @@ export function adminDeps() {
|
|
|
84
62
|
* throws `SmoodlyContentError`. `content().pages.create(…)`, `.entries.create(…)`, `.globals.set(…)`,
|
|
85
63
|
* `.media.upload(…)`; build tree nodes with `node(Section, fields)`. */
|
|
86
64
|
export function content(): SmoodlyContent {
|
|
87
|
-
const { pages, entries, assets, members } = bound();
|
|
88
|
-
return createSmoodlyContent({ config, pages, entries, assets, members, href });
|
|
65
|
+
const { pages, entries, assets, members, site } = bound();
|
|
66
|
+
return createSmoodlyContent({ config, pages, entries, assets, members, href, projector: site.projector });
|
|
89
67
|
}
|
|
90
68
|
|
|
91
69
|
export { node } from "smoodly";
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
// Relative imports on purpose: collections.ts pulls this file into
|
|
6
6
|
// create-smoodly-app's template build, which runs outside the app.
|
|
7
7
|
import { smoodly } from "smoodly";
|
|
8
|
-
import {
|
|
8
|
+
import { buttonSchema } from "../components/elements/Button.schema";
|
|
9
9
|
|
|
10
10
|
export const text = smoodly.toolset({
|
|
11
11
|
marks: ["bold", "italic", "link"],
|
|
12
12
|
nodes: ["h2", "h3", "bulletList", "orderedList", "blockquote"],
|
|
13
|
-
elements: [
|
|
13
|
+
elements: [buttonSchema],
|
|
14
14
|
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// The components that render the registered schemas. A function, not a
|
|
2
|
+
// value: a page component may import smoodly/server.ts, which imports
|
|
3
|
+
// this file. defineViews names a schema with no component, and a
|
|
4
|
+
// component with no schema, the first time the site renders.
|
|
5
|
+
import { defineViews } from "smoodly/react";
|
|
6
|
+
import { config } from "./config";
|
|
7
|
+
import { RichText } from "./richtext";
|
|
8
|
+
import { Text } from "@/components/sections/Text";
|
|
9
|
+
import { Button } from "@/components/elements/Button";
|
|
10
|
+
import { HomePage } from "@/components/pages/Home";
|
|
11
|
+
import { StandardPage } from "@/components/pages/Page";
|
|
12
|
+
import { PostPage } from "@/components/pages/Post";
|
|
13
|
+
|
|
14
|
+
export const views = () =>
|
|
15
|
+
defineViews(config, { sections: [Text], elements: [Button], pages: [HomePage, StandardPage, PostPage], RichText });
|