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
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Working in this Smoodly site
|
|
2
|
+
|
|
3
|
+
This is an Astro site with Smoodly installed: content lives in Supabase, the admin is mounted at /admin by the `smoodly/astro` integration in `astro.config.ts`, and the site reads content through live collections (`src/live.config.ts`). Read README.md first: it says where things are.
|
|
4
|
+
|
|
5
|
+
## Rules
|
|
6
|
+
|
|
7
|
+
- **Register schemas in the config; views are files by name.** A section's view is
|
|
8
|
+
`src/sections/<name>.astro`, an element's `src/elements/<name>.astro`, a page
|
|
9
|
+
type's `src/page-types/<name>.astro`, an entry page's
|
|
10
|
+
`src/entry-pages/<collection>.astro`, where <name> is the schema's `name`.
|
|
11
|
+
The schema is listed in its barrel (`src/smoodly/sections.ts`, `elements.ts`,
|
|
12
|
+
the config's `pages`; collections and global items in `collections.ts`,
|
|
13
|
+
`globals.ts`) and `src/smoodly/config.ts` is the one registry. The server
|
|
14
|
+
names a schema with no file, and a file with no schema, at the first request.
|
|
15
|
+
- **A `.schema.ts` file imports no component.** Zones, toolsets, global items and
|
|
16
|
+
`node()` take schemas (`z.locked(heroSchema)`), never views.
|
|
17
|
+
- **After a new collection or a `smoodly` upgrade, run `npx smoodly migrate`**
|
|
18
|
+
and apply what it writes (`supabase db push` hosted, `supabase migration up`
|
|
19
|
+
local). It copies the core schema files the package ships and writes a
|
|
20
|
+
read view and order index per collection. Never edit a file it wrote.
|
|
21
|
+
The admin reads the base tables, so it lists a collection either way;
|
|
22
|
+
the view is for SQL and PostgREST readers, the index for `order`.
|
|
23
|
+
- **Content from code goes through `createContent(config)`** from `smoodly/astro`:
|
|
24
|
+
`scripts/seed.ts` is starter content written with it — the admin's own
|
|
25
|
+
operations, so validation and publish checks apply and a failure throws. Never
|
|
26
|
+
write rows or call the stores directly. The seed is idempotent; `npm run seed`.
|
|
27
|
+
- **Reads are live collections.** `src/live.config.ts` names one loader per
|
|
28
|
+
collection, global item, the pages and the page tree; a view reads with
|
|
29
|
+
`getLiveCollection("articles", { locale })` or `getLiveEntry("footer", { locale })`
|
|
30
|
+
from `astro:content`. Every read tags the response, and a publish expires it.
|
|
31
|
+
- **The admin, the preview address and the page shell are injected** by
|
|
32
|
+
`smoodly()` in `astro.config.ts`; the project has no route file for them. A page
|
|
33
|
+
file of your own under `src/pages` wins its address. `site` in `astro.config.ts`
|
|
34
|
+
is the site's own address (from `SITE_URL`).
|
|
35
|
+
- **A link an editor typed goes through `safeHref`** from "smoodly" in an `.astro`
|
|
36
|
+
view: `<a href={safeHref(link.href)}>`. Astro writes attributes as given, so a
|
|
37
|
+
`javascript:` URL would reach the page; the template build refuses a shipped
|
|
38
|
+
view that skips it.
|
|
39
|
+
- **Section styles are inline.** `<Section>` from `smoodly/astro/components` renders
|
|
40
|
+
the root element with Smoodly's styles set and the node id; marks
|
|
41
|
+
(`smoodly.marks(schema)`) tie rendered elements to fields.
|
|
42
|
+
- **Multilingual sites.** The locale set is `locales` in `src/smoodly/config.ts`
|
|
43
|
+
and `i18n` in `astro.config.ts`; the two must agree. UI strings of the site's
|
|
44
|
+
own go through `src/strings.ts` and `src/messages/<locale>.json`.
|
|
45
|
+
- **Fixed versus open pages.** A page type with a `slug` is fixed: one
|
|
46
|
+
record, created for you, never deleted. Without one it is open: editors
|
|
47
|
+
create as many as they like.
|
|
48
|
+
|
|
49
|
+
## Commands
|
|
50
|
+
|
|
51
|
+
npm run dev # http://localhost:4321, /admin is the editor
|
|
52
|
+
npm run build # checks the schema files (smoodly migrate --check), then astro build
|
|
53
|
+
npm run start # the built server (dist/server/entry.mjs)
|
|
54
|
+
npm run seed # starter content, idempotent
|
|
55
|
+
npm run typecheck # astro check
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Smoodly site
|
|
2
|
+
|
|
3
|
+
Created by `create-smoodly-app`. Content lives in Supabase; the admin is
|
|
4
|
+
mounted at `/admin` by the `smoodly/astro` integration. AGENTS.md holds the
|
|
5
|
+
rules for an agent (or a person) building the site.
|
|
6
|
+
|
|
7
|
+
npm run dev # http://localhost:4321 — /admin is the editor
|
|
8
|
+
|
|
9
|
+
## Where things are
|
|
10
|
+
|
|
11
|
+
- `astro.config.ts` — the `smoodly()` integration (it mounts the admin, the preview address and the page shell), the node adapter, the cache and `site` (from `SITE_URL`).
|
|
12
|
+
- `astro.config.ts` also carries `i18n`: the same locales as `src/smoodly/config.ts`, which must agree with it. The default locale is served at the root, the others under their prefix.
|
|
13
|
+
- `src/page-types/` — one view per page type: `home.astro` (fixed at /, one freeform zone) and `page.astro` (open, editors create many).
|
|
14
|
+
- `src/entry-pages/posts.astro` — the entry page of the posts collection, at /posts/<slug>.
|
|
15
|
+
- `src/sections/text.astro` and `src/components/sections/Text.schema.ts` — the one section: a title and a richtext body.
|
|
16
|
+
- `src/elements/button.astro` and `src/components/elements/Button.schema.ts` — the one element: a link styled as a button, embedded in richtext through `src/smoodly/toolsets.ts`.
|
|
17
|
+
- `src/components/LocaleNav.astro` — the language links every page view renders from its `locales` map; nothing with one locale.
|
|
18
|
+
- `src/layouts/Layout.astro` — the document every view renders: the head, the footer line from the `site` global item, `src/styles/global.css`.
|
|
19
|
+
- `src/smoodly/` — the wiring: `config.ts` (the registry of schemas and the settings), `collections.ts` (posts), `globals.ts` (the site item), `sections.ts` and `elements.ts` (the schemas the config registers), `toolsets.ts`.
|
|
20
|
+
- `src/live.config.ts` — the live collections the views read with `getLiveCollection` and `getLiveEntry`.
|
|
21
|
+
- `scripts/seed.ts` — the home page and the site item, written through `createContent(config)`. `npm run seed` is idempotent.
|
|
22
|
+
- `src/styles/global.css` — a reset, a container, the two tones. Replace it.
|
|
23
|
+
- `.env` — `SMOODLY_URL`, `SMOODLY_SECRET_KEY`, `SMOODLY_PUBLISHABLE_KEY`.
|
|
24
|
+
|
|
25
|
+
## Add a section
|
|
26
|
+
|
|
27
|
+
Copy `src/components/sections/Text.schema.ts`, give the schema a new
|
|
28
|
+
`name` and `title` and declare its fields. List it in `sections` in
|
|
29
|
+
`src/smoodly/sections.ts` and in the `sections` of every zone that may
|
|
30
|
+
hold it in `src/components/pages/*.schema.ts`. Then write its view,
|
|
31
|
+
`src/sections/<name>.astro`, by copying `text.astro`: render the fields
|
|
32
|
+
inside `<Section>` with marks on each. It appears in the editor's "+"
|
|
33
|
+
picker. A schema with no view, and a view with no schema, are named at
|
|
34
|
+
the first request.
|
|
35
|
+
|
|
36
|
+
## Add an element
|
|
37
|
+
|
|
38
|
+
Copy `src/components/elements/Button.schema.ts` (relative imports only).
|
|
39
|
+
Add the schema to `elements` in `src/smoodly/elements.ts` and to the
|
|
40
|
+
`elements` of the toolset in `src/smoodly/toolsets.ts` that may embed
|
|
41
|
+
it, and write `src/elements/<name>.astro`. A link an editor types goes
|
|
42
|
+
through `safeHref`, as in `button.astro`. It appears in the richtext
|
|
43
|
+
editor's "/" menu.
|
|
44
|
+
|
|
45
|
+
## Add a collection
|
|
46
|
+
|
|
47
|
+
Copy the `posts` block in `src/smoodly/collections.ts`, add the new
|
|
48
|
+
collection to `collections` and a loader for it in `src/live.config.ts`,
|
|
49
|
+
and write its entry page, `src/entry-pages/<collection>.astro`, by
|
|
50
|
+
copying `posts.astro`. Then write its read view and order index and
|
|
51
|
+
apply them:
|
|
52
|
+
|
|
53
|
+
npx smoodly migrate
|
|
54
|
+
supabase db push # hosted; `supabase migration up` for the local stack (keeps the content)
|
|
55
|
+
|
|
56
|
+
The same command brings the core schema forward after a `smoodly` upgrade.
|
|
57
|
+
|
|
58
|
+
## Add a global item
|
|
59
|
+
|
|
60
|
+
Copy the `site` block in `src/smoodly/globals.ts`, add it to `globals`
|
|
61
|
+
and give it a loader in `src/live.config.ts`. A view reads it with
|
|
62
|
+
`getLiveEntry("name", { locale })`. Edit it under Globals in the admin.
|
|
63
|
+
|
|
64
|
+
Reseed an empty database any time with `npm run seed`.
|
|
65
|
+
|
|
66
|
+
## Moving the admin
|
|
67
|
+
|
|
68
|
+
The admin is at `/admin`. To serve it somewhere else, say `/studio`:
|
|
69
|
+
|
|
70
|
+
1. set `smoodly({ adminPath: "/studio" })` in `astro.config.ts`,
|
|
71
|
+
2. set `admin: { path: "/studio" }` in `src/smoodly/config.ts`.
|
|
72
|
+
|
|
73
|
+
The two must agree; the admin says so when they do not.
|
|
74
|
+
|
|
75
|
+
## Editors
|
|
76
|
+
|
|
77
|
+
Anyone who may open `/admin` is a Supabase Auth user with a row in the
|
|
78
|
+
`editors` table. To add one: create the user in Supabase Studio
|
|
79
|
+
(Authentication → Users), then in the SQL editor:
|
|
80
|
+
|
|
81
|
+
insert into editors (user_id, role) values ('<the user id>', 'editor');
|
|
82
|
+
|
|
83
|
+
## Hosted Supabase
|
|
84
|
+
|
|
85
|
+
supabase init # if the CLI has not been set up here yet
|
|
86
|
+
supabase link # pick the project
|
|
87
|
+
supabase db push # applies supabase/migrations/
|
|
88
|
+
|
|
89
|
+
Then put the project's URL and keys in `.env`.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { defineConfig, memoryCache } from "astro/config";
|
|
2
|
+
import node from "@astrojs/node";
|
|
3
|
+
import smoodly from "smoodly/astro";
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
output: "server",
|
|
7
|
+
adapter: node({ mode: "standalone" }),
|
|
8
|
+
// Pages are cached whole and expire by tag when an editor publishes (one process, one cache).
|
|
9
|
+
cache: { provider: memoryCache() },
|
|
10
|
+
// The site's own address: canonical, hreflang and social links are absolute on it. Astro reads astro.config
|
|
11
|
+
// before .env, so this sees only a SITE_URL set in the shell; when it is unset, smoodly() sets `site` from
|
|
12
|
+
// SITE_URL in .env. Set SITE_URL where you deploy: `site` is fixed at `astro build`.
|
|
13
|
+
site: process.env.SITE_URL,
|
|
14
|
+
// The same locales as src/smoodly/config.ts (the adapter checks): the default at the root, the others under their prefix.
|
|
15
|
+
i18n: { locales: ["en", "fi"], defaultLocale: "en" },
|
|
16
|
+
integrations: [smoodly({ config: "src/smoodly/config.ts" })],
|
|
17
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "smoodly-site",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "astro dev",
|
|
7
|
+
"build": "smoodly migrate --check && astro build",
|
|
8
|
+
"start": "node --env-file-if-exists=.env dist/server/entry.mjs",
|
|
9
|
+
"seed": "tsx scripts/seed.ts",
|
|
10
|
+
"typecheck": "astro check"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@astrojs/node": "^11.1.6",
|
|
14
|
+
"@supabase/supabase-js": "^2.113.0",
|
|
15
|
+
"astro": "^7.3.5",
|
|
16
|
+
"smoodly": "0.0.47"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@astrojs/check": "^0.9.10",
|
|
20
|
+
"@types/node": "^26.4.1",
|
|
21
|
+
"typescript": "^5",
|
|
22
|
+
"tsx": "^4"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// The starter's content, written through the content API (`createContent(config)`
|
|
2
|
+
// from smoodly/astro): the admin's own operations, so validation and
|
|
3
|
+
// the publish checks apply and a failure throws. It is also the example
|
|
4
|
+
// of writing content from code. Ships in the scaffold; create-smoodly-app
|
|
5
|
+
// runs `npm run seed` after the first editor. Idempotent: exits once the
|
|
6
|
+
// home page has content in the default locale. Writes the same copy into every configured locale, whatever
|
|
7
|
+
// their codes, so every locale's "/" resolves.
|
|
8
|
+
// Run: npm run seed (needs .env and a Supabase stack).
|
|
9
|
+
import type { PageTree, TreeNode } from "smoodly";
|
|
10
|
+
|
|
11
|
+
const { config } = await import("../src/smoodly/config");
|
|
12
|
+
const { node } = await import("smoodly");
|
|
13
|
+
const { createContent } = await import("smoodly/astro");
|
|
14
|
+
const { content } = createContent(config);
|
|
15
|
+
const { textSchema } = await import("../src/components/sections/Text.schema");
|
|
16
|
+
const c = content;
|
|
17
|
+
|
|
18
|
+
const DEFAULT = config.locales.default;
|
|
19
|
+
const OTHERS = config.locales.supported.filter((l) => l !== DEFAULT);
|
|
20
|
+
|
|
21
|
+
// The home page is code-owned: `find` returns its record, creating it when
|
|
22
|
+
// the database is new. It is seeded once somebody has given it sections.
|
|
23
|
+
const home = (await c.pages.find(DEFAULT, "/"))!;
|
|
24
|
+
if (Object.values((await c.pages.getTree(home.id, DEFAULT))?.zones ?? {}).some((nodes) => nodes.length > 0)) {
|
|
25
|
+
console.log(`Already seeded — the home page has content in "${DEFAULT}".`);
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Richtext is TipTap JSON, the stored format; RichText renders it.
|
|
30
|
+
type Node = Record<string, unknown>;
|
|
31
|
+
const p = (s: string): Node => ({ type: "paragraph", content: [{ type: "text", text: s }] });
|
|
32
|
+
const button = (label: string, href: string): Node => ({ type: "element", attrs: { name: "button", fields: { label, href }, settings: {} } });
|
|
33
|
+
const doc = (...content: Node[]) => ({ type: "doc", content });
|
|
34
|
+
|
|
35
|
+
// --- the site item: name and tagline, published in every locale ------
|
|
36
|
+
|
|
37
|
+
for (const locale of [DEFAULT, ...OTHERS]) {
|
|
38
|
+
await c.globals.set("site", locale, { name: "My site", tagline: "Built with Smoodly" });
|
|
39
|
+
await c.globals.publish("site", locale);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// --- the home page: one Text section and one custom section ----------
|
|
43
|
+
|
|
44
|
+
// The custom section is not a registered section, so it is a plain node object.
|
|
45
|
+
const custom: TreeNode = {
|
|
46
|
+
id: "node-custom",
|
|
47
|
+
type: "custom",
|
|
48
|
+
fields: { rows: [
|
|
49
|
+
{ spans: [6, 6], gap: "md", align: "top", reverse: false, columns: [
|
|
50
|
+
doc(p("A custom section holds rows of columns. Drag the width bar in the inspector to resize them.")),
|
|
51
|
+
doc(p("Each column is richtext. Columns stack on small screens; the developer's stylesheet needs nothing.")),
|
|
52
|
+
] },
|
|
53
|
+
] },
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const tree: PageTree = {
|
|
57
|
+
meta: { description: "A new site, built with Smoodly." },
|
|
58
|
+
zones: {
|
|
59
|
+
body: [
|
|
60
|
+
node(textSchema, {
|
|
61
|
+
title: "Hello",
|
|
62
|
+
body: doc(
|
|
63
|
+
p("This is your home page. Open the admin to edit this text, add sections, create pages and write posts."),
|
|
64
|
+
p("Everything you see is defined in components/ and registered in smoodly/. The README says where things are."),
|
|
65
|
+
button("Open the admin", "/admin"),
|
|
66
|
+
),
|
|
67
|
+
}, { id: "node-hello", settings: { background: "paper" } }),
|
|
68
|
+
// The custom section: the editor's own rows of columns, rendered by Smoodly.
|
|
69
|
+
custom,
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// The home page exists in every locale already (its registration says so): write the tree and publish.
|
|
75
|
+
for (const locale of [DEFAULT, ...OTHERS]) {
|
|
76
|
+
await c.pages.setTree(home.id, locale, tree);
|
|
77
|
+
await c.pages.publish(home.id, locale);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log(`Seeded the blank starter in "${[DEFAULT, ...OTHERS].join('", "')}": the home page and the site item, published.`);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
// src/components/LocaleNav.astro — the language links, rendered by every page view from its own `locales` map:
|
|
3
|
+
// the same page in the other language where it is published there, that language's home otherwise. Nothing
|
|
4
|
+
// with one locale, so the single-language scaffold shares the file.
|
|
5
|
+
import { href } from "smoodly/astro/runtime";
|
|
6
|
+
|
|
7
|
+
type Props = { locale: string; locales: Record<string, { path: string | null } | null> };
|
|
8
|
+
const { locale, locales } = Astro.props;
|
|
9
|
+
const codes = Object.keys(locales);
|
|
10
|
+
---
|
|
11
|
+
{codes.length > 1 && (
|
|
12
|
+
<nav class="container locales" aria-label="Language">
|
|
13
|
+
{codes.map((code) => <a href={href(locales[code]?.path ?? "/", code)} aria-current={code === locale ? "page" : undefined}>{code}</a>)}
|
|
14
|
+
</nav>
|
|
15
|
+
)}
|
|
@@ -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
|
+
// src/elements/button.astro is its view. To add another element, copy
|
|
6
|
+
// both files, name the view after the schema, and list the schema in
|
|
7
|
+
// src/smoodly/elements.ts and in the toolsets that may embed it
|
|
8
|
+
// (src/smoodly/toolsets.ts).
|
|
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
|
+
});
|
|
@@ -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. Its view,
|
|
5
|
+
// src/page-types/home.astro, 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
|
+
});
|
|
@@ -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. src/page-types/page.astro 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
|
+
});
|
|
@@ -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. Its view is
|
|
5
|
+
// src/sections/text.astro. To add another section, copy both files, name the
|
|
6
|
+
// view after the new schema, list the schema in src/smoodly/sections.ts
|
|
7
|
+
// and allow it in a page type's zone (src/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
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
// src/elements/button.astro — the view of the element named "button": a link styled as a button, inserted inside
|
|
3
|
+
// richtext. An editor typed the href, so it goes through safeHref: a scheme the page must not carry renders no link.
|
|
4
|
+
import { safeHref, type Props as SmoodlyProps } from "smoodly";
|
|
5
|
+
import { buttonSchema } from "@/components/elements/Button.schema";
|
|
6
|
+
|
|
7
|
+
type Props = SmoodlyProps<typeof buttonSchema>;
|
|
8
|
+
const { label, href } = Astro.props;
|
|
9
|
+
---
|
|
10
|
+
<a class="button" href={safeHref(href)}>{label}</a>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
// src/entry-pages/posts.astro — the entry page of the collection "posts", served at /posts/<slug>. An entry page
|
|
3
|
+
// is a file by the collection's name; it receives the entry as a read returns it, with its locale alternates.
|
|
4
|
+
import type { EntryFields, EntryItem } from "smoodly";
|
|
5
|
+
import { RichText } from "smoodly/astro/components";
|
|
6
|
+
import type { PageHead } from "smoodly/astro/runtime";
|
|
7
|
+
import type { posts } from "@/smoodly/collections";
|
|
8
|
+
import Layout from "../layouts/Layout.astro";
|
|
9
|
+
import LocaleNav from "../components/LocaleNav.astro";
|
|
10
|
+
|
|
11
|
+
type Props = { entry: EntryItem<EntryFields<typeof posts>>; head: PageHead };
|
|
12
|
+
const { entry, head } = Astro.props;
|
|
13
|
+
const { locale, locales } = entry;
|
|
14
|
+
const post = entry.fields;
|
|
15
|
+
---
|
|
16
|
+
<Layout head={head} locale={locale}>
|
|
17
|
+
<LocaleNav locale={locale} locales={locales} />
|
|
18
|
+
<article class="container prose">
|
|
19
|
+
<h1>{post.title}</h1>
|
|
20
|
+
{post.date && <p><time datetime={post.date}>{post.date.slice(0, 10)}</time></p>}
|
|
21
|
+
<RichText doc={post.body} />
|
|
22
|
+
</article>
|
|
23
|
+
</Layout>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
// src/layouts/Layout.astro — the site's own document: every page type and entry page renders inside it. The
|
|
3
|
+
// `site` global item (src/smoodly/globals.ts) gives the title and the footer line, read as a live entry per
|
|
4
|
+
// locale, null until published there. In a preview the integration adds what the editor needs to the response.
|
|
5
|
+
import { getLiveEntry } from "astro:content";
|
|
6
|
+
import { Head } from "smoodly/astro/components";
|
|
7
|
+
import type { PageHead } from "smoodly/astro/runtime";
|
|
8
|
+
import "../styles/global.css";
|
|
9
|
+
|
|
10
|
+
type Props = { head: PageHead; locale: string };
|
|
11
|
+
const { head, locale } = Astro.props;
|
|
12
|
+
const { entry: site } = await getLiveEntry("site", { locale });
|
|
13
|
+
---
|
|
14
|
+
<!doctype html>
|
|
15
|
+
<html lang={locale}>
|
|
16
|
+
<head>
|
|
17
|
+
<meta charset="utf-8" />
|
|
18
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
19
|
+
<Head of={head} fallback={site?.data.fields.name ?? "Smoodly site"} />
|
|
20
|
+
</head>
|
|
21
|
+
<body>
|
|
22
|
+
<main><slot /></main>
|
|
23
|
+
{site && <footer class="container site-footer">{site.data.fields.name} · {site.data.fields.tagline}</footer>}
|
|
24
|
+
</body>
|
|
25
|
+
</html>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// src/live.config.ts — Smoodly's content as live collections: one loader per collection, global item and the pages,
|
|
2
|
+
// from the package; this file only names them. A view reads with getLiveCollection / getLiveEntry from astro:content.
|
|
3
|
+
import { defineLiveCollection } from "astro:content";
|
|
4
|
+
import { entriesLoader, globalLoader, pageLoader, pageTreeLoader } from "smoodly/astro/content";
|
|
5
|
+
import { posts } from "@/smoodly/collections";
|
|
6
|
+
import { site } from "@/smoodly/globals";
|
|
7
|
+
|
|
8
|
+
export const collections = {
|
|
9
|
+
pages: defineLiveCollection({ loader: pageLoader() }),
|
|
10
|
+
pageTree: defineLiveCollection({ loader: pageTreeLoader() }),
|
|
11
|
+
posts: defineLiveCollection({ loader: entriesLoader(posts) }),
|
|
12
|
+
site: defineLiveCollection({ loader: globalLoader(site) }),
|
|
13
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
// src/page-types/home.astro — the view of the page type named "home", fixed at "/": one freeform body zone inside the layout.
|
|
3
|
+
import type { PageContext } from "smoodly";
|
|
4
|
+
import { Zone } from "smoodly/astro/components";
|
|
5
|
+
import type { PageHead, ZoneContent } from "smoodly/astro/runtime";
|
|
6
|
+
import Layout from "../layouts/Layout.astro";
|
|
7
|
+
import LocaleNav from "../components/LocaleNav.astro";
|
|
8
|
+
|
|
9
|
+
type Props = { page: PageContext; zones: Record<string, ZoneContent>; head: PageHead };
|
|
10
|
+
const { page, zones, head } = Astro.props;
|
|
11
|
+
---
|
|
12
|
+
<Layout head={head} locale={page.locale}>
|
|
13
|
+
<LocaleNav locale={page.locale} locales={page.locales} />
|
|
14
|
+
<Zone of={zones.body} />
|
|
15
|
+
</Layout>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
// src/page-types/page.astro — the view of the page type named "page", which editors create many of: one freeform body zone inside the layout.
|
|
3
|
+
import type { PageContext } from "smoodly";
|
|
4
|
+
import { Zone } from "smoodly/astro/components";
|
|
5
|
+
import type { PageHead, ZoneContent } from "smoodly/astro/runtime";
|
|
6
|
+
import Layout from "../layouts/Layout.astro";
|
|
7
|
+
import LocaleNav from "../components/LocaleNav.astro";
|
|
8
|
+
|
|
9
|
+
type Props = { page: PageContext; zones: Record<string, ZoneContent>; head: PageHead };
|
|
10
|
+
const { page, zones, head } = Astro.props;
|
|
11
|
+
---
|
|
12
|
+
<Layout head={head} locale={page.locale}>
|
|
13
|
+
<LocaleNav locale={page.locale} locales={page.locales} />
|
|
14
|
+
<Zone of={zones.body} />
|
|
15
|
+
</Layout>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
// src/pages/404.astro — the site's own "not found" page: the shell rewrites here.
|
|
3
|
+
import Layout from "../layouts/Layout.astro";
|
|
4
|
+
---
|
|
5
|
+
<Layout head={{ title: "Not found", noindex: true, languages: {} }} locale="en">
|
|
6
|
+
<div class="container"><h1>Page not found</h1></div>
|
|
7
|
+
</Layout>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
// src/sections/text.astro — the view of the section named "text". <Section> renders the root element, Smoodly's
|
|
3
|
+
// styles set inline and the node id; a setting the CSS reads — here `background` — is the view's own data
|
|
4
|
+
// attribute. Marks tie the rendered elements to their fields, so the editor can select and edit them in place.
|
|
5
|
+
import { smoodly, type Props as SmoodlyProps } from "smoodly";
|
|
6
|
+
import { RichText, Section } from "smoodly/astro/components";
|
|
7
|
+
import { textSchema } from "@/components/sections/Text.schema";
|
|
8
|
+
|
|
9
|
+
type Props = SmoodlyProps<typeof textSchema>;
|
|
10
|
+
const { title, body, settings, styles } = Astro.props;
|
|
11
|
+
const m = smoodly.marks(textSchema);
|
|
12
|
+
---
|
|
13
|
+
<Section styles={styles} class="text" data-background={settings.background}>
|
|
14
|
+
<div class="container prose">
|
|
15
|
+
<h2 {...m.field("title")}>{title}</h2>
|
|
16
|
+
<div {...m.field("body")}><RichText doc={body} /></div>
|
|
17
|
+
</div>
|
|
18
|
+
</Section>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { f, smoodly } from "smoodly";
|
|
2
|
+
import { text } from "./toolsets";
|
|
3
|
+
|
|
4
|
+
// A collection: structured content with its own admin list, served at
|
|
5
|
+
// `path` by its entry page (src/entry-pages/posts.astro). Fields marked
|
|
6
|
+
// .localized() are stored per locale; the rest are shared across
|
|
7
|
+
// locales. To add a collection: copy this block, add it to
|
|
8
|
+
// `collections`, run `npx smoodly migrate` and apply the file it writes
|
|
9
|
+
// (supabase db push, or supabase migration up locally).
|
|
10
|
+
export const posts = smoodly.collection({
|
|
11
|
+
name: "posts",
|
|
12
|
+
title: "Posts",
|
|
13
|
+
titleField: "title",
|
|
14
|
+
path: "posts",
|
|
15
|
+
order: { by: "date", direction: "desc" },
|
|
16
|
+
fields: {
|
|
17
|
+
title: f.text().localized(),
|
|
18
|
+
slug: f.slug({ from: "title" }),
|
|
19
|
+
date: f.date(),
|
|
20
|
+
body: f.richtext({ toolset: text }).localized(),
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export const collections = [posts];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { defineConfig } from "smoodly";
|
|
2
|
+
import { collections } from "./collections";
|
|
3
|
+
import { sections } from "./sections";
|
|
4
|
+
import { globals } from "./globals";
|
|
5
|
+
import { elements } from "./elements";
|
|
6
|
+
import { homeSchema } from "@/components/pages/Home.schema";
|
|
7
|
+
import { pageSchema } from "@/components/pages/Page.schema";
|
|
8
|
+
|
|
9
|
+
export { collections, sections, globals, elements };
|
|
10
|
+
|
|
11
|
+
// The registry of schemas and the plain settings, one file. It imports
|
|
12
|
+
// no component and no route file, so a script and the CLI can load it
|
|
13
|
+
// outside the app; the views are files by name under src/.
|
|
14
|
+
// The locale set is below; astro.config.ts declares the same set.
|
|
15
|
+
export const config = defineConfig({
|
|
16
|
+
registry: {
|
|
17
|
+
sections,
|
|
18
|
+
elements,
|
|
19
|
+
collections,
|
|
20
|
+
globals,
|
|
21
|
+
// Page types. The entry page is a view: src/entry-pages/posts.astro.
|
|
22
|
+
pages: [homeSchema, pageSchema],
|
|
23
|
+
},
|
|
24
|
+
locales: { default: "en", supported: ["en", "fi"] },
|
|
25
|
+
// The record the site root serves.
|
|
26
|
+
homePageSlug: "home",
|
|
27
|
+
// Editors can nest pages three deep.
|
|
28
|
+
pages: { tree: { depth: 3 } },
|
|
29
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Global content: code-declared singletons, edited once under Globals
|
|
2
|
+
// and read anywhere. `site` is an object item — fields code consumes;
|
|
3
|
+
// the layout reads it as a live entry, getLiveEntry("site"): a layout
|
|
4
|
+
// global: it comes with the page's own read. A visual item
|
|
5
|
+
// (`section: someSectionSchema`) renders through a section instead.
|
|
6
|
+
import { f, smoodly } from "smoodly";
|
|
7
|
+
|
|
8
|
+
export const site = smoodly.global({
|
|
9
|
+
name: "site",
|
|
10
|
+
title: "Site",
|
|
11
|
+
fields: {
|
|
12
|
+
name: f.text(),
|
|
13
|
+
tagline: f.text().localized(),
|
|
14
|
+
},
|
|
15
|
+
layout: true,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export const globals = [site];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Toolsets are values, not registrations: a richtext field names one.
|
|
2
|
+
// `text` is the starter's one set — the default marks and block nodes,
|
|
3
|
+
// plus the Button element. Elements are embedded by value; the config
|
|
4
|
+
// must also register them (smoodly/elements.ts; defineConfig checks).
|
|
5
|
+
// Relative imports on purpose: collections.ts pulls this file into
|
|
6
|
+
// create-smoodly-app's template build, which runs outside the app.
|
|
7
|
+
import { smoodly } from "smoodly";
|
|
8
|
+
import { buttonSchema } from "../components/elements/Button.schema";
|
|
9
|
+
|
|
10
|
+
export const text = smoodly.toolset({
|
|
11
|
+
marks: ["bold", "italic", "link"],
|
|
12
|
+
nodes: ["h2", "h3", "bulletList", "orderedList", "blockquote"],
|
|
13
|
+
elements: [buttonSchema],
|
|
14
|
+
});
|