create-smoodly-app 0.0.46 → 0.0.48
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/package.json +1 -1
- package/templates/astro-blank/package.json +1 -1
- package/templates/astro-blank/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/astro-blank/supabase/migrations/20261009120000_smoodly_v11.sql +49 -0
- package/templates/astro-blank/supabase/migrations/{20261007200100_smoodly_views.sql → 20261009120100_smoodly_views.sql} +1 -1
- package/templates/astro-blank-intl/package.json +1 -1
- package/templates/astro-blank-intl/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/astro-blank-intl/supabase/migrations/20261009120000_smoodly_v11.sql +49 -0
- package/templates/astro-blank-intl/supabase/migrations/{20261007200100_smoodly_views.sql → 20261009120100_smoodly_views.sql} +1 -1
- package/templates/astro-lorem/package.json +1 -1
- package/templates/astro-lorem/src/components/ArticleCard.astro +1 -1
- package/templates/astro-lorem/src/elements/callout.astro +1 -1
- package/templates/astro-lorem/src/elements/cta.astro +1 -1
- package/templates/astro-lorem/src/entry-pages/articles.astro +1 -1
- package/templates/astro-lorem/src/entry-pages/news.astro +1 -1
- package/templates/astro-lorem/src/layouts/Layout.astro +1 -1
- package/templates/astro-lorem/src/live.config.ts +1 -1
- package/templates/astro-lorem/src/page-types/articlesIndex.astro +1 -1
- package/templates/astro-lorem/src/page-types/home.astro +1 -1
- package/templates/astro-lorem/src/page-types/newsIndex.astro +1 -1
- package/templates/astro-lorem/src/page-types/page.astro +1 -1
- package/templates/astro-lorem/src/pages/404.astro +1 -1
- package/templates/astro-lorem/src/sections/favouriteArticles.astro +1 -1
- package/templates/astro-lorem/src/sections/footer.astro +1 -1
- package/templates/astro-lorem/src/sections/header.astro +1 -1
- package/templates/astro-lorem/src/sections/hero.astro +1 -1
- package/templates/astro-lorem/src/sections/imageText.astro +1 -1
- package/templates/astro-lorem/src/sections/pageHero.astro +1 -1
- package/templates/astro-lorem/src/sections/peopleSection.astro +1 -1
- package/templates/astro-lorem/src/sections/points.astro +1 -2
- package/templates/astro-lorem/src/sections/quote.astro +1 -1
- package/templates/astro-lorem/src/strings.ts +1 -1
- package/templates/astro-lorem/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/astro-lorem/supabase/migrations/20261009120000_smoodly_v11.sql +49 -0
- package/templates/{lorem/supabase/migrations/20261007200100_smoodly_views.sql → astro-lorem/supabase/migrations/20261009120100_smoodly_views.sql} +1 -1
- package/templates/astro-lorem-intl/package.json +1 -1
- package/templates/astro-lorem-intl/src/components/ArticleCard.astro +1 -1
- package/templates/astro-lorem-intl/src/elements/callout.astro +1 -1
- package/templates/astro-lorem-intl/src/elements/cta.astro +1 -1
- package/templates/astro-lorem-intl/src/entry-pages/articles.astro +1 -1
- package/templates/astro-lorem-intl/src/entry-pages/news.astro +1 -1
- package/templates/astro-lorem-intl/src/layouts/Layout.astro +1 -1
- package/templates/astro-lorem-intl/src/live.config.ts +1 -1
- package/templates/astro-lorem-intl/src/page-types/articlesIndex.astro +1 -1
- package/templates/astro-lorem-intl/src/page-types/home.astro +1 -1
- package/templates/astro-lorem-intl/src/page-types/newsIndex.astro +1 -1
- package/templates/astro-lorem-intl/src/page-types/page.astro +1 -1
- package/templates/astro-lorem-intl/src/pages/404.astro +1 -1
- package/templates/astro-lorem-intl/src/sections/favouriteArticles.astro +1 -1
- package/templates/astro-lorem-intl/src/sections/footer.astro +1 -1
- package/templates/astro-lorem-intl/src/sections/header.astro +1 -1
- package/templates/astro-lorem-intl/src/sections/hero.astro +1 -1
- package/templates/astro-lorem-intl/src/sections/imageText.astro +1 -1
- package/templates/astro-lorem-intl/src/sections/pageHero.astro +1 -1
- package/templates/astro-lorem-intl/src/sections/peopleSection.astro +1 -1
- package/templates/astro-lorem-intl/src/sections/points.astro +1 -2
- package/templates/astro-lorem-intl/src/sections/quote.astro +1 -1
- package/templates/astro-lorem-intl/src/strings.ts +1 -1
- package/templates/astro-lorem-intl/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/astro-lorem-intl/supabase/migrations/20261009120000_smoodly_v11.sql +49 -0
- package/templates/{lorem-intl/supabase/migrations/20261007200100_smoodly_views.sql → astro-lorem-intl/supabase/migrations/20261009120100_smoodly_views.sql} +1 -1
- package/templates/blank/package.json +1 -1
- package/templates/blank/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/blank/supabase/migrations/20261009120000_smoodly_v11.sql +49 -0
- package/templates/blank/supabase/migrations/{20261007200100_smoodly_views.sql → 20261009120100_smoodly_views.sql} +1 -1
- package/templates/blank-intl/package.json +1 -1
- package/templates/blank-intl/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/blank-intl/supabase/migrations/20261009120000_smoodly_v11.sql +49 -0
- package/templates/blank-intl/supabase/migrations/{20261007200100_smoodly_views.sql → 20261009120100_smoodly_views.sql} +1 -1
- package/templates/lorem/package.json +1 -1
- package/templates/lorem/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/lorem/supabase/migrations/20261009120000_smoodly_v11.sql +49 -0
- package/templates/{astro-lorem/supabase/migrations/20261007200100_smoodly_views.sql → lorem/supabase/migrations/20261009120100_smoodly_views.sql} +1 -1
- package/templates/lorem-intl/package.json +1 -1
- package/templates/lorem-intl/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/lorem-intl/supabase/migrations/20261009120000_smoodly_v11.sql +49 -0
- package/templates/{astro-lorem-intl/supabase/migrations/20261007200100_smoodly_views.sql → lorem-intl/supabase/migrations/20261009120100_smoodly_views.sql} +1 -1
package/package.json
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
-- Smoodly core schema, version 10 (DESIGN §3, the document stamp, decided 2026-10-08).
|
|
2
|
+
-- Shipped in the smoodly package; `npx smoodly migrate` copies it into supabase/migrations/.
|
|
3
|
+
-- Never edit a published file: the next change is the next file.
|
|
4
|
+
-- The delta over version 9: published_models, one row per space holding the
|
|
5
|
+
-- document stamp the space recorded as current, so only the deployment at that
|
|
6
|
+
-- stamp rewrites delivery rows (a preview deployment on a newer package serves
|
|
7
|
+
-- assembled documents and writes nothing). Additive: no function changes.
|
|
8
|
+
|
|
9
|
+
set client_min_messages = warning;
|
|
10
|
+
|
|
11
|
+
-- The document stamp a space recorded as current: set by `npx smoodly rebuild` and by the first writer
|
|
12
|
+
-- into an empty record; only a reader at this stamp rewrites published_pages and published_entries.
|
|
13
|
+
create table if not exists "published_models" (
|
|
14
|
+
"space_id" uuid primary key default '00000000-0000-0000-0000-000000000000',
|
|
15
|
+
"model" text not null,
|
|
16
|
+
"recorded_at" timestamptz not null default now()
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
alter table "published_models" enable row level security;
|
|
20
|
+
|
|
21
|
+
-- Stamped with the caller's space on insert, as every content table.
|
|
22
|
+
drop trigger if exists "smoodly_a_set_space" on "published_models";
|
|
23
|
+
create trigger "smoodly_a_set_space" before insert on "published_models"
|
|
24
|
+
for each row execute function "smoodly_set_space"();
|
|
25
|
+
|
|
26
|
+
-- A write key reads and writes its own space's record; no other key reads (spec 2026-09-29 content API contract §8).
|
|
27
|
+
drop policy if exists "smoodly_write" on "published_models";
|
|
28
|
+
|
|
29
|
+
drop policy if exists "smoodly_insert" on "published_models";
|
|
30
|
+
create policy "smoodly_insert" on "published_models" for insert
|
|
31
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
32
|
+
|
|
33
|
+
drop policy if exists "smoodly_update" on "published_models";
|
|
34
|
+
create policy "smoodly_update" on "published_models" for update
|
|
35
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
36
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
37
|
+
|
|
38
|
+
drop policy if exists "smoodly_delete" on "published_models";
|
|
39
|
+
create policy "smoodly_delete" on "published_models" for delete
|
|
40
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
41
|
+
|
|
42
|
+
drop policy if exists "smoodly_read" on "published_models";
|
|
43
|
+
create policy "smoodly_read" on "published_models" for select
|
|
44
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
45
|
+
|
|
46
|
+
insert into "smoodly_meta" ("key", "value") values ('schema_version', '10')
|
|
47
|
+
on conflict ("key") do update set "value" = excluded."value";
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
-- Smoodly core schema, version 11 (DESIGN §3, static mode, decided 2026-10-09).
|
|
2
|
+
-- Shipped in the smoodly package; `npx smoodly migrate` copies it into supabase/migrations/.
|
|
3
|
+
-- Never edit a published file: the next change is the next file.
|
|
4
|
+
-- The delta over version 10: space_deploys, one row per space holding the last
|
|
5
|
+
-- Deploy press (static mode's button), so a serverless function can tell a
|
|
6
|
+
-- build in flight from one that landed. Additive: no function changes.
|
|
7
|
+
|
|
8
|
+
set client_min_messages = warning;
|
|
9
|
+
|
|
10
|
+
-- The last Deploy press of a space (spec 2026-10-09 static mode §7): who pressed and when; the admin
|
|
11
|
+
-- compares it with the build marker the live site serves to show building, landed or not landed.
|
|
12
|
+
create table if not exists "space_deploys" (
|
|
13
|
+
"space_id" uuid primary key default '00000000-0000-0000-0000-000000000000',
|
|
14
|
+
-- Null until the first press: a removal may make the row first.
|
|
15
|
+
"requested_at" timestamptz,
|
|
16
|
+
"requested_by" text,
|
|
17
|
+
-- When a delivery row last went (an unpublish, a delete): a change the count of newer rows cannot see.
|
|
18
|
+
"removed_at" timestamptz
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
alter table "space_deploys" enable row level security;
|
|
22
|
+
|
|
23
|
+
-- Stamped with the caller's space on insert, as every content table.
|
|
24
|
+
drop trigger if exists "smoodly_a_set_space" on "space_deploys";
|
|
25
|
+
create trigger "smoodly_a_set_space" before insert on "space_deploys"
|
|
26
|
+
for each row execute function "smoodly_set_space"();
|
|
27
|
+
|
|
28
|
+
-- A write key reads and writes its own space's row; no other key reads (spec 2026-09-29 content API contract §8).
|
|
29
|
+
drop policy if exists "smoodly_write" on "space_deploys";
|
|
30
|
+
|
|
31
|
+
drop policy if exists "smoodly_insert" on "space_deploys";
|
|
32
|
+
create policy "smoodly_insert" on "space_deploys" for insert
|
|
33
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
34
|
+
|
|
35
|
+
drop policy if exists "smoodly_update" on "space_deploys";
|
|
36
|
+
create policy "smoodly_update" on "space_deploys" for update
|
|
37
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
38
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
39
|
+
|
|
40
|
+
drop policy if exists "smoodly_delete" on "space_deploys";
|
|
41
|
+
create policy "smoodly_delete" on "space_deploys" for delete
|
|
42
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
43
|
+
|
|
44
|
+
drop policy if exists "smoodly_read" on "space_deploys";
|
|
45
|
+
create policy "smoodly_read" on "space_deploys" for select
|
|
46
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
47
|
+
|
|
48
|
+
insert into "smoodly_meta" ("key", "value") values ('schema_version', '11')
|
|
49
|
+
on conflict ("key") do update set "value" = excluded."value";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
-- Smoodly: read views for this app's collections, written by `npx smoodly migrate`
|
|
2
|
-
-- (2026-10-
|
|
2
|
+
-- (2026-10-09T12:01:00.000Z). One block per collection; the marker's hash is the block's SQL, compared on the next run.
|
|
3
3
|
-- Never edit a written file: change the collection and run migrate again.
|
|
4
4
|
|
|
5
5
|
-- smoodly:collection posts sha256:38ba2918f83ab367
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
-- Smoodly core schema, version 10 (DESIGN §3, the document stamp, decided 2026-10-08).
|
|
2
|
+
-- Shipped in the smoodly package; `npx smoodly migrate` copies it into supabase/migrations/.
|
|
3
|
+
-- Never edit a published file: the next change is the next file.
|
|
4
|
+
-- The delta over version 9: published_models, one row per space holding the
|
|
5
|
+
-- document stamp the space recorded as current, so only the deployment at that
|
|
6
|
+
-- stamp rewrites delivery rows (a preview deployment on a newer package serves
|
|
7
|
+
-- assembled documents and writes nothing). Additive: no function changes.
|
|
8
|
+
|
|
9
|
+
set client_min_messages = warning;
|
|
10
|
+
|
|
11
|
+
-- The document stamp a space recorded as current: set by `npx smoodly rebuild` and by the first writer
|
|
12
|
+
-- into an empty record; only a reader at this stamp rewrites published_pages and published_entries.
|
|
13
|
+
create table if not exists "published_models" (
|
|
14
|
+
"space_id" uuid primary key default '00000000-0000-0000-0000-000000000000',
|
|
15
|
+
"model" text not null,
|
|
16
|
+
"recorded_at" timestamptz not null default now()
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
alter table "published_models" enable row level security;
|
|
20
|
+
|
|
21
|
+
-- Stamped with the caller's space on insert, as every content table.
|
|
22
|
+
drop trigger if exists "smoodly_a_set_space" on "published_models";
|
|
23
|
+
create trigger "smoodly_a_set_space" before insert on "published_models"
|
|
24
|
+
for each row execute function "smoodly_set_space"();
|
|
25
|
+
|
|
26
|
+
-- A write key reads and writes its own space's record; no other key reads (spec 2026-09-29 content API contract §8).
|
|
27
|
+
drop policy if exists "smoodly_write" on "published_models";
|
|
28
|
+
|
|
29
|
+
drop policy if exists "smoodly_insert" on "published_models";
|
|
30
|
+
create policy "smoodly_insert" on "published_models" for insert
|
|
31
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
32
|
+
|
|
33
|
+
drop policy if exists "smoodly_update" on "published_models";
|
|
34
|
+
create policy "smoodly_update" on "published_models" for update
|
|
35
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
36
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
37
|
+
|
|
38
|
+
drop policy if exists "smoodly_delete" on "published_models";
|
|
39
|
+
create policy "smoodly_delete" on "published_models" for delete
|
|
40
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
41
|
+
|
|
42
|
+
drop policy if exists "smoodly_read" on "published_models";
|
|
43
|
+
create policy "smoodly_read" on "published_models" for select
|
|
44
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
45
|
+
|
|
46
|
+
insert into "smoodly_meta" ("key", "value") values ('schema_version', '10')
|
|
47
|
+
on conflict ("key") do update set "value" = excluded."value";
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
-- Smoodly core schema, version 11 (DESIGN §3, static mode, decided 2026-10-09).
|
|
2
|
+
-- Shipped in the smoodly package; `npx smoodly migrate` copies it into supabase/migrations/.
|
|
3
|
+
-- Never edit a published file: the next change is the next file.
|
|
4
|
+
-- The delta over version 10: space_deploys, one row per space holding the last
|
|
5
|
+
-- Deploy press (static mode's button), so a serverless function can tell a
|
|
6
|
+
-- build in flight from one that landed. Additive: no function changes.
|
|
7
|
+
|
|
8
|
+
set client_min_messages = warning;
|
|
9
|
+
|
|
10
|
+
-- The last Deploy press of a space (spec 2026-10-09 static mode §7): who pressed and when; the admin
|
|
11
|
+
-- compares it with the build marker the live site serves to show building, landed or not landed.
|
|
12
|
+
create table if not exists "space_deploys" (
|
|
13
|
+
"space_id" uuid primary key default '00000000-0000-0000-0000-000000000000',
|
|
14
|
+
-- Null until the first press: a removal may make the row first.
|
|
15
|
+
"requested_at" timestamptz,
|
|
16
|
+
"requested_by" text,
|
|
17
|
+
-- When a delivery row last went (an unpublish, a delete): a change the count of newer rows cannot see.
|
|
18
|
+
"removed_at" timestamptz
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
alter table "space_deploys" enable row level security;
|
|
22
|
+
|
|
23
|
+
-- Stamped with the caller's space on insert, as every content table.
|
|
24
|
+
drop trigger if exists "smoodly_a_set_space" on "space_deploys";
|
|
25
|
+
create trigger "smoodly_a_set_space" before insert on "space_deploys"
|
|
26
|
+
for each row execute function "smoodly_set_space"();
|
|
27
|
+
|
|
28
|
+
-- A write key reads and writes its own space's row; no other key reads (spec 2026-09-29 content API contract §8).
|
|
29
|
+
drop policy if exists "smoodly_write" on "space_deploys";
|
|
30
|
+
|
|
31
|
+
drop policy if exists "smoodly_insert" on "space_deploys";
|
|
32
|
+
create policy "smoodly_insert" on "space_deploys" for insert
|
|
33
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
34
|
+
|
|
35
|
+
drop policy if exists "smoodly_update" on "space_deploys";
|
|
36
|
+
create policy "smoodly_update" on "space_deploys" for update
|
|
37
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
38
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
39
|
+
|
|
40
|
+
drop policy if exists "smoodly_delete" on "space_deploys";
|
|
41
|
+
create policy "smoodly_delete" on "space_deploys" for delete
|
|
42
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
43
|
+
|
|
44
|
+
drop policy if exists "smoodly_read" on "space_deploys";
|
|
45
|
+
create policy "smoodly_read" on "space_deploys" for select
|
|
46
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
47
|
+
|
|
48
|
+
insert into "smoodly_meta" ("key", "value") values ('schema_version', '11')
|
|
49
|
+
on conflict ("key") do update set "value" = excluded."value";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
-- Smoodly: read views for this app's collections, written by `npx smoodly migrate`
|
|
2
|
-
-- (2026-10-
|
|
2
|
+
-- (2026-10-09T12:01:00.000Z). One block per collection; the marker's hash is the block's SQL, compared on the next run.
|
|
3
3
|
-- Never edit a written file: change the collection and run migrate again.
|
|
4
4
|
|
|
5
5
|
-- smoodly:collection posts sha256:38ba2918f83ab367
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/components/ArticleCard.astro
|
|
3
3
|
// One article card: photo, first tag and date, title, excerpt. The grid item on the Articles page and in
|
|
4
4
|
// Favourite articles; `compact` drops the excerpt for the Related list. The caller resolves the URL.
|
|
5
5
|
import { Image } from "smoodly/astro/components";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/elements/callout.astro — the view of the element named "callout", inside an article body
|
|
3
3
|
import { type Props as SmoodlyProps } from "smoodly";
|
|
4
4
|
import { RichText } from "smoodly/astro/components";
|
|
5
5
|
import { calloutSchema } from "@/components/elements/Callout.schema";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/elements/cta.astro — the view of the element named "cta"
|
|
3
3
|
import { safeHref, type Props as SmoodlyProps } from "smoodly";
|
|
4
4
|
import { ctaSchema } from "@/components/elements/Cta.schema";
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/entry-pages/articles.astro — the entry page of the collection "articles", served at the
|
|
3
3
|
// collection's path (/posts/<slug>, /fi/artikkelit/<slug>). Fields only; refs arrive resolved (author is a
|
|
4
4
|
// person). "Related" is the newest other published articles; "More from <author>" filters on the shared
|
|
5
5
|
// author field in the store. The render locale and the alternates ride on the entry (spec 2026-09-15).
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/entry-pages/news.astro — the entry page of the collection "news", at
|
|
3
3
|
// /company/news/<slug> and /fi/yritys/uutiset/<slug>: the collection's nested path, then the slug.
|
|
4
4
|
import { RichText } from "smoodly/astro/components";
|
|
5
5
|
import { href } from "smoodly/astro/runtime";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/layouts/Layout.astro
|
|
3
3
|
// The site's own document: every page type and entry page renders inside it. The header and the footer are
|
|
4
4
|
// global content, read as live entries per locale, null until published there; the language links come from
|
|
5
5
|
// the page's own `locales` map (spec 2026-09-15), so a layout here can know which page is on screen — Astro
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// src/live.config.ts
|
|
2
2
|
// Smoodly's content as live collections (spec 2026-10-02 astro cloud fit §6): a loader per collection, global
|
|
3
3
|
// item and the pages, from the package; this file only names them. `getLiveCollection("articles", { locale })`
|
|
4
4
|
// in a view reads through the read layer, and the response is tagged by what it read.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/page-types/articlesIndex.astro — the view of the page type named "articlesIndex": the
|
|
3
3
|
// editor owns the hero; the grid reads the published articles as a live collection, newest first (the
|
|
4
4
|
// collection's `order`), and in the canvas the drafts too (the request scope reads drafts in a preview).
|
|
5
5
|
import { getLiveCollection } from "astro:content";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/page-types/home.astro — the view of the page type named "home"
|
|
3
3
|
import { Zone } from "smoodly/astro/components";
|
|
4
4
|
import type { PageContext } from "smoodly";
|
|
5
5
|
import type { PageHead, ZoneContent } from "smoodly/astro/runtime";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/page-types/newsIndex.astro — the view of the page type named "newsIndex"
|
|
3
3
|
import { getLiveCollection } from "astro:content";
|
|
4
4
|
import { Zone } from "smoodly/astro/components";
|
|
5
5
|
import { href } from "smoodly/astro/runtime";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/page-types/page.astro — the view of the page type named "page"
|
|
3
3
|
import { Zone } from "smoodly/astro/components";
|
|
4
4
|
import type { PageContext } from "smoodly";
|
|
5
5
|
import type { PageHead, ZoneContent } from "smoodly/astro/runtime";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/pages/404.astro — the site's own "not found" page: the shell rewrites here.
|
|
3
3
|
import Layout from "../layouts/Layout.astro";
|
|
4
4
|
---
|
|
5
5
|
<Layout head={{ title: "Not found", noindex: true, languages: {} }} locale="en">
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/sections/favouriteArticles.astro — the view of the section named "favouriteArticles":
|
|
3
3
|
// articles an editor picked, resolved before render, so the view gets article fields, not ids.
|
|
4
4
|
import { smoodly, type Props as SmoodlyProps } from "smoodly";
|
|
5
5
|
import { Section } from "smoodly/astro/components";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/sections/footer.astro — the view of the section named "footer", a visual global item
|
|
3
3
|
// the layout renders with the contact object item, which is not a footer field.
|
|
4
4
|
import { safeHref, smoodly, type Props as SmoodlyProps, type Scope } from "smoodly";
|
|
5
5
|
import { Section } from "smoodly/astro/components";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/sections/header.astro — the view of the section named "header", a visual global item
|
|
3
3
|
// the layout renders with the locale links beside the schema's own props.
|
|
4
4
|
import { safeHref, smoodly, type Props as SmoodlyProps } from "smoodly";
|
|
5
5
|
import { Section } from "smoodly/astro/components";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/sections/hero.astro — the view of the section named "hero"
|
|
3
3
|
import { safeHref, smoodly, type Props as SmoodlyProps } from "smoodly";
|
|
4
4
|
import { Image, Section } from "smoodly/astro/components";
|
|
5
5
|
import { heroSchema } from "@/components/sections/Hero.schema";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/sections/imageText.astro — the view of the section named "imageText"
|
|
3
3
|
import { safeHref, smoodly, type Props as SmoodlyProps } from "smoodly";
|
|
4
4
|
import { Image, RichText, Section } from "smoodly/astro/components";
|
|
5
5
|
import { imageTextSchema } from "@/components/sections/ImageText.schema";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/sections/pageHero.astro — the view of the section named "pageHero"
|
|
3
3
|
import { smoodly, type Props as SmoodlyProps } from "smoodly";
|
|
4
4
|
import { Image, Section } from "smoodly/astro/components";
|
|
5
5
|
import { pageHeroSchema } from "@/components/sections/PageHero.schema";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/sections/peopleSection.astro — the view of the section named "peopleSection"
|
|
3
3
|
import { smoodly, type Props as SmoodlyProps } from "smoodly";
|
|
4
4
|
import { Section } from "smoodly/astro/components";
|
|
5
5
|
import { peopleSchema } from "@/components/sections/People.schema";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/sections/points.astro — the view of the section named "points"
|
|
3
3
|
import { smoodly, type Props as SmoodlyProps } from "smoodly";
|
|
4
4
|
import { Section } from "smoodly/astro/components";
|
|
5
5
|
import { pointsSchema } from "@/components/sections/Points.schema";
|
|
@@ -17,7 +17,6 @@ const icons: Record<string, string> = {
|
|
|
17
17
|
<div class="container">
|
|
18
18
|
<h2 class="h2" {...m.field("heading")}>{heading}</h2>
|
|
19
19
|
<div class="points__grid">
|
|
20
|
-
{/* A real crash for the suite's guard test: `(points ?? []).map` on a string throws here, as in the React view. */}
|
|
21
20
|
{(points ?? []).map((point, i) => {
|
|
22
21
|
const p = m.item("points", i);
|
|
23
22
|
return (
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/sections/quote.astro — the view of the section named "quote"
|
|
3
3
|
import { smoodly, type Props as SmoodlyProps } from "smoodly";
|
|
4
4
|
import { Section } from "smoodly/astro/components";
|
|
5
5
|
import { quoteSchema } from "@/components/sections/Quote.schema";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// src/strings.ts
|
|
2
2
|
// The site's own UI strings in the page's language — what a view says that is not content: "All articles",
|
|
3
3
|
// "min read". The messages are plain JSON under messages/; this seam reads them with no i18n library behind it.
|
|
4
4
|
/// <reference types="vite/client" />
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
-- Smoodly core schema, version 10 (DESIGN §3, the document stamp, decided 2026-10-08).
|
|
2
|
+
-- Shipped in the smoodly package; `npx smoodly migrate` copies it into supabase/migrations/.
|
|
3
|
+
-- Never edit a published file: the next change is the next file.
|
|
4
|
+
-- The delta over version 9: published_models, one row per space holding the
|
|
5
|
+
-- document stamp the space recorded as current, so only the deployment at that
|
|
6
|
+
-- stamp rewrites delivery rows (a preview deployment on a newer package serves
|
|
7
|
+
-- assembled documents and writes nothing). Additive: no function changes.
|
|
8
|
+
|
|
9
|
+
set client_min_messages = warning;
|
|
10
|
+
|
|
11
|
+
-- The document stamp a space recorded as current: set by `npx smoodly rebuild` and by the first writer
|
|
12
|
+
-- into an empty record; only a reader at this stamp rewrites published_pages and published_entries.
|
|
13
|
+
create table if not exists "published_models" (
|
|
14
|
+
"space_id" uuid primary key default '00000000-0000-0000-0000-000000000000',
|
|
15
|
+
"model" text not null,
|
|
16
|
+
"recorded_at" timestamptz not null default now()
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
alter table "published_models" enable row level security;
|
|
20
|
+
|
|
21
|
+
-- Stamped with the caller's space on insert, as every content table.
|
|
22
|
+
drop trigger if exists "smoodly_a_set_space" on "published_models";
|
|
23
|
+
create trigger "smoodly_a_set_space" before insert on "published_models"
|
|
24
|
+
for each row execute function "smoodly_set_space"();
|
|
25
|
+
|
|
26
|
+
-- A write key reads and writes its own space's record; no other key reads (spec 2026-09-29 content API contract §8).
|
|
27
|
+
drop policy if exists "smoodly_write" on "published_models";
|
|
28
|
+
|
|
29
|
+
drop policy if exists "smoodly_insert" on "published_models";
|
|
30
|
+
create policy "smoodly_insert" on "published_models" for insert
|
|
31
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
32
|
+
|
|
33
|
+
drop policy if exists "smoodly_update" on "published_models";
|
|
34
|
+
create policy "smoodly_update" on "published_models" for update
|
|
35
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
36
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
37
|
+
|
|
38
|
+
drop policy if exists "smoodly_delete" on "published_models";
|
|
39
|
+
create policy "smoodly_delete" on "published_models" for delete
|
|
40
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
41
|
+
|
|
42
|
+
drop policy if exists "smoodly_read" on "published_models";
|
|
43
|
+
create policy "smoodly_read" on "published_models" for select
|
|
44
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
45
|
+
|
|
46
|
+
insert into "smoodly_meta" ("key", "value") values ('schema_version', '10')
|
|
47
|
+
on conflict ("key") do update set "value" = excluded."value";
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
-- Smoodly core schema, version 11 (DESIGN §3, static mode, decided 2026-10-09).
|
|
2
|
+
-- Shipped in the smoodly package; `npx smoodly migrate` copies it into supabase/migrations/.
|
|
3
|
+
-- Never edit a published file: the next change is the next file.
|
|
4
|
+
-- The delta over version 10: space_deploys, one row per space holding the last
|
|
5
|
+
-- Deploy press (static mode's button), so a serverless function can tell a
|
|
6
|
+
-- build in flight from one that landed. Additive: no function changes.
|
|
7
|
+
|
|
8
|
+
set client_min_messages = warning;
|
|
9
|
+
|
|
10
|
+
-- The last Deploy press of a space (spec 2026-10-09 static mode §7): who pressed and when; the admin
|
|
11
|
+
-- compares it with the build marker the live site serves to show building, landed or not landed.
|
|
12
|
+
create table if not exists "space_deploys" (
|
|
13
|
+
"space_id" uuid primary key default '00000000-0000-0000-0000-000000000000',
|
|
14
|
+
-- Null until the first press: a removal may make the row first.
|
|
15
|
+
"requested_at" timestamptz,
|
|
16
|
+
"requested_by" text,
|
|
17
|
+
-- When a delivery row last went (an unpublish, a delete): a change the count of newer rows cannot see.
|
|
18
|
+
"removed_at" timestamptz
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
alter table "space_deploys" enable row level security;
|
|
22
|
+
|
|
23
|
+
-- Stamped with the caller's space on insert, as every content table.
|
|
24
|
+
drop trigger if exists "smoodly_a_set_space" on "space_deploys";
|
|
25
|
+
create trigger "smoodly_a_set_space" before insert on "space_deploys"
|
|
26
|
+
for each row execute function "smoodly_set_space"();
|
|
27
|
+
|
|
28
|
+
-- A write key reads and writes its own space's row; no other key reads (spec 2026-09-29 content API contract §8).
|
|
29
|
+
drop policy if exists "smoodly_write" on "space_deploys";
|
|
30
|
+
|
|
31
|
+
drop policy if exists "smoodly_insert" on "space_deploys";
|
|
32
|
+
create policy "smoodly_insert" on "space_deploys" for insert
|
|
33
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
34
|
+
|
|
35
|
+
drop policy if exists "smoodly_update" on "space_deploys";
|
|
36
|
+
create policy "smoodly_update" on "space_deploys" for update
|
|
37
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
38
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
39
|
+
|
|
40
|
+
drop policy if exists "smoodly_delete" on "space_deploys";
|
|
41
|
+
create policy "smoodly_delete" on "space_deploys" for delete
|
|
42
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
43
|
+
|
|
44
|
+
drop policy if exists "smoodly_read" on "space_deploys";
|
|
45
|
+
create policy "smoodly_read" on "space_deploys" for select
|
|
46
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
47
|
+
|
|
48
|
+
insert into "smoodly_meta" ("key", "value") values ('schema_version', '11')
|
|
49
|
+
on conflict ("key") do update set "value" = excluded."value";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
-- Smoodly: read views for this app's collections, written by `npx smoodly migrate`
|
|
2
|
-
-- (2026-10-
|
|
2
|
+
-- (2026-10-09T12:01:00.000Z). One block per collection; the marker's hash is the block's SQL, compared on the next run.
|
|
3
3
|
-- Never edit a written file: change the collection and run migrate again.
|
|
4
4
|
|
|
5
5
|
-- smoodly:collection people sha256:929798ebb4fa2bb6
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/components/ArticleCard.astro
|
|
3
3
|
// One article card: photo, first tag and date, title, excerpt. The grid item on the Articles page and in
|
|
4
4
|
// Favourite articles; `compact` drops the excerpt for the Related list. The caller resolves the URL.
|
|
5
5
|
import { Image } from "smoodly/astro/components";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/elements/callout.astro — the view of the element named "callout", inside an article body
|
|
3
3
|
import { type Props as SmoodlyProps } from "smoodly";
|
|
4
4
|
import { RichText } from "smoodly/astro/components";
|
|
5
5
|
import { calloutSchema } from "@/components/elements/Callout.schema";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/elements/cta.astro — the view of the element named "cta"
|
|
3
3
|
import { safeHref, type Props as SmoodlyProps } from "smoodly";
|
|
4
4
|
import { ctaSchema } from "@/components/elements/Cta.schema";
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/entry-pages/articles.astro — the entry page of the collection "articles", served at the
|
|
3
3
|
// collection's path (/posts/<slug>, /fi/artikkelit/<slug>). Fields only; refs arrive resolved (author is a
|
|
4
4
|
// person). "Related" is the newest other published articles; "More from <author>" filters on the shared
|
|
5
5
|
// author field in the store. The render locale and the alternates ride on the entry (spec 2026-09-15).
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/entry-pages/news.astro — the entry page of the collection "news", at
|
|
3
3
|
// /company/news/<slug> and /fi/yritys/uutiset/<slug>: the collection's nested path, then the slug.
|
|
4
4
|
import { RichText } from "smoodly/astro/components";
|
|
5
5
|
import { href } from "smoodly/astro/runtime";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
//
|
|
2
|
+
// src/layouts/Layout.astro
|
|
3
3
|
// The site's own document: every page type and entry page renders inside it. The header and the footer are
|
|
4
4
|
// global content, read as live entries per locale, null until published there; the language links come from
|
|
5
5
|
// the page's own `locales` map (spec 2026-09-15), so a layout here can know which page is on screen — Astro
|