@port60/template-kit 0.1.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.
- package/LICENSE +21 -0
- package/README.md +50 -0
- package/bin/cli.mjs +58 -0
- package/package.json +33 -0
- package/src/commands/create.mjs +73 -0
- package/src/commands/dev.mjs +56 -0
- package/src/commands/packageCmd.mjs +25 -0
- package/src/commands/validate.mjs +38 -0
- package/src/lib/agentsMd.mjs +81 -0
- package/src/lib/artifactFiles.mjs +28 -0
- package/src/lib/zip.mjs +77 -0
- package/src/vendor/contract/v1/content-bounds.json +117 -0
- package/src/vendor/contract/v1/context.json +534 -0
- package/src/vendor/contract/v1/dialect.json +39 -0
- package/src/vendor/contract/v1/fonts.json +67 -0
- package/src/vendor/contract/v1/islands.json +95 -0
- package/src/vendor/contract/v1/manifest.schema.json +144 -0
- package/src/vendor/contract/v1/sections.json +558 -0
- package/src/vendor/contract/v1/tokens.json +26 -0
- package/src/vendor/engine/budgets.mjs +14 -0
- package/src/vendor/engine/dialect.mjs +77 -0
- package/src/vendor/validator/preview.mjs +111 -0
- package/src/vendor/validator/validate.mjs +265 -0
- package/starter/assets/theme.css +43 -0
- package/starter/layout.liquid +75 -0
- package/starter/manifest.json +40 -0
- package/starter/sections/cta.liquid +12 -0
- package/starter/sections/hero.liquid +7 -0
- package/starter/sections/values.liquid +14 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "The platform's functional islands — the app-block table. A template PLACES an island with {% island 'name' %}; the platform renders, hydrates, upgrades and patches it. The stylingApi lists the STABLE class names a template may target with CSS; anything not listed is internal and may change without notice.",
|
|
3
|
+
"islands": [
|
|
4
|
+
{
|
|
5
|
+
"name": "donation_widget",
|
|
6
|
+
"label": "Donation widget",
|
|
7
|
+
"status": "available",
|
|
8
|
+
"description": "The full donation flow for the tenant's quick-give cause: suggested amounts, custom amount, donor details, Gift Aid opt-in, payment. All payment/compliance behaviour is platform-owned.",
|
|
9
|
+
"params": [],
|
|
10
|
+
"stylingApi": [
|
|
11
|
+
".donate-card",
|
|
12
|
+
".donate-head",
|
|
13
|
+
".donate-sub",
|
|
14
|
+
".freq-tabs",
|
|
15
|
+
".freq-tab",
|
|
16
|
+
".amount-grid",
|
|
17
|
+
".amount-option",
|
|
18
|
+
".amount-list",
|
|
19
|
+
".amount-row",
|
|
20
|
+
".giftaid-box",
|
|
21
|
+
".donate-submit",
|
|
22
|
+
".donate-note",
|
|
23
|
+
".donate-success"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "member_menu",
|
|
28
|
+
"label": "Port60 ID sign-in / account menu",
|
|
29
|
+
"status": "available",
|
|
30
|
+
"description": "The branded Port60 ID entry point: the sign-in button (popup flow) for guests, the account pill (Members area / Sign out) for signed-in members. Renders NOTHING when the tenant doesn't allow member sign-ups. The identity brand and popup behaviour are platform-owned and identical across every template — place it in your header's nav; never rebuild it.",
|
|
31
|
+
"params": [],
|
|
32
|
+
"stylingApi": [
|
|
33
|
+
".nav-p60-signin",
|
|
34
|
+
".nav-account",
|
|
35
|
+
".nav-account-toggle",
|
|
36
|
+
".nav-account-menu",
|
|
37
|
+
".p60-mark"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "events_carousel",
|
|
42
|
+
"label": "Events carousel",
|
|
43
|
+
"status": "available",
|
|
44
|
+
"description": "The rotating showcase of published ticketed events. Renders nothing when the tenant has no matching published content.",
|
|
45
|
+
"params": [],
|
|
46
|
+
"stylingApi": [
|
|
47
|
+
".events-carousel",
|
|
48
|
+
".carousel-slide",
|
|
49
|
+
".carousel-caption",
|
|
50
|
+
".carousel-dots",
|
|
51
|
+
".carousel-dot"
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "whats_on_strip",
|
|
56
|
+
"label": "What's-on strip",
|
|
57
|
+
"status": "available",
|
|
58
|
+
"description": "The slim banner of upcoming info events. Renders nothing when the tenant has no matching published content.",
|
|
59
|
+
"params": [],
|
|
60
|
+
"stylingApi": [
|
|
61
|
+
".info-events-bar",
|
|
62
|
+
".info-events-inner",
|
|
63
|
+
".info-event-chip"
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"name": "latest_articles",
|
|
68
|
+
"label": "Latest articles",
|
|
69
|
+
"status": "available",
|
|
70
|
+
"description": "A strip of the most recent published articles. Renders nothing when the tenant has no matching published content.",
|
|
71
|
+
"params": [],
|
|
72
|
+
"stylingApi": [
|
|
73
|
+
".article-grid",
|
|
74
|
+
".article-card",
|
|
75
|
+
".article-card-body",
|
|
76
|
+
".article-strip-cta"
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "course_enrol",
|
|
81
|
+
"label": "Course enrolment widget",
|
|
82
|
+
"status": "available",
|
|
83
|
+
"description": "The member-gated course enrolment journey (schedule options, household picker, payment, seat holds) for the course the page addresses. Only meaningful on the course page template (pages/course.liquid) — place it where your layout wants the purchase column (left rail, right rail, or below the content); position in your source is position on the page. Everything inside is platform-owned; it renders a standard sold-out note when no places remain (branch on course.soldOut if you want your own tag elsewhere).",
|
|
84
|
+
"params": [],
|
|
85
|
+
"stylingApi": [
|
|
86
|
+
".course-enrol",
|
|
87
|
+
".course-variant-list",
|
|
88
|
+
".course-subject-list",
|
|
89
|
+
".course-summary",
|
|
90
|
+
".course-pay-panel",
|
|
91
|
+
".course-soldout-note"
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://developers.port60.co.uk/schemas/template-manifest-v1.json",
|
|
4
|
+
"title": "Port60 template manifest (contract v1)",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["name", "version", "format", "supports"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"name": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"pattern": "^[a-z][a-z0-9-]{1,48}[a-z0-9]$",
|
|
12
|
+
"description": "The template's identity — lowercase, hyphenated, stable across versions."
|
|
13
|
+
},
|
|
14
|
+
"version": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"pattern": "^\\d+\\.\\d+\\.\\d+$",
|
|
17
|
+
"description": "Semver. Versions are IMMUTABLE once published — a fix is a new version."
|
|
18
|
+
},
|
|
19
|
+
"format": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"enum": ["port60-liquid@1"],
|
|
22
|
+
"description": "The dialect/contract major this template is written against."
|
|
23
|
+
},
|
|
24
|
+
"label": { "type": "string", "maxLength": 60, "description": "Human-readable name shown in pickers." },
|
|
25
|
+
"description": { "type": "string", "maxLength": 300 },
|
|
26
|
+
"changelog": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"maxLength": 300,
|
|
29
|
+
"description": "One human line describing what THIS version changed — shown on the Appearance update nudge."
|
|
30
|
+
},
|
|
31
|
+
"supports": {
|
|
32
|
+
"type": "object",
|
|
33
|
+
"additionalProperties": false,
|
|
34
|
+
"required": ["pages", "sections"],
|
|
35
|
+
"properties": {
|
|
36
|
+
"pages": {
|
|
37
|
+
"type": "array",
|
|
38
|
+
"items": { "type": "string", "enum": ["home", "about"] },
|
|
39
|
+
"minItems": 1,
|
|
40
|
+
"uniqueItems": true,
|
|
41
|
+
"description": "The pages this template renders (grows with the contract)."
|
|
42
|
+
},
|
|
43
|
+
"sections": {
|
|
44
|
+
"type": "array",
|
|
45
|
+
"items": { "type": "string" },
|
|
46
|
+
"minItems": 1,
|
|
47
|
+
"uniqueItems": true,
|
|
48
|
+
"description": "Section types this template ships renderers for (sections/{type}.liquid). Unsupported types are omitted at render — never an error."
|
|
49
|
+
},
|
|
50
|
+
"islands": {
|
|
51
|
+
"type": "array",
|
|
52
|
+
"items": { "type": "string" },
|
|
53
|
+
"uniqueItems": true,
|
|
54
|
+
"default": [],
|
|
55
|
+
"description": "Islands this template places. Every {% island %} name must be listed here AND exist in the platform island registry."
|
|
56
|
+
},
|
|
57
|
+
"layout": {
|
|
58
|
+
"type": "boolean",
|
|
59
|
+
"default": false,
|
|
60
|
+
"description": "True when the template ships layout.liquid and owns the page chrome (header/nav/footer). The platform still owns <head>, consent, and identity — see the layouts guide."
|
|
61
|
+
},
|
|
62
|
+
"pageTemplates": {
|
|
63
|
+
"type": "array",
|
|
64
|
+
"items": { "type": "string", "enum": ["events", "course"] },
|
|
65
|
+
"uniqueItems": true,
|
|
66
|
+
"default": [],
|
|
67
|
+
"description": "Pages whose DISPLAY body this template renders itself (pages/{page}.liquid) with that page's documented data context. Transactional views stay platform-owned; without an entry the platform body renders inside your chrome."
|
|
68
|
+
},
|
|
69
|
+
"worship": {
|
|
70
|
+
"type": "boolean",
|
|
71
|
+
"default": false,
|
|
72
|
+
"description": "True when the layout renders the `worship` context (the prayer/service-times rail). Declared honesty: the choosers badge worship-enabled tenants toward looks that show their times, and warn on looks that don't. Requires supports.layout; the layout must actually branch on `worship`."
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"fonts": {
|
|
77
|
+
"type": "array",
|
|
78
|
+
"items": {
|
|
79
|
+
"type": "string",
|
|
80
|
+
"pattern": "^https://fonts\\.googleapis\\.com/css2\\?"
|
|
81
|
+
},
|
|
82
|
+
"default": [],
|
|
83
|
+
"description": "Webfont stylesheet URLs the platform loads in <head> (with preconnects, never a CSS @import). Google Fonts css2 URLs only."
|
|
84
|
+
},
|
|
85
|
+
"looks": {
|
|
86
|
+
"type": "array",
|
|
87
|
+
"maxItems": 8,
|
|
88
|
+
"items": {
|
|
89
|
+
"type": "object",
|
|
90
|
+
"additionalProperties": false,
|
|
91
|
+
"required": ["name", "values"],
|
|
92
|
+
"properties": {
|
|
93
|
+
"name": {
|
|
94
|
+
"type": "string",
|
|
95
|
+
"maxLength": 40,
|
|
96
|
+
"description": "The look's evocative, author-chosen name — shown as a one-click chip in Appearance."
|
|
97
|
+
},
|
|
98
|
+
"values": {
|
|
99
|
+
"type": "object",
|
|
100
|
+
"minProperties": 1,
|
|
101
|
+
"propertyNames": { "pattern": "^[a-zA-Z][a-zA-Z0-9]{0,39}$" },
|
|
102
|
+
"additionalProperties": { "type": "string" },
|
|
103
|
+
"description": "Knob key → value. Every key must be a declared settings knob; select values must be listed options; font values must be catalogue families."
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"default": [],
|
|
108
|
+
"description": "One-click LOOKS: author-named bundles of knob values (scheme + fonts + width…) applied together. Everything remains individually adjustable afterwards."
|
|
109
|
+
},
|
|
110
|
+
"settings": {
|
|
111
|
+
"type": "object",
|
|
112
|
+
"additionalProperties": false,
|
|
113
|
+
"properties": {
|
|
114
|
+
"schema": {
|
|
115
|
+
"type": "array",
|
|
116
|
+
"items": {
|
|
117
|
+
"type": "object",
|
|
118
|
+
"additionalProperties": false,
|
|
119
|
+
"required": ["key", "kind", "label"],
|
|
120
|
+
"properties": {
|
|
121
|
+
"key": { "type": "string", "pattern": "^[a-zA-Z][a-zA-Z0-9]{0,39}$" },
|
|
122
|
+
"kind": { "type": "string", "enum": ["color", "select", "toggle", "font"] },
|
|
123
|
+
"label": { "type": "string", "maxLength": 60 },
|
|
124
|
+
"default": {},
|
|
125
|
+
"options": { "type": "array", "items": { "type": "string" } },
|
|
126
|
+
"group": {
|
|
127
|
+
"type": "string",
|
|
128
|
+
"enum": ["typography", "looks"],
|
|
129
|
+
"description": "Where the admin surfaces this knob: 'typography' → the Typography section beside the font slots; 'looks' → the Looks section with the one-click bundles (colour schemes and accent dials belong there — and ungrouped color knobs plus a knob keyed 'scheme' default there anyway); other ungrouped knobs render under Template options."
|
|
130
|
+
},
|
|
131
|
+
"weights": {
|
|
132
|
+
"type": "array",
|
|
133
|
+
"items": { "type": "integer", "minimum": 100, "maximum": 1000 },
|
|
134
|
+
"uniqueItems": true,
|
|
135
|
+
"description": "FONT knobs only: the weights this template's typographic system uses for the slot. The host requests these for the tenant's chosen family (clamped to the family's real weights). The tenant picks the FAMILY; weights, sizes and tracking stay template-owned."
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
"description": "The template's own theming knobs (colour schemes etc.) — rendered as an editor in Appearance/get-started; values land in site-config config.theme."
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|