create-goodfellow 0.1.0 → 0.3.0

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.
Files changed (59) hide show
  1. package/README.md +2 -2
  2. package/dist/cli.js +36 -3
  3. package/dist/index.d.ts +6 -79
  4. package/dist/index.js +2 -2
  5. package/dist/scaffold-BGxzPdN1.js +150 -0
  6. package/package.json +8 -8
  7. package/templates/next/.github/workflows/deploy.yml +37 -2
  8. package/templates/next/.gitlab-ci.yml +12 -2
  9. package/templates/next/README.md +14 -7
  10. package/templates/next/app/admin/layout.tsx +2 -2
  11. package/templates/next/app/goodfellow-site.json/route.ts +5 -0
  12. package/templates/next/app/layout.tsx +2 -1
  13. package/templates/next/content/site.json +3 -1
  14. package/templates/parish/.github/workflows/deploy.yml +37 -2
  15. package/templates/parish/.gitlab-ci.yml +12 -2
  16. package/templates/parish/README.md +14 -7
  17. package/templates/parish/content/collections/events/_collection.json +19 -20
  18. package/templates/parish/content/collections/events/advent-penance-service.json +5 -3
  19. package/templates/parish/content/collections/events/all-souls.json +5 -3
  20. package/templates/parish/content/collections/events/christmas-concert.json +5 -3
  21. package/templates/parish/content/collections/events/fall-festival.json +5 -3
  22. package/templates/parish/content/collections/events/youth-group.json +23 -0
  23. package/templates/parish/content/collections/news/_collection.json +24 -0
  24. package/templates/parish/content/collections/news/bell-tower-repairs.json +13 -0
  25. package/templates/parish/content/collections/news/choir-new-voices.json +14 -0
  26. package/templates/parish/content/collections/news/food-drive.json +4 -1
  27. package/templates/parish/content/collections/news/new-website.json +4 -1
  28. package/templates/parish/content/collections/news/winter-coats.json +13 -0
  29. package/templates/parish/content/collections/news/youth-group.json +4 -1
  30. package/templates/parish/content/collections/news/youth-service-day.json +14 -0
  31. package/templates/parish/content/menus.json +4 -0
  32. package/templates/parish/content/pages/about.json +48 -5
  33. package/templates/parish/content/pages/calendar.json +59 -0
  34. package/templates/parish/content/pages/events.json +27 -11
  35. package/templates/parish/content/pages/index.json +4 -37
  36. package/templates/parish/content/pages/news.json +14 -1
  37. package/templates/parish/content/site.json +4 -1
  38. package/templates/parish/vercel.ts +65 -0
  39. package/templates/registry/custom-html.json +1 -1
  40. package/templates/registry/registry.json +11 -11
  41. package/templates/registry/shadcn-call-to-action.json +1 -1
  42. package/templates/registry/shadcn-cards.json +1 -1
  43. package/templates/registry/shadcn-carousel.json +1 -1
  44. package/templates/registry/shadcn-faq.json +1 -1
  45. package/templates/registry/shadcn-hero.json +1 -1
  46. package/templates/registry/shadcn-notice.json +1 -1
  47. package/templates/registry/shadcn-pricing.json +1 -1
  48. package/templates/registry/shadcn-tabs.json +1 -1
  49. package/templates/registry/shadcn-testimonials.json +1 -1
  50. package/templates/starter/.github/workflows/deploy.yml +37 -2
  51. package/templates/starter/.gitlab-ci.yml +12 -2
  52. package/templates/starter/README.md +14 -7
  53. package/templates/starter/content/site.json +3 -1
  54. package/templates/starter/vercel.ts +65 -0
  55. package/templates/versions.json +12 -11
  56. package/dist/scaffold-4nOF_fOJ.js +0 -207
  57. package/templates/next/tsconfig.tsbuildinfo +0 -1
  58. package/templates/parish/vercel.json +0 -7
  59. package/templates/starter/vercel.json +0 -7
@@ -1,7 +1,10 @@
1
1
  # Builds the site and publishes it with GitHub Pages whenever the main branch
2
2
  # changes (including every Publish in the admin panel), and once a night so
