create-smoodly-app 0.0.45 → 0.0.47
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/astro-blank/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/{blank/supabase/migrations/20260930041056_smoodly_views.sql → astro-blank/supabase/migrations/20261008120100_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/astro-blank-intl/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/{blank-intl/supabase/migrations/20260930041056_smoodly_views.sql → astro-blank-intl/supabase/migrations/20261008120100_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 +32 -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/astro-lorem/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/{lorem/supabase/migrations/20260930041056_smoodly_views.sql → astro-lorem/supabase/migrations/20261008120100_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 +32 -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/astro-lorem-intl/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/{lorem-intl/supabase/migrations/20260930041056_smoodly_views.sql → astro-lorem-intl/supabase/migrations/20261008120100_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/20261008120000_smoodly_v10.sql +47 -0
- package/templates/blank/supabase/migrations/20261008120100_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/20261008120000_smoodly_v10.sql +47 -0
- package/templates/blank-intl/supabase/migrations/20261008120100_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/20261008120000_smoodly_v10.sql +47 -0
- package/templates/lorem/supabase/migrations/20261008120100_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/20261008120000_smoodly_v10.sql +47 -0
- package/templates/lorem-intl/supabase/migrations/20261008120100_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
|
@@ -10,15 +10,15 @@ 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: fonts, `app/globals.css`, the footer from global content
|
|
13
|
+
- `app/(site)/layout.tsx` — the site's root layout: fonts, `app/globals.css`, the footer from global content. 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` (locked hero, freeform body), `Articles` (a fixed page at the collection's path — its index — with a code-fetched grid), `Page` (open; About lives here), `Article` (the entry page), `News` and `NewsPost` (a collection at the nested address `company/news`, its index and entry page).
|
|
15
15
|
- `components/PageFrame.tsx` — the header and `<main>` every page view renders (a layout cannot know which page is on screen); with more than one locale, the language links from the page's `locales` map — the same page in the other language, or its home when there is no translation.
|
|
16
|
-
- `components/sections/` — the building blocks editors compose with, and the header, footer and quote behind the global items. Add one, list
|
|
16
|
+
- `components/sections/` — the building blocks editors compose with, and the header, footer and quote behind the global items. Each is two files: `Name.schema.ts` (the schema) and `Name.tsx` (the component). Add one, list its schema in `smoodly/sections.ts` and its component in `smoodly/views.ts`.
|
|
17
17
|
- `components/strings.ts`, `messages/` — the site's own UI strings and the request locale, one seam.
|
|
18
18
|
- `public/images/` — the starter's photos; image fields hold URLs like `/images/hero_image.jpg`.
|
|
19
19
|
- `scripts/seed.ts` — the starter content, written through the content API (`content()`). `npm run seed` is idempotent.
|
|
20
20
|
- `smoodly/collections.ts` — structured content (people, articles, news). Add a collection, run `npx smoodly migrate`, apply the file it writes.
|
|
21
|
-
- `smoodly/` — the wiring: `config.ts` (the registry and settings), `collections.ts`, `sections.ts
|
|
21
|
+
- `smoodly/` — the wiring: `config.ts` (the registry of schemas and the settings; it imports no component), `collections.ts`, `sections.ts` and `elements.ts` (the schemas the config registers), `views.ts` (the components that render them), `server.ts` (site layer, renderer, the content API `content()`).
|
|
22
22
|
- `.env.local` — `SMOODLY_URL`, `SMOODLY_SECRET_KEY`, `SMOODLY_PUBLISHABLE_KEY`.
|
|
23
23
|
|
|
24
24
|
## What is in the starter
|
|
@@ -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,24 @@
|
|
|
1
|
+
import { f, smoodly } from "smoodly";
|
|
2
|
+
|
|
3
|
+
// An Element: a small registered block editors insert inside an article
|
|
4
|
+
// body (the `richtext` context). Its body is richtext too — marks only —
|
|
5
|
+
// rendered by the package's pure RichText (a schema file imports no view:
|
|
6
|
+
// the view imports this file, and an import back would cycle).
|
|
7
|
+
export const calloutSchema = smoodly.schema.element({
|
|
8
|
+
name: "callout",
|
|
9
|
+
title: "Callout",
|
|
10
|
+
icon: "!",
|
|
11
|
+
description: "A highlighted note inside the text.",
|
|
12
|
+
contexts: ["richtext"],
|
|
13
|
+
fields: {
|
|
14
|
+
title: f.text().max(80),
|
|
15
|
+
body: f.richtext({ toolset: smoodly.toolset({ marks: ["bold", "italic", "link"] }) }),
|
|
16
|
+
},
|
|
17
|
+
settings: {
|
|
18
|
+
tone: f.select([{ value: "info", label: "Info" }, { value: "success", label: "Success" }, { value: "warning", label: "Warning" }]).default("info"),
|
|
19
|
+
},
|
|
20
|
+
sample: {
|
|
21
|
+
title: "Good to know",
|
|
22
|
+
body: { type: "doc", content: [{ type: "paragraph", content: [{ type: "text", text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }] }] },
|
|
23
|
+
},
|
|
24
|
+
});
|
|
@@ -1,27 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
// An Element: a small registered block editors insert inside an article
|
|
4
|
-
// body (the `richtext` context). Its body is richtext too — marks only —
|
|
5
|
-
// rendered by the package's pure RichText (never the project's bound one:
|
|
6
|
-
// smoodly/richtext.tsx imports this file, and an import back would cycle).
|
|
7
|
-
export const calloutSchema = smoodly.schema.element({
|
|
8
|
-
name: "callout",
|
|
9
|
-
title: "Callout",
|
|
10
|
-
icon: "!",
|
|
11
|
-
description: "A highlighted note inside the text.",
|
|
12
|
-
contexts: ["richtext"],
|
|
13
|
-
fields: {
|
|
14
|
-
title: f.text().max(80),
|
|
15
|
-
body: f.richtext({ toolset: smoodly.toolset({ marks: ["bold", "italic", "link"] }) }),
|
|
16
|
-
},
|
|
17
|
-
settings: {
|
|
18
|
-
tone: f.select([{ value: "info", label: "Info" }, { value: "success", label: "Success" }, { value: "warning", label: "Warning" }]).default("info"),
|
|
19
|
-
},
|
|
20
|
-
sample: {
|
|
21
|
-
title: "Good to know",
|
|
22
|
-
body: { type: "doc", content: [{ type: "paragraph", content: [{ type: "text", text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }] }] },
|
|
23
|
-
},
|
|
24
|
-
});
|
|
1
|
+
import { RichText, smoodly, type Props } from "smoodly/react";
|
|
2
|
+
import { calloutSchema } from "./Callout.schema";
|
|
25
3
|
|
|
26
4
|
function CalloutView({ title, body, settings }: Props<typeof calloutSchema>) {
|
|
27
5
|
return (
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { f, smoodly } from "smoodly";
|
|
2
|
+
|
|
3
|
+
// A call to action inside an article body: heading, a line of text and
|
|
4
|
+
// one button. `variant` is a style — never translated.
|
|
5
|
+
export const ctaSchema = smoodly.schema.element({
|
|
6
|
+
name: "cta",
|
|
7
|
+
title: "Call to action",
|
|
8
|
+
icon: "→",
|
|
9
|
+
description: "A heading, a line and a button.",
|
|
10
|
+
contexts: ["richtext"],
|
|
11
|
+
fields: {
|
|
12
|
+
heading: f.text().max(80),
|
|
13
|
+
text: f.text().max(200).optional(),
|
|
14
|
+
label: f.text().max(40),
|
|
15
|
+
href: f.link(),
|
|
16
|
+
},
|
|
17
|
+
settings: {
|
|
18
|
+
variant: f.select([{ value: "primary", label: "Primary" }, { value: "outline", label: "Outline" }]).default("primary"),
|
|
19
|
+
},
|
|
20
|
+
sample: { heading: "Ready to start?", text: "Sed ut perspiciatis unde omnis iste natus.", label: "Get in touch", href: "/company/about-us" },
|
|
21
|
+
});
|
|
@@ -1,24 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
// A call to action inside an article body: heading, a line of text and
|
|
4
|
-
// one button. `variant` is a style — never translated.
|
|
5
|
-
export const ctaSchema = smoodly.schema.element({
|
|
6
|
-
name: "cta",
|
|
7
|
-
title: "Call to action",
|
|
8
|
-
icon: "→",
|
|
9
|
-
description: "A heading, a line and a button.",
|
|
10
|
-
contexts: ["richtext"],
|
|
11
|
-
fields: {
|
|
12
|
-
heading: f.text().max(80),
|
|
13
|
-
text: f.text().max(200).optional(),
|
|
14
|
-
label: f.text().max(40),
|
|
15
|
-
href: f.link(),
|
|
16
|
-
},
|
|
17
|
-
settings: {
|
|
18
|
-
variant: f.select([{ value: "primary", label: "Primary" }, { value: "outline", label: "Outline" }]).default("primary"),
|
|
19
|
-
},
|
|
20
|
-
sample: { heading: "Ready to start?", text: "Sed ut perspiciatis unde omnis iste natus.", label: "Get in touch", href: "/company/about-us" },
|
|
21
|
-
});
|
|
1
|
+
import { smoodly, type Props } from "smoodly/react";
|
|
2
|
+
import { ctaSchema } from "./Cta.schema";
|
|
22
3
|
|
|
23
4
|
function CtaView({ heading, text, label, href, settings }: Props<typeof ctaSchema>) {
|
|
24
5
|
return (
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { smoodly, z } from "smoodly";
|
|
2
|
+
import { pageHeroSchema } from "../sections/PageHero.schema";
|
|
3
|
+
|
|
4
|
+
// The Articles index: a fixed page whose slugs are the collection's own
|
|
5
|
+
// segments (smoodly/collections.ts), which makes it the collection's
|
|
6
|
+
// index page — the mount in the Pages list opens this page's editor. The
|
|
7
|
+
// editor owns the hero; the grid below is developer JSX that reads the
|
|
8
|
+
// articles through `q`, newest first (the collection's `order`), cached
|
|
9
|
+
// under the collection's tag. In the editor canvas the site runs in draft
|
|
10
|
+
// mode, so the grid reads the live rows too: an unpublished article shows
|
|
11
|
+
// there as it will (spec 2026-09-11 §2).
|
|
12
|
+
export const articlesSchema = smoodly.schema.page({
|
|
13
|
+
name: "articlesIndex",
|
|
14
|
+
title: "Articles",
|
|
15
|
+
slug: "posts",
|
|
16
|
+
zones: {
|
|
17
|
+
hero: z.locked(pageHeroSchema),
|
|
18
|
+
},
|
|
19
|
+
seo: true,
|
|
20
|
+
});
|
|
@@ -1,27 +1,9 @@
|
|
|
1
|
-
import { smoodly,
|
|
2
|
-
import { PageHero } from "../sections/PageHero";
|
|
1
|
+
import { smoodly, Zone, type Props } from "smoodly/react";
|
|
3
2
|
import { ArticleCard } from "../ArticleCard";
|
|
4
3
|
import { PageFrame } from "../PageFrame";
|
|
5
4
|
import { ui } from "../strings";
|
|
6
5
|
import { q } from "@/smoodly/server";
|
|
7
|
-
|
|
8
|
-
// The Articles index: a fixed page whose slugs are the collection's own
|
|
9
|
-
// segments (smoodly/collections.ts), which makes it the collection's
|
|
10
|
-
// index page — the mount in the Pages list opens this page's editor. The
|
|
11
|
-
// editor owns the hero; the grid below is developer JSX that reads the
|
|
12
|
-
// articles through `q`, newest first (the collection's `order`), cached
|
|
13
|
-
// under the collection's tag. In the editor canvas the site runs in draft
|
|
14
|
-
// mode, so the grid reads the live rows too: an unpublished article shows
|
|
15
|
-
// there as it will (spec 2026-09-11 §2).
|
|
16
|
-
export const articlesSchema = smoodly.schema.page({
|
|
17
|
-
name: "articlesIndex",
|
|
18
|
-
title: "Articles",
|
|
19
|
-
slug: "posts",
|
|
20
|
-
zones: {
|
|
21
|
-
hero: z.locked(PageHero),
|
|
22
|
-
},
|
|
23
|
-
seo: true,
|
|
24
|
-
});
|
|
6
|
+
import { articlesSchema } from "./Articles.schema";
|
|
25
7
|
|
|
26
8
|
async function ArticlesView({ zones, page }: Props<typeof articlesSchema>) {
|
|
27
9
|
const { locale, url } = await ui();
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { smoodly, z } from "smoodly";
|
|
2
|
+
import { heroSchema } from "../sections/Hero.schema";
|
|
3
|
+
import { imageTextSchema } from "../sections/ImageText.schema";
|
|
4
|
+
import { pointsSchema } from "../sections/Points.schema";
|
|
5
|
+
import { favouriteArticlesSchema } from "../sections/FavouriteArticles.schema";
|
|
6
|
+
import { peopleSchema } from "../sections/People.schema";
|
|
7
|
+
import { quoteSchema } from "../sections/Quote.schema";
|
|
8
|
+
|
|
9
|
+
// A page type: zones declared here, placed by the page type's view (DESIGN.md §3).
|
|
10
|
+
// `slug` makes it fixed — one record the editor can neither delete nor
|
|
11
|
+
// duplicate — and the config's homePageSlug maps that record to "/".
|
|
12
|
+
// The hero is locked: fields only, never added, moved or removed. The
|
|
13
|
+
// body is freeform over five sections. Quote is among them because the
|
|
14
|
+
// picker offers a global item only where the zone allows its section: an
|
|
15
|
+
// editor may drop a one-off quote, or place the global one from the
|
|
16
|
+
// picker's Global group.
|
|
17
|
+
export const homeSchema = smoodly.schema.page({
|
|
18
|
+
name: "home",
|
|
19
|
+
title: "Home",
|
|
20
|
+
slug: "home",
|
|
21
|
+
zones: {
|
|
22
|
+
hero: z.locked(heroSchema),
|
|
23
|
+
body: z.freeform({ sections: [imageTextSchema, pointsSchema, favouriteArticlesSchema, peopleSchema, quoteSchema], custom: true }),
|
|
24
|
+
},
|
|
25
|
+
seo: true,
|
|
26
|
+
});
|
|
@@ -1,30 +1,6 @@
|
|
|
1
|
-
import { smoodly,
|
|
2
|
-
import { Hero } from "../sections/Hero";
|
|
3
|
-
import { ImageText } from "../sections/ImageText";
|
|
4
|
-
import { Points } from "../sections/Points";
|
|
5
|
-
import { FavouriteArticles } from "../sections/FavouriteArticles";
|
|
6
|
-
import { People } from "../sections/People";
|
|
7
|
-
import { Quote } from "../sections/Quote";
|
|
1
|
+
import { smoodly, Zone, type Props } from "smoodly/react";
|
|
8
2
|
import { PageFrame } from "../PageFrame";
|
|
9
|
-
|
|
10
|
-
// A page shape: zones declared, <Zone /> placed, one file (DESIGN.md §3).
|
|
11
|
-
// `slug` makes it fixed — one record the editor can neither delete nor
|
|
12
|
-
// duplicate — and the config's homePageSlug maps that record to "/".
|
|
13
|
-
// The hero is locked: fields only, never added, moved or removed. The
|
|
14
|
-
// body is freeform over five sections. Quote is among them because the
|
|
15
|
-
// picker offers a global item only where the zone allows its section: an
|
|
16
|
-
// editor may drop a one-off quote, or place the global one from the
|
|
17
|
-
// picker's Global group.
|
|
18
|
-
export const homeSchema = smoodly.schema.page({
|
|
19
|
-
name: "home",
|
|
20
|
-
title: "Home",
|
|
21
|
-
slug: "home",
|
|
22
|
-
zones: {
|
|
23
|
-
hero: z.locked(Hero),
|
|
24
|
-
body: z.freeform({ sections: [ImageText, Points, FavouriteArticles, People, Quote], custom: true }),
|
|
25
|
-
},
|
|
26
|
-
seo: true,
|
|
27
|
-
});
|
|
3
|
+
import { homeSchema } from "./Home.schema";
|
|
28
4
|
|
|
29
5
|
function HomeView({ zones, page }: Props<typeof homeSchema>) {
|
|
30
6
|
return (
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { smoodly, z } from "smoodly";
|
|
2
|
+
import { pageHeroSchema } from "../sections/PageHero.schema";
|
|
3
|
+
|
|
4
|
+
// The News index: a fixed page on the news collection's own nested
|
|
5
|
+
// address (smoodly/collections.ts), so it is the collection's index page.
|
|
6
|
+
// Code owns /company/news whole: the Company page above it is an
|
|
7
|
+
// editor's, and renaming it leaves the news where it is. The editor owns
|
|
8
|
+
// the hero; the list below reads the posts through `q`, newest first.
|
|
9
|
+
export const newsSchema = smoodly.schema.page({
|
|
10
|
+
name: "newsIndex",
|
|
11
|
+
title: "News",
|
|
12
|
+
slug: "company/news",
|
|
13
|
+
zones: {
|
|
14
|
+
hero: z.locked(pageHeroSchema),
|
|
15
|
+
},
|
|
16
|
+
seo: true,
|
|
17
|
+
});
|
|
@@ -1,24 +1,9 @@
|
|
|
1
|
-
import { smoodly,
|
|
2
|
-
import { PageHero } from "../sections/PageHero";
|
|
1
|
+
import { smoodly, Zone, type Props } from "smoodly/react";
|
|
3
2
|
import { PageFrame } from "../PageFrame";
|
|
4
3
|
import { formatDate } from "../articles";
|
|
5
4
|
import { ui } from "../strings";
|
|
6
5
|
import { q } from "@/smoodly/server";
|
|
7
|
-
|
|
8
|
-
// The News index: a fixed page on the news collection's own nested
|
|
9
|
-
// address (smoodly/collections.ts), so it is the collection's index page.
|
|
10
|
-
// Code owns /company/news whole: the Company page above it is an
|
|
11
|
-
// editor's, and renaming it leaves the news where it is. The editor owns
|
|
12
|
-
// the hero; the list below reads the posts through `q`, newest first.
|
|
13
|
-
export const newsSchema = smoodly.schema.page({
|
|
14
|
-
name: "newsIndex",
|
|
15
|
-
title: "News",
|
|
16
|
-
slug: "company/news",
|
|
17
|
-
zones: {
|
|
18
|
-
hero: z.locked(PageHero),
|
|
19
|
-
},
|
|
20
|
-
seo: true,
|
|
21
|
-
});
|
|
6
|
+
import { newsSchema } from "./News.schema";
|
|
22
7
|
|
|
23
8
|
async function NewsView({ zones, page }: Props<typeof newsSchema>) {
|
|
24
9
|
const { locale, url } = await ui();
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { f, smoodly, z } from "smoodly";
|
|
2
|
+
import { pageHeroSchema } from "../sections/PageHero.schema";
|
|
3
|
+
import { imageTextSchema } from "../sections/ImageText.schema";
|
|
4
|
+
import { pointsSchema } from "../sections/Points.schema";
|
|
5
|
+
import { favouriteArticlesSchema } from "../sections/FavouriteArticles.schema";
|
|
6
|
+
import { peopleSchema } from "../sections/People.schema";
|
|
7
|
+
import { quoteSchema } from "../sections/Quote.schema";
|
|
8
|
+
|
|
9
|
+
// Open registration: editors create as many of these as they like, at
|
|
10
|
+
// any depth the config allows. `page` is where this one sits in the tree.
|
|
11
|
+
// Its locked hero is the page hero, not the home one: each shape locks
|
|
12
|
+
// its own.
|
|
13
|
+
export const pageSchema = smoodly.schema.page({
|
|
14
|
+
name: "page",
|
|
15
|
+
title: "Page",
|
|
16
|
+
zones: {
|
|
17
|
+
hero: z.locked(pageHeroSchema),
|
|
18
|
+
body: z.freeform({ sections: [imageTextSchema, pointsSchema, favouriteArticlesSchema, peopleSchema, quoteSchema], custom: true }),
|
|
19
|
+
},
|
|
20
|
+
seo: true,
|
|
21
|
+
// A page field (spec 2026-09-10 page fields §7): the parent's view lists
|
|
22
|
+
// the children that keep this on. Edited on the Settings tab.
|
|
23
|
+
fields: { showInNavigation: f.boolean().default(true) },
|
|
24
|
+
});
|
|
@@ -1,29 +1,7 @@
|
|
|
1
1
|
import Link from "next/link";
|
|
2
|
-
import {
|
|
3
|
-
import { PageHero } from "../sections/PageHero";
|
|
4
|
-
import { ImageText } from "../sections/ImageText";
|
|
5
|
-
import { Points } from "../sections/Points";
|
|
6
|
-
import { FavouriteArticles } from "../sections/FavouriteArticles";
|
|
7
|
-
import { People } from "../sections/People";
|
|
8
|
-
import { Quote } from "../sections/Quote";
|
|
2
|
+
import { smoodly, Zone, type Props } from "smoodly/react";
|
|
9
3
|
import { PageFrame } from "../PageFrame";
|
|
10
|
-
|
|
11
|
-
// Open registration: editors create as many of these as they like, at
|
|
12
|
-
// any depth the config allows. `page` is where this one sits in the tree.
|
|
13
|
-
// Its locked hero is the page hero, not the home one: each shape locks
|
|
14
|
-
// its own.
|
|
15
|
-
export const pageSchema = smoodly.schema.page({
|
|
16
|
-
name: "page",
|
|
17
|
-
title: "Page",
|
|
18
|
-
zones: {
|
|
19
|
-
hero: z.locked(PageHero),
|
|
20
|
-
body: z.freeform({ sections: [ImageText, Points, FavouriteArticles, People, Quote], custom: true }),
|
|
21
|
-
},
|
|
22
|
-
seo: true,
|
|
23
|
-
// A page field (spec 2026-09-10 page fields §7): the parent's view lists
|
|
24
|
-
// the children that keep this on. Edited on the Settings tab.
|
|
25
|
-
fields: { showInNavigation: f.boolean().default(true) },
|
|
26
|
-
});
|
|
4
|
+
import { pageSchema } from "./Page.schema";
|
|
27
5
|
|
|
28
6
|
function PageView({ zones, page }: Props<typeof pageSchema>) {
|
|
29
7
|
// Sub-navigation: the published children that opted in through their page field.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { f, smoodly } from "smoodly";
|
|
2
|
+
import { articles } from "@/smoodly/collections";
|
|
3
|
+
|
|
4
|
+
// Articles an editor picks by hand (refList), as cards. The resolve pass
|
|
5
|
+
// hydrates each ref before render, so the view gets article fields, not
|
|
6
|
+
// ids; an article unpublished after this page went live resolves to
|
|
7
|
+
// null and is skipped.
|
|
8
|
+
export const favouriteArticlesSchema = smoodly.schema.section({
|
|
9
|
+
name: "favouriteArticles",
|
|
10
|
+
title: "Favourite articles",
|
|
11
|
+
description: "Articles picked by hand, as cards.",
|
|
12
|
+
fields: {
|
|
13
|
+
heading: f.text(),
|
|
14
|
+
items: f.refList(() => articles).max(6),
|
|
15
|
+
},
|
|
16
|
+
sample: { heading: "From the journal", items: [] },
|
|
17
|
+
});
|
|
@@ -1,22 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { articles } from "@/smoodly/collections";
|
|
1
|
+
import { smoodly, type Props } from "smoodly/react";
|
|
3
2
|
import { ArticleCard } from "@/components/ArticleCard";
|
|
4
3
|
import { ui } from "@/components/strings";
|
|
5
|
-
|
|
6
|
-
// Articles an editor picks by hand (refList), as cards. The resolve pass
|
|
7
|
-
// hydrates each ref before render, so the view gets article fields, not
|
|
8
|
-
// ids; an article unpublished after this page went live resolves to
|
|
9
|
-
// null and is skipped.
|
|
10
|
-
export const favouriteArticlesSchema = smoodly.schema.section({
|
|
11
|
-
name: "favouriteArticles",
|
|
12
|
-
title: "Favourite articles",
|
|
13
|
-
description: "Articles picked by hand, as cards.",
|
|
14
|
-
fields: {
|
|
15
|
-
heading: f.text(),
|
|
16
|
-
items: f.refList(() => articles).max(6),
|
|
17
|
-
},
|
|
18
|
-
sample: { heading: "From the journal", items: [] },
|
|
19
|
-
});
|
|
4
|
+
import { favouriteArticlesSchema } from "./FavouriteArticles.schema";
|
|
20
5
|
|
|
21
6
|
const m = smoodly.marks(favouriteArticlesSchema);
|
|
22
7
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { f, smoodly } from "smoodly";
|
|
2
|
+
|
|
3
|
+
// The site footer — a VISUAL global item (smoodly/globals.ts): one row,
|
|
4
|
+
// edited under Global content, rendered by the layout. Three link columns
|
|
5
|
+
// as top-level objects, each localized as a whole (an object holding a
|
|
6
|
+
// list — one level, which the list field allows; a list of columns each
|
|
7
|
+
// holding a list would be a nested list, which it refuses).
|
|
8
|
+
const column = () =>
|
|
9
|
+
f.object({ title: f.text(), links: f.list(f.object({ label: f.text(), href: f.link() })) }).localized();
|
|
10
|
+
|
|
11
|
+
export const footerSchema = smoodly.schema.section({
|
|
12
|
+
name: "footer",
|
|
13
|
+
title: "Footer",
|
|
14
|
+
description: "The site footer: tagline, three link columns, copyright.",
|
|
15
|
+
fields: {
|
|
16
|
+
tagline: f.text().localized(),
|
|
17
|
+
company: column(),
|
|
18
|
+
legal: column(),
|
|
19
|
+
social: column(),
|
|
20
|
+
copyright: f.text(),
|
|
21
|
+
},
|
|
22
|
+
sample: {
|
|
23
|
+
tagline: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
|
24
|
+
company: { title: "Company", links: [{ label: "About", href: "/company/about-us" }] },
|
|
25
|
+
legal: { title: "Legal", links: [{ label: "Privacy", href: "#" }] },
|
|
26
|
+
social: { title: "Social", links: [{ label: "Instagram", href: "#" }] },
|
|
27
|
+
copyright: "© 2026 Lorem Co. Built with Smoodly.",
|
|
28
|
+
},
|
|
29
|
+
// The layout's footer keeps the design's spacing: no Spacing & layout group.
|
|
30
|
+
styles: false,
|
|
31
|
+
});
|
|
@@ -1,36 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { smoodly, type Props, type Scope } from "smoodly/react";
|
|
2
|
+
import { footerSchema } from "./Footer.schema";
|
|
2
3
|
|
|
3
|
-
// The site footer
|
|
4
|
-
//
|
|
5
|
-
// as top-level objects, each localized as a whole (an object holding a
|
|
6
|
-
// list — one level, which the list field allows; a list of columns each
|
|
7
|
-
// holding a list would be a nested list, which it refuses). The layout
|
|
8
|
-
// renders FooterView directly to hand it the contact object item, which
|
|
9
|
-
// is not a footer field.
|
|
10
|
-
const column = () =>
|
|
11
|
-
f.object({ title: f.text(), links: f.list(f.object({ label: f.text(), href: f.link() })) }).localized();
|
|
12
|
-
|
|
13
|
-
export const footerSchema = smoodly.schema.section({
|
|
14
|
-
name: "footer",
|
|
15
|
-
title: "Footer",
|
|
16
|
-
description: "The site footer: tagline, three link columns, copyright.",
|
|
17
|
-
fields: {
|
|
18
|
-
tagline: f.text().localized(),
|
|
19
|
-
company: column(),
|
|
20
|
-
legal: column(),
|
|
21
|
-
social: column(),
|
|
22
|
-
copyright: f.text(),
|
|
23
|
-
},
|
|
24
|
-
sample: {
|
|
25
|
-
tagline: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
|
26
|
-
company: { title: "Company", links: [{ label: "About", href: "/company/about-us" }] },
|
|
27
|
-
legal: { title: "Legal", links: [{ label: "Privacy", href: "#" }] },
|
|
28
|
-
social: { title: "Social", links: [{ label: "Instagram", href: "#" }] },
|
|
29
|
-
copyright: "© 2026 Lorem Co. Built with Smoodly.",
|
|
30
|
-
},
|
|
31
|
-
// The layout's footer keeps the design's spacing: no Spacing & layout group.
|
|
32
|
-
styles: false,
|
|
33
|
-
});
|
|
4
|
+
// The site footer's view. The layout renders FooterView directly to hand
|
|
5
|
+
// it the contact object item, which is not a footer field.
|
|
34
6
|
|
|
35
7
|
export type ContactFields = { email: string; phone?: string; address: string };
|
|
36
8
|
type Column = { title: string; links: { label: string; href: string }[] };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { f, smoodly } from "smoodly";
|
|
2
|
+
|
|
3
|
+
// The site header — a VISUAL global item (smoodly/globals.ts): one row,
|
|
4
|
+
// edited under Global content, rendered by the layout, never placed in a
|
|
5
|
+
// page. The brand is the same in every language; the nav is a list of
|
|
6
|
+
// links localized as a whole, so each language has its own labels and
|
|
7
|
+
// hrefs. The layout renders HeaderView directly to hand it the locale
|
|
8
|
+
// links (a paired component takes only its schema's props); the paired
|
|
9
|
+
// Header is what the registry and the admin know.
|
|
10
|
+
export const headerSchema = smoodly.schema.section({
|
|
11
|
+
name: "header",
|
|
12
|
+
title: "Header",
|
|
13
|
+
description: "The site header: brand and navigation.",
|
|
14
|
+
fields: {
|
|
15
|
+
brand: f.text(),
|
|
16
|
+
nav: f.list(f.object({ label: f.text(), href: f.link() })).localized(),
|
|
17
|
+
},
|
|
18
|
+
sample: { brand: "Lorem Co.", nav: [{ label: "Home", href: "/" }] },
|
|
19
|
+
// Nobody pads the header from the editor: no Spacing & layout group.
|
|
20
|
+
styles: false,
|
|
21
|
+
});
|
|
@@ -1,24 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
// The site header — a VISUAL global item (smoodly/globals.ts): one row,
|
|
4
|
-
// edited under Global content, rendered by the layout, never placed in a
|
|
5
|
-
// page. The brand is the same in every language; the nav is a list of
|
|
6
|
-
// links localized as a whole, so each language has its own labels and
|
|
7
|
-
// hrefs. The layout renders HeaderView directly to hand it the locale
|
|
8
|
-
// links (a paired component takes only its schema's props); the paired
|
|
9
|
-
// Header is what the registry and the admin know.
|
|
10
|
-
export const headerSchema = smoodly.schema.section({
|
|
11
|
-
name: "header",
|
|
12
|
-
title: "Header",
|
|
13
|
-
description: "The site header: brand and navigation.",
|
|
14
|
-
fields: {
|
|
15
|
-
brand: f.text(),
|
|
16
|
-
nav: f.list(f.object({ label: f.text(), href: f.link() })).localized(),
|
|
17
|
-
},
|
|
18
|
-
sample: { brand: "Lorem Co.", nav: [{ label: "Home", href: "/" }] },
|
|
19
|
-
// Nobody pads the header from the editor: no Spacing & layout group.
|
|
20
|
-
styles: false,
|
|
21
|
-
});
|
|
1
|
+
import { smoodly, type Props } from "smoodly/react";
|
|
2
|
+
import { headerSchema } from "./Header.schema";
|
|
22
3
|
|
|
23
4
|
export type LocaleLink = { code: string; url: string; current: boolean };
|
|
24
5
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { f, smoodly } from "smoodly";
|
|
2
|
+
|
|
3
|
+
// The home page opener: kicker, heading, text, up to two buttons and a
|
|
4
|
+
// portrait photo. Home locks it (`z.locked(heroSchema)`): one node an editor
|
|
5
|
+
// fills but cannot add, move or remove. `sample` is what the editor
|
|
6
|
+
// materializes into an empty locked zone, so it is a complete value.
|
|
7
|
+
export const heroSchema = smoodly.schema.section({
|
|
8
|
+
name: "hero",
|
|
9
|
+
title: "Hero",
|
|
10
|
+
description: "The home page opener: heading, text, buttons and a photo.",
|
|
11
|
+
fields: {
|
|
12
|
+
kicker: f.text().optional(),
|
|
13
|
+
heading: f.text(),
|
|
14
|
+
text: f.text(),
|
|
15
|
+
buttons: f.list(f.object({ label: f.text(), href: f.link() })).max(2),
|
|
16
|
+
image: f.image({ aspect: "4:5" }),
|
|
17
|
+
},
|
|
18
|
+
sample: {
|
|
19
|
+
kicker: "Lorem ipsum dolor",
|
|
20
|
+
heading: "Consectetur adipiscing elit sed do eiusmod",
|
|
21
|
+
text: "Tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip.",
|
|
22
|
+
buttons: [{ label: "About us", href: "/company/about-us" }],
|
|
23
|
+
},
|
|
24
|
+
});
|
|
@@ -1,28 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { smoodly, type Props } from "smoodly/react";
|
|
2
2
|
import { SmoodlyImage } from "smoodly/image";
|
|
3
|
-
|
|
4
|
-
// The home page opener: kicker, heading, text, up to two buttons and a
|
|
5
|
-
// portrait photo. Home locks it (`z.locked(Hero)`): one node an editor
|
|
6
|
-
// fills but cannot add, move or remove. `sample` is what the editor
|
|
7
|
-
// materializes into an empty locked zone, so it is a complete value.
|
|
8
|
-
export const heroSchema = smoodly.schema.section({
|
|
9
|
-
name: "hero",
|
|
10
|
-
title: "Hero",
|
|
11
|
-
description: "The home page opener: heading, text, buttons and a photo.",
|
|
12
|
-
fields: {
|
|
13
|
-
kicker: f.text().optional(),
|
|
14
|
-
heading: f.text(),
|
|
15
|
-
text: f.text(),
|
|
16
|
-
buttons: f.list(f.object({ label: f.text(), href: f.link() })).max(2),
|
|
17
|
-
image: f.image({ aspect: "4:5" }),
|
|
18
|
-
},
|
|
19
|
-
sample: {
|
|
20
|
-
kicker: "Lorem ipsum dolor",
|
|
21
|
-
heading: "Consectetur adipiscing elit sed do eiusmod",
|
|
22
|
-
text: "Tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip.",
|
|
23
|
-
buttons: [{ label: "About us", href: "/company/about-us" }],
|
|
24
|
-
},
|
|
25
|
-
});
|
|
3
|
+
import { heroSchema } from "./Hero.schema";
|
|
26
4
|
|
|
27
5
|
const m = smoodly.marks(heroSchema);
|
|
28
6
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { f, smoodly } from "smoodly";
|
|
2
|
+
|
|
3
|
+
// A photo beside a heading and richtext, the photo on either side (a
|
|
4
|
+
// setting, not a field: settings are never translated). Without a photo the
|
|
5
|
+
// heading takes the left column and the text the right — the About
|
|
6
|
+
// page's text block. The richtext renders through the package's
|
|
7
|
+
// RichText: paragraphs, headings, lists, quotes.
|
|
8
|
+
export const imageTextSchema = smoodly.schema.section({
|
|
9
|
+
name: "imageText",
|
|
10
|
+
title: "Image and text",
|
|
11
|
+
description: "A photo beside a heading and text; text alone in two columns without one.",
|
|
12
|
+
fields: {
|
|
13
|
+
image: f.image({ aspect: "4:3" }).optional(),
|
|
14
|
+
heading: f.text(),
|
|
15
|
+
// Body copy beside a photo: emphasis and links, no headings — the block's
|
|
16
|
+
// own heading field owns that. Every other richtext field takes the default.
|
|
17
|
+
text: f.richtext({ toolset: smoodly.toolset({ marks: ["bold", "italic", "link"] }) }),
|
|
18
|
+
link: f.object({ label: f.text(), href: f.link() }).optional(),
|
|
19
|
+
},
|
|
20
|
+
settings: {
|
|
21
|
+
imageSide: f.radio([{ value: "left", label: "Image left" }, { value: "right", label: "Image right" }]).default("left"),
|
|
22
|
+
},
|
|
23
|
+
sample: {
|
|
24
|
+
heading: "Duis aute irure dolor in reprehenderit",
|
|
25
|
+
text: {
|
|
26
|
+
type: "doc",
|
|
27
|
+
content: [{ type: "paragraph", content: [{ type: "text", text: "In voluptate velit esse cillum dolore eu fugiat nulla pariatur." }] }],
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
});
|