3
- # date-based content stays current. In the repository's Settings → Pages, set
4
- # "Source" to "GitHub Actions". See README.md.
3
+ # date-based content stays current. Each night it first installs Goodfellow's
4
+ # newest fixes, and publishes them only if the site still builds with them,
5
+ # unless content/updates.json turns automatic updates off.
6
+ # In the repository's Settings → Pages, set "Source" to "GitHub Actions".
7
+ # See README.md.
5
8
  name: Deploy to GitHub Pages
6
9
 
7
10
  on:
@@ -10,6 +13,11 @@ on:
10
13
  schedule:
11
14
  - cron: "17 4 * * *"
12
15
  workflow_dispatch:
16
+ inputs:
17
+ update:
18
+ description: "Update Goodfellow first: fixes, latest, or a release such as 0.5.0 (an older one goes back to it). Leave empty to only build."
19
+ required: false
20
+ default: ""
13
21
 
14
22
  permissions:
15
23
  contents: read
@@ -21,10 +29,36 @@ concurrency:
21
29
  cancel-in-progress: false
22
30
 
23
31
  jobs:
32
+ update:
33
+ # Each night, and when the admin panel's Updates screen asks.
34
+ if: github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.update != '')
35
+ runs-on: ubuntu-latest
36
+ permissions:
37
+ contents: write
38
+ outputs:
39
+ sha: ${{ steps.update.outputs.sha }}
40
+ steps:
41
+ - uses: actions/checkout@v5
42
+ - uses: actions/setup-node@v5
43
+ with:
44
+ node-version: 22
45
+ cache: npm
46
+ - run: npm ci
47
+ - id: update
48
+ env:
49
+ TO: ${{ inputs.update || 'automatic' }}
50
+ run: npx goodfellow update --publish --to "$TO"
51
+
24
52
  build:
53
+ needs: update
54
+ # Also when there was no update to run, or it didn't work: the site is built either way.
55
+ if: ${{ !cancelled() }}
25
56
  runs-on: ubuntu-latest
26
57
  steps:
27
58
  - uses: actions/checkout@v5
59
+ with:
60
+ # The update's commit, when it published one.
61
+ ref: ${{ needs.update.outputs.sha || github.sha }}
28
62
  - uses: actions/setup-node@v5
29
63
  with:
30
64
  node-version: 22
@@ -40,6 +74,7 @@ jobs:
40
74
 
41
75
  deploy:
42
76
  needs: build
77
+ if: ${{ !cancelled() && needs.build.result == 'success' }}
43
78
  runs-on: ubuntu-latest
44
79
  environment:
45
80
  name: github-pages
@@ -1,6 +1,11 @@
1
1
  # Builds the site and publishes it with GitLab Pages whenever the default
2
- # branch changes (including every Publish in the admin panel). For nightly
3
- # rebuilds, add a schedule under Build → Pipeline schedules. See README.md.
2
+ # branch changes (including every Publish in the admin panel). On scheduled
3
+ # pipelines, which the admin panel's Updates screen sets up to run each night,
4
+ # it first installs Goodfellow's newest fixes, unless content/updates.json turns
5
+ # automatic updates off (or the release GOODFELLOW_UPDATE names), and publishes
6
+ # them only if the site still builds with them. That
7
+ # needs "Allow Git push requests to the repository" under Settings → CI/CD →
8
+ # Job token permissions, which the Updates screen turns on. See README.md.
4
9
  pages:
5
10
  image: node:22
6
11
  cache:
@@ -9,6 +14,11 @@ pages:
9
14
  paths: [.npm/]
10
15
  script:
11
16
  - npm ci --cache .npm --prefer-offline
17
+ - |
18
+ if [ "$CI_PIPELINE_SOURCE" = "schedule" ] || [ -n "$GOODFELLOW_UPDATE" ]; then
19
+ git remote set-url origin "https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_FQDN:-$CI_SERVER_HOST}/${CI_PROJECT_PATH}.git"
20
+ npx goodfellow update --publish --to "${GOODFELLOW_UPDATE:-automatic}" || echo "The update wasn't published; building the site as it is."
21
+ fi
12
22
  # Pages may serve the site from a subfolder, such as https://group.gitlab.io/site/.
13
23
  - export GOODFELLOW_BASE="$(node -e 'console.log(new URL(process.env.CI_PAGES_URL).pathname)')"
14
24
  - npx goodfellow build
@@ -1,6 +1,6 @@
1
1
  # St. Joseph Parish (example)
2
2
 
3
- An example parish website built with [Goodfellow](https://github.com/chartung17/goodfellow-cms). **St. Joseph Parish is made up**: its name, address, phone number, staff, history, Mass times and events are invented, and the pictures are simple drawings. Replace them all with your own before putting the site online.
3
+ An example parish website built with [Goodfellow](https://github.com/goodfellow-cms/goodfellow-cms). **St. Joseph Parish is made up**: its name, address, phone number, staff, history, Mass times and events are invented, and the pictures are simple drawings. Replace them all with your own before putting the site online.
4
4
 
5
5
  Start a site from this example with `npm create goodfellow@latest my-parish -- --template parish`.
6
6
 
@@ -28,13 +28,13 @@ On your own computer, the admin panel saves straight to the files in `content/`.
28
28
  - **Bulletins:** each one links to a PDF uploaded on the **Media** screen.
29
29
  - **Staff**, listed on the About us page. They have no pages of their own, and the **Order** field sets who comes first.
30
30
  - **Contact details** (address, phone and email) are set once in **Site settings → General**, and shown in the footer and on the contact page by the **Contact details** block.
31
- - **More blocks**, such as an FAQ and tabs, can be added on the admin panel's **Blocks** screen. See [Blocks from block registries](https://github.com/chartung17/goodfellow-cms#blocks-from-block-registries).
31
+ - **More blocks**, such as an FAQ and tabs, can be added on the admin panel's **Blocks** screen. See [Add blocks](https://goodfellow-cms.github.io/goodfellow-cms/docs/add-blocks).
32
32
  - **The parish's own blocks**, in `blocks/`, show how a developer adds blocks to a site. They're listed under **Parish** in the editor:
33
33
  - **Mass times:** a list of days and times, each with an optional note.
34
34
  - **Scripture quote:** a short passage with its reference. The example uses the Douay-Rheims Bible (Challoner revision), a Catholic translation in the public domain; most modern translations need permission to quote.
35
35
  - **Notice:** an announcement that stands out from the text around it.
36
36
 
37
- Each block is a React component plus the fields the editor shows for it. They're added to the editor in `goodfellow.config.tsx`. Never rename a block's key or its fields once pages use them, since content files refer to them by name. Parts of a block that respond to visitors, such as a button that shows more, go in a file starting with `"use client"`, and only pages that use them load JavaScript: see [Interactive blocks](https://github.com/chartung17/goodfellow-cms#interactive-blocks).
37
+ Each block is a React component plus the fields the editor shows for it. They're added to the editor in `goodfellow.config.tsx`. Never rename a block's key or its fields once pages use them, since content files refer to them by name. Parts of a block that respond to visitors, such as a button that shows more, go in a file starting with `"use client"`, and only pages that use them load JavaScript: see [Interactive blocks](https://goodfellow-cms.github.io/goodfellow-cms/docs/interactive-blocks).
38
38
 
39
39
  ## Making it yours
40
40
 
@@ -49,7 +49,14 @@ Setup takes four steps. It's done once, usually by whoever set up the site.
49
49
 
50
50
  ### 1. Store the site on GitHub or GitLab
51
51
 
52
- Create a repository and push this folder to it, including `package-lock.json`.
52
+ Create an empty repository on GitHub or GitLab, without a README, and push this folder to it:
53
+
54
+ ```sh
55
+ git remote add origin https://github.com/your-name/your-site.git # unless origin is already set
56
+ git push -u origin main
57
+ ```
58
+
59
+ `create-goodfellow` makes the new site a git repository on the branch `main`, with everything, `package-lock.json` included, in its first commit, and sets `origin` when it's given the repository. Commit any changes since (`git add -A` and `git commit`) before pushing.
53
60
 
54
61
  ### 2. Tell Goodfellow where the site is stored
55
62
 
@@ -71,7 +78,7 @@ Also set the site's address under **Site settings → General → Site address**
71
78
 
72
79
  ### 3. Choose a host
73
80
 
74
- Each host's free plan has its own rules about business use. If the site is for a business, sells anything, shows ads, or is built or looked after by someone who's paid for it, check those rules first. As of October 2026, GitHub Pages and Vercel's free plan don't allow most of these, and GitLab Pages has no rule against them that we know of. See [Commercial sites](https://github.com/chartung17/goodfellow-cms#requirements-and-limits) in Goodfellow's README.
81
+ Each host's free plan has its own rules about business use. If the site is for a business, sells anything, shows ads, or is built or looked after by someone who's paid for it, check those rules first. As of October 2026, GitHub Pages and Vercel's free plan don't allow most of these, and GitLab Pages has no rule against them that we know of. See [Hosts and business sites](https://goodfellow-cms.github.io/goodfellow-cms/docs/hosts) in Goodfellow's documentation.
75
82
 
76
83
  **GitHub Pages** (free for public repositories; not for online businesses or shops)
77
84
 
@@ -86,7 +93,7 @@ Each host's free plan has its own rules about business use. If the site is for a
86
93
 
87
94
  **Vercel** (works with GitHub and GitLab; the free plan is for non-commercial sites only)
88
95
 
89
- 1. Import the repository in Vercel. `vercel.json` already has the right settings.
96
+ 1. Import the repository in Vercel. `vercel.ts` already has the right settings, and has Vercel send the site's redirects itself.
90
97
  2. For nightly rebuilds, create a deploy hook under **Settings → Git → Deploy Hooks**, and call it from a scheduled GitHub Action or GitLab pipeline schedule.
91
98
 
92
99
  Delete the setup files for the hosts you don't use.
@@ -114,7 +121,7 @@ Upload images and files, such as the weekly bulletin, on the admin panel's **Med
114
121
 
115
122
  ## Writing with AI
116
123
 
117
- The admin panel's **AI** tab can draft pages, rewrite blocks and fill in events and news stories. Each editor picks an AI service there. Claude and some others need the editor's own API key and charge for use; there are free options, including copying the request into a chat app such as Claude.ai. To offer only some services, or to turn the assistant off, see `ai` in [Goodfellow's README](https://github.com/chartung17/goodfellow-cms#ai-services).
124
+ The admin panel's **AI** tab can draft pages, rewrite blocks and fill in events and news stories. Each editor picks an AI service there. Claude and some others need the editor's own API key and charge for use; there are free options, including copying the request into a chat app such as Claude.ai. To offer only some services, or to turn the assistant off, see `ai` in [Configuration](https://goodfellow-cms.github.io/goodfellow-cms/docs/configuration).
118
125
 
119
126
  ## Publishing
120
127
 
@@ -1,5 +1,10 @@
1
1
  {
2
2
  "version": 1,
3
+ "calendar": {
4
+ "place": "place",
5
+ "summary": "summary",
6
+ "when": "when"
7
+ },
3
8
  "entryName": "Event",
4
9
  "fields": [
5
10
  {
@@ -9,17 +14,11 @@
9
14
  "required": true
10
15
  },
11
16
  {
12
- "type": "date",
13
- "label": "Date",
14
- "name": "date",
17
+ "type": "event",
18
+ "label": "Date and time",
19
+ "name": "when",
15
20
  "required": true
16
21
  },
17
- {
18
- "type": "text",
19
- "hint": "Such as 7:00 pm, or 11:00 am to 5:00 pm.",
20
- "label": "Time",
21
- "name": "time"
22
- },
23
22
  {
24
23
  "type": "text",
25
24
  "hint": "Such as the church or the parish hall.",
@@ -46,7 +45,7 @@
46
45
  "name": "Events",
47
46
  "path": "/events/{slug}",
48
47
  "sort": {
49
- "field": "date",
48
+ "field": "when",
50
49
  "order": "asc"
51
50
  },
52
51
  "template": {
@@ -64,7 +63,7 @@
64
63
  "props": {
65
64
  "id": "EntryField-date",
66
65
  "className": "",
67
- "field": "date",
66
+ "field": "when",
68
67
  "style": "small"
69
68
  }
70
69
  },
@@ -86,15 +85,6 @@
86
85
  "direction": "row",
87
86
  "gap": "lg",
88
87
  "items": [
89
- {
90
- "type": "EntryField",
91
- "props": {
92
- "id": "EntryField-time",
93
- "className": "",
94
- "field": "time",
95
- "style": "text"
96
- }
97
- },
98
88
  {
99
89
  "type": "EntryField",
100
90
  "props": {
@@ -109,6 +99,15 @@
109
99
  "wrap": true
110
100
  }
111
101
  },
102
+ {
103
+ "type": "AddToCalendar",
104
+ "props": {
105
+ "id": "AddToCalendar-event",
106
+ "addLabel": "Add to calendar",
107
+ "className": "mt-4",
108
+ "otherCalendarsLabel": "Apple Calendar and others"
109
+ }
110
+ },
112
111
  {
113
112
  "type": "EntryField",
114
113
  "props": {
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "version": 1,
3
3
  "fields": {
4
- "date": "2026-12-09",
5
4
  "image": "/media/candles.svg",
6
5
  "place": "Church",
7
6
  "summary": "Prepare for Christmas with a short service and individual confession, with several priests available.",
8
7
  "text": "<p>The service begins with readings and an examination of conscience, followed by the chance to go to confession. It usually ends by 8:30 pm.</p>",
9
- "time": "7:00 pm",
10
- "title": "Advent penance service"
8
+ "title": "Advent penance service",
9
+ "when": {
10
+ "end": "2026-12-09T20:30",
11
+ "start": "2026-12-09T19:00"
12
+ }
11
13
  }
12
14
  }
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "version": 1,
3
3
  "fields": {
4
- "date": "2026-11-02",
5
4
  "image": "/media/candles.svg",
6
5
  "place": "Church",
7
6
  "summary": "On All Souls' Day, we pray for parishioners and loved ones who have died this year.",
8
7
  "text": "<p>Families of those whose funerals were held at St. Joseph this year are invited to light a candle in their memory. Anyone may add a name to the Book of Remembrance at the back of the church.</p>",
9
- "time": "7:00 pm",
10
- "title": "Mass of Remembrance"
8
+ "title": "Mass of Remembrance",
9
+ "when": {
10
+ "end": "2026-11-02T20:00",
11
+ "start": "2026-11-02T19:00"
12
+ }
11
13
  }
12
14
  }
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "version": 1,
3
3
  "fields": {
4
- "date": "2026-12-13",
5
4
  "image": "/media/gathering.svg",
6
5
  "place": "Church",
7
6
  "summary": "The parish choir and children's choir sing carols old and new. Free, with a collection for the food pantry.",
8
7
  "text": "<p>Bring family and friends for an afternoon of carols, followed by hot chocolate in the parish hall.</p>",
9
- "time": "3:00 pm",
10
- "title": "Christmas concert"
8
+ "title": "Christmas concert",
9
+ "when": {
10
+ "end": "2026-12-13T16:30",
11
+ "start": "2026-12-13T15:00"
12
+ }
11
13
  }
12
14
  }
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "version": 1,
3
3
  "fields": {
4
- "date": "2026-10-17",
5
4
  "image": "/media/gathering.svg",
6
5
  "place": "Church grounds",
7
6
  "summary": "Food, games, music and a bake sale for the whole family.",
8
7
  "text": "<p>Our biggest day of the year! There's a barbecue lunch, games and face painting for children, live music in the afternoon and the famous bake sale.</p><p>Volunteers are always welcome: sign up after any weekend Mass.</p>",
9
- "time": "11:00 am to 5:00 pm",
10
- "title": "Fall festival"
8
+ "title": "Fall festival",
9
+ "when": {
10
+ "end": "2026-10-17T17:00",
11
+ "start": "2026-10-17T11:00"
12
+ }
11
13
  }
12
14
  }
@@ -0,0 +1,23 @@
1
+ {
2
+ "version": 1,
3
+ "fields": {
4
+ "image": "/media/gathering.svg",
5
+ "place": "Parish hall",
6
+ "summary": "Games, food and conversation for high school students, every Wednesday during the school year.",
7
+ "text": "<p>All high school students are welcome, whether or not they're parishioners. There's no youth group the day before Thanksgiving or over the Christmas break.</p>",
8
+ "title": "Youth group",
9
+ "when": {
10
+ "end": "2026-09-09T20:30",
11
+ "repeat": {
12
+ "every": "week",
13
+ "skip": [
14
+ "2026-11-25",
15
+ "2026-12-23",
16
+ "2026-12-30"
17
+ ],
18
+ "until": "2027-06-09"
19
+ },
20
+ "start": "2026-09-09T19:00"
21
+ }
22
+ }
23
+ }
@@ -20,6 +20,30 @@
20
20
  "label": "Summary",
21
21
  "name": "summary"
22
22
  },
23
+ {
24
+ "type": "tags",
25
+ "hint": "News pages list stories by topic.",
26
+ "label": "Topics",
27
+ "name": "topics",
28
+ "options": [
29
+ {
30
+ "label": "Parish life",
31
+ "value": "parish-life"
32
+ },
33
+ {
34
+ "label": "Youth",
35
+ "value": "youth"
36
+ },
37
+ {
38
+ "label": "Outreach",
39
+ "value": "outreach"
40
+ },
41
+ {
42
+ "label": "Music",
43
+ "value": "music"
44
+ }
45
+ ]
46
+ },
23
47
  {
24
48
  "type": "image",
25
49
  "label": "Picture",
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": 1,
3
+ "fields": {
4
+ "date": "2026-07-19",
5
+ "image": "/media/placeholder.svg",
6
+ "summary": "After a summer of scaffolding, the bells ring again every Sunday morning.",
7
+ "text": "<p>Thank you for your patience while the tower was repaired, and to everyone who gave to the building fund to make it possible.</p>",
8
+ "title": "Bell tower repairs are finished",
9
+ "topics": [
10
+ "parish-life"
11
+ ]
12
+ }
13
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "version": 1,
3
+ "fields": {
4
+ "date": "2026-09-14",
5
+ "image": "/media/placeholder.svg",
6
+ "summary": "Six new singers joined the parish choir this fall, and there is room for more.",
7
+ "text": "<p>The choir rehearses on Thursday evenings in the church. No experience is needed, only a love of singing. Speak to the music director after any Sunday Mass.</p>",
8
+ "title": "Choir welcomes new voices",
9
+ "topics": [
10
+ "music",
11
+ "parish-life"
12
+ ]
13
+ }
14
+ }
@@ -5,6 +5,9 @@
5
5
  "image": "/media/placeholder.svg",
6
6
  "summary": "Parishioners filled the shelves of the local food pantry for the months ahead.",
7
7
  "text": "<p>Thank you to everyone who brought food, sorted donations and drove deliveries. The pantry is open every Tuesday and Thursday, and always needs volunteers.</p>",
8
- "title": "Thank you for supporting the food drive"
8
+ "title": "Thank you for supporting the food drive",
9
+ "topics": [
10
+ "outreach"
11
+ ]
9
12
  }
10
13
  }
@@ -5,6 +5,9 @@
5
5
  "image": "/media/church.svg",
6
6
  "summary": "Mass times, events and the weekly bulletin are now easier to find, on any phone or computer.",
7
7
  "text": "<p>The parish office can now keep the website up to date themselves, so you'll always find this week's times and news here. Something missing? Let us know.</p>",
8
- "title": "Welcome to our new website"
8
+ "title": "Welcome to our new website",
9
+ "topics": [
10
+ "parish-life"
11
+ ]
9
12
  }
10
13
  }
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": 1,
3
+ "fields": {
4
+ "date": "2026-10-04",
5
+ "image": "/media/placeholder.svg",
6
+ "summary": "Bring clean, warm coats for children and adults to the parish hall in October.",
7
+ "text": "<p>Coats go to families in the neighborhood through the parish outreach team. Hats, gloves and scarves are welcome too.</p>",
8
+ "title": "Winter coat collection begins",
9
+ "topics": [
10
+ "outreach"
11
+ ]
12
+ }
13
+ }
@@ -5,6 +5,9 @@
5
5
  "image": "/media/gathering.svg",
6
6
  "summary": "High school students meet on Sunday evenings after the 6:00 pm Mass, with pizza.",
7
7
  "text": "<p>Every week there's food, games, conversation and a short reflection. New members are always welcome, and parents can contact the parish office for details.</p>",
8
- "title": "Youth group starts again"
8
+ "title": "Youth group starts again",
9
+ "topics": [
10
+ "youth"
11
+ ]
9
12
  }
10
13
  }
@@ -0,0 +1,14 @@
1
+ {
2
+ "version": 1,
3
+ "fields": {
4
+ "date": "2026-06-21",
5
+ "image": "/media/placeholder.svg",
6
+ "summary": "Twenty young people painted, gardened and cooked lunch for neighbors.",
7
+ "text": "<p>The youth group plans a service day every summer. Parents and parishioners who would like to help next year can contact the parish office.</p>",
8
+ "title": "Teens spend a day serving the neighborhood",
9
+ "topics": [
10
+ "youth",
11
+ "outreach"
12
+ ]
13
+ }
14
+ }
@@ -38,6 +38,10 @@
38
38
  "href": "/events",
39
39
  "label": "Events"
40
40
  },
41
+ {
42
+ "href": "/calendar",
43
+ "label": "Calendar"
44
+ },
41
45
  {
42
46
  "href": "/news",
43
47
  "label": "News"
@@ -76,20 +76,63 @@
76
76
  }
77
77
  },
78
78
  {
79
- "type": "CollectionList",
79
+ "type": "CollectionLoop",
80
80
  "props": {
81
- "id": "CollectionList-staff",
81
+ "id": "CollectionLoop-staff",
82
+ "allLabel": "All",
83
+ "choicePages": "",
82
84
  "className": "",
83
85
  "collection": "staff",
84
86
  "columns": "4",
85
87
  "dateField": "",
88
+ "design": [
89
+ {
90
+ "type": "Image",
91
+ "props": {
92
+ "id": "Image-staff-photo",
93
+ "alt": "",
94
+ "aspect": "square",
95
+ "caption": "",
96
+ "className": "",
97
+ "rounded": true,
98
+ "src": "{photo}"
99
+ }
100
+ },
101
+ {
102
+ "type": "Heading",
103
+ "props": {
104
+ "id": "Heading-staff-name",
105
+ "align": "left",
106
+ "className": "text-lg",
107
+ "level": "h3",
108
+ "text": "{title}"
109
+ }
110
+ },
111
+ {
112
+ "type": "Text",
113
+ "props": {
114
+ "id": "Text-staff-role",
115
+ "align": "left",
116
+ "className": "text-muted-foreground",
117
+ "content": "<p>{role}</p>"
118
+ }
119
+ }
120
+ ],
86
121
  "emptyText": "",
87
- "imageField": "photo",
88
- "layout": "cards",
122
+ "filterField": "",
123
+ "filterValue": "",
124
+ "gap": "md",
125
+ "items": [],
89
126
  "limit": 0,
127
+ "linkToPage": false,
128
+ "nextLabel": "Next",
90
129
  "order": "default",
130
+ "pageTitle": "Page {number}",
131
+ "pagesLabel": "Pages",
132
+ "paginate": false,
133
+ "previousLabel": "Previous",
91
134
  "show": "all",
92
- "summaryField": "role"
135
+ "sortField": ""
93
136
  }
94
137
  }
95
138
  ],
@@ -0,0 +1,59 @@
1
+ {
2
+ "version": 1,
3
+ "data": {
4
+ "content": [
5
+ {
6
+ "type": "Section",
7
+ "props": {
8
+ "id": "Section-calendar",
9
+ "background": "none",
10
+ "backgroundImage": "",
11
+ "className": "",
12
+ "content": [
13
+ {
14
+ "type": "Heading",
15
+ "props": {
16
+ "id": "Heading-calendar",
17
+ "align": "left",
18
+ "className": "mb-8",
19
+ "level": "h1",
20
+ "text": "Calendar"
21
+ }
22
+ },
23
+ {
24
+ "type": "Calendar",
25
+ "props": {
26
+ "id": "Calendar-month",
27
+ "addLabel": "Add to calendar",
28
+ "className": "",
29
+ "collection": "events",
30
+ "days": 90,
31
+ "emptyText": "Nothing is planned this month yet.",
32
+ "feed": "",
33
+ "limit": 0,
34
+ "monthsAfter": 12,
35
+ "monthsBefore": 1,
36
+ "nextLabel": "Next month",
37
+ "otherCalendarsLabel": "Apple Calendar and others",
38
+ "previousLabel": "Previous month",
39
+ "subscribeLabel": "Subscribe to the parish calendar",
40
+ "view": "month",
41
+ "weekStart": "sunday"
42
+ }
43
+ }
44
+ ],
45
+ "padding": "lg",
46
+ "width": "normal"
47
+ }
48
+ }
49
+ ],
50
+ "root": {
51
+ "props": {
52
+ "className": "",
53
+ "description": "St. Joseph Parish's events, a month at a time.",
54
+ "image": "",
55
+ "title": "Calendar"
56
+ }
57
+ }
58
+ }
59
+ }