@514sid/signagekit 0.0.0-stage → 0.0.2

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 (95) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/LICENSE +44 -0
  3. package/README.md +106 -2
  4. package/bin/signagekit.js +4 -0
  5. package/dist/chunks/chart-WERjiRho.js +2 -0
  6. package/dist/chunks/empty--6iNLsra.js +2 -0
  7. package/dist/chunks/icon-paths-Dl0Rqja7.js +2 -0
  8. package/dist/chunks/lists-qOUpM5us.js +2 -0
  9. package/dist/chunks/measures-D0av_G5P.js +2 -0
  10. package/dist/chunks/media-DI35kQ5D.js +3 -0
  11. package/dist/chunks/qr-size-Dq23do6_.js +2 -0
  12. package/dist/chunks/ready-Boq20M-G.js +2 -0
  13. package/dist/chunks/share-D64VSp1B.js +2 -0
  14. package/dist/chunks/stat-DEE3meII.js +2 -0
  15. package/dist/chunks/time-KYYBrpD9.js +2 -0
  16. package/dist/cli.js +10 -0
  17. package/dist/index.js +3 -0
  18. package/dist/style.css +2 -0
  19. package/dist/types/alert.d.ts +20 -0
  20. package/dist/types/binds.d.ts +6 -0
  21. package/dist/types/chart.d.ts +16 -0
  22. package/dist/types/check.d.ts +31 -0
  23. package/dist/types/checks.d.ts +36 -0
  24. package/dist/types/colors.d.ts +18 -0
  25. package/dist/types/components.d.ts +13 -0
  26. package/dist/types/cycle-fit.d.ts +6 -0
  27. package/dist/types/data.d.ts +19 -0
  28. package/dist/types/empty.d.ts +6 -0
  29. package/dist/types/fit.d.ts +3 -0
  30. package/dist/types/flow.d.ts +7 -0
  31. package/dist/types/icon-paths.d.ts +2 -0
  32. package/dist/types/icon.d.ts +7 -0
  33. package/dist/types/icons.d.ts +3 -0
  34. package/dist/types/index.d.ts +20 -0
  35. package/dist/types/lists.d.ts +29 -0
  36. package/dist/types/measure.d.ts +4 -0
  37. package/dist/types/measures.d.ts +22 -0
  38. package/dist/types/media.d.ts +15 -0
  39. package/dist/types/mount.d.ts +45 -0
  40. package/dist/types/parse.d.ts +11 -0
  41. package/dist/types/qr-size.d.ts +2 -0
  42. package/dist/types/ready.d.ts +3 -0
  43. package/dist/types/share.d.ts +33 -0
  44. package/dist/types/sizes.d.ts +15 -0
  45. package/dist/types/specs.d.ts +7 -0
  46. package/dist/types/stat.d.ts +38 -0
  47. package/dist/types/table-fit.d.ts +8 -0
  48. package/dist/types/table.d.ts +11 -0
  49. package/dist/types/time.d.ts +28 -0
  50. package/dist/types/trend-fit.d.ts +14 -0
  51. package/dist/types/type-scale.d.ts +10 -0
  52. package/dist/types/types.d.ts +271 -0
  53. package/dist/types/validate-layout.d.ts +2 -0
  54. package/dist/types/validate.d.ts +7 -0
  55. package/dist/types/version.d.ts +24 -0
  56. package/dist/types/views.d.ts +29 -0
  57. package/docs/api.md +106 -0
  58. package/docs/assistants.md +55 -0
  59. package/docs/format.md +183 -0
  60. package/docs/getting-started.md +77 -0
  61. package/docs/preview.md +84 -0
  62. package/examples/clinic-queue/data.json +17 -0
  63. package/examples/clinic-queue/layout.yml +43 -0
  64. package/examples/fire-alarm/data.yml +23 -0
  65. package/examples/fire-alarm/layout.yml +30 -0
  66. package/examples/gym-classes/data.yml +17 -0
  67. package/examples/gym-classes/layout.yml +47 -0
  68. package/examples/hotel-lobby/data.yml +2 -0
  69. package/examples/hotel-lobby/layout.yml +29 -0
  70. package/examples/lunch/data.yml +16 -0
  71. package/examples/lunch/layout.yml +43 -0
  72. package/examples/meeting-room/data.json +19 -0
  73. package/examples/meeting-room/layout.json +107 -0
  74. package/examples/noc-wall/data.yml +18 -0
  75. package/examples/noc-wall/layout.yml +63 -0
  76. package/examples/oee-line/data.yml +25 -0
  77. package/examples/oee-line/layout.yml +55 -0
  78. package/examples/office-air/data.yml +25 -0
  79. package/examples/office-air/layout.yml +71 -0
  80. package/examples/sales-today/data.json +28 -0
  81. package/examples/sales-today/layout.json +62 -0
  82. package/examples/snow-closure/data.yml +28 -0
  83. package/examples/snow-closure/layout.json +35 -0
  84. package/examples/station-departures/data.json +24 -0
  85. package/examples/station-departures/layout.json +34 -0
  86. package/examples/store-promo/data.yml +18 -0
  87. package/examples/store-promo/layout.yml +54 -0
  88. package/examples/storm-banner/data.json +20 -0
  89. package/examples/storm-banner/layout.json +33 -0
  90. package/examples/trading-floor/data.json +23 -0
  91. package/examples/trading-floor/layout.json +65 -0
  92. package/examples/warehouse/data.json +20 -0
  93. package/examples/warehouse/layout.json +50 -0
  94. package/package.json +100 -4
  95. package/schema.json +962 -0
@@ -0,0 +1,107 @@
1
+ {
2
+ "version": 1,
3
+ "colors": {
4
+ "scheme": "dark",
5
+ "accent": "#f59e0b"
6
+ },
7
+ "layout": {
8
+ "design": "portrait",
9
+ "flow": [
10
+ {
11
+ "zone": "room",
12
+ "span": 8,
13
+ "height": "200px"
14
+ },
15
+ {
16
+ "zone": "clock",
17
+ "span": 4,
18
+ "height": "200px"
19
+ },
20
+ {
21
+ "zone": "status",
22
+ "span": 12,
23
+ "height": 2
24
+ },
25
+ {
26
+ "zone": "ends",
27
+ "span": 6,
28
+ "height": 1.2
29
+ },
30
+ {
31
+ "zone": "book",
32
+ "span": 6,
33
+ "height": 1.2
34
+ },
35
+ {
36
+ "zone": "agenda",
37
+ "span": 12,
38
+ "height": 4
39
+ },
40
+ {
41
+ "zone": "rules",
42
+ "span": 12,
43
+ "height": "150px"
44
+ }
45
+ ]
46
+ },
47
+ "zones": {
48
+ "room": {
49
+ "type": "heading",
50
+ "title": "Meeting room",
51
+ "text": {
52
+ "bind": "/room/name"
53
+ }
54
+ },
55
+ "clock": {
56
+ "type": "clock",
57
+ "surface": "raised",
58
+ "hour12": false
59
+ },
60
+ "status": {
61
+ "type": "stat",
62
+ "title": {
63
+ "bind": "/room/floor"
64
+ },
65
+ "value": {
66
+ "bind": "/status/text"
67
+ },
68
+ "label": {
69
+ "bind": "/status/label"
70
+ },
71
+ "state": {
72
+ "bind": "/status/state"
73
+ }
74
+ },
75
+ "ends": {
76
+ "type": "countdown",
77
+ "surface": "raised",
78
+ "title": "Current meeting",
79
+ "to": {
80
+ "bind": "/status/ends_at"
81
+ },
82
+ "label": "left"
83
+ },
84
+ "book": {
85
+ "type": "qr",
86
+ "title": "Book this room",
87
+ "value": {
88
+ "bind": "/room/book_url"
89
+ },
90
+ "label": "Scan to book"
91
+ },
92
+ "agenda": {
93
+ "type": "schedule",
94
+ "title": "Next up",
95
+ "rows": 6,
96
+ "items": {
97
+ "bind": "/agenda"
98
+ }
99
+ },
100
+ "rules": {
101
+ "type": "text",
102
+ "surface": "accent",
103
+ "text": "Seats 10. Please wipe the whiteboard and take your cups when you leave.",
104
+ "fit": true
105
+ }
106
+ }
107
+ }
@@ -0,0 +1,18 @@
1
+ alert: ''
2
+ kpi:
3
+ error_rate: 0.31
4
+ error_state: warning
5
+ p99: 412
6
+ p99_spark: [530, 510, 498, 470, 455, 430, 412]
7
+ svc:
8
+ cdn: good
9
+ auth: good
10
+ api: warning
11
+ payments: good
12
+ db: warning
13
+ vpn: danger
14
+ incidents:
15
+ - [SEV2, VPN ams-02 saturated, 41 m]
16
+ - [SEV3, eu-west API over SLO, 36 m]
17
+ - [SEV3, Replica lag on pg-replica-04, 22 m]
18
+ - [SEV4, Certificate expires in 9 days, 3 d]
@@ -0,0 +1,63 @@
1
+ # yaml-language-server: $schema=https://signagekit.514sid.com/schema.json
2
+ # Network operations wall: six zones, dark.
3
+ colors:
4
+ scheme: dark
5
+
6
+ layout:
7
+ flow:
8
+ - { zone: head, span: 8, height: 120px }
9
+ - { zone: clock, span: 4, height: 120px }
10
+ - { zone: err, span: 3, height: 1 }
11
+ - { zone: p99, span: 3, height: 1 }
12
+ - { zone: svc, span: 6, height: 1 }
13
+ - { zone: inc, span: 12, height: 1 }
14
+
15
+ alert:
16
+ text: { bind: /alert }
17
+ title: Major incident
18
+ state: danger
19
+
20
+ zones:
21
+ head:
22
+ type: heading
23
+ title: Network operations
24
+ text: Global edge and core
25
+ clock:
26
+ type: clock
27
+ surface: raised
28
+ show_date: true
29
+ hour12: false
30
+ err:
31
+ type: stat
32
+ title: Error rate
33
+ value: { bind: /kpi/error_rate }
34
+ unit: '%'
35
+ state: { bind: /kpi/error_state }
36
+ trend: up
37
+ delta: '+0.04'
38
+ good_when: down
39
+ p99:
40
+ type: stat
41
+ title: p99 latency
42
+ value: { bind: /kpi/p99 }
43
+ unit: ms
44
+ trend: down
45
+ delta: -18 ms
46
+ good_when: down
47
+ spark: { bind: /kpi/p99_spark }
48
+ svc:
49
+ type: status
50
+ title: Services
51
+ items:
52
+ - { label: Edge CDN, state: { bind: /svc/cdn } }
53
+ - { label: Sign-in, state: { bind: /svc/auth } }
54
+ - { label: Core API, state: { bind: /svc/api }, note: eu-west slow }
55
+ - { label: Payments, state: { bind: /svc/payments } }
56
+ - { label: Postgres, state: { bind: /svc/db }, note: lag 4 s }
57
+ - { label: Office VPN, state: { bind: /svc/vpn }, note: down }
58
+ inc:
59
+ type: table
60
+ title: Open incidents
61
+ columns: [Sev, Incident, Age]
62
+ align: [start, start, end]
63
+ rows: { bind: /incidents }
@@ -0,0 +1,25 @@
1
+ # Every value is read as text.
2
+ oee:
3
+ value: 78.4
4
+ state: warning
5
+ trend: up
6
+ delta: +1.6 pts
7
+ spark: [71, 73, 72, 75, 77, 76, 78.4]
8
+ hourly: [74, 76, 72, 79, 81, 77, 78]
9
+ target: [85, 85, 85, 85, 85, 85, 85]
10
+ hours: ['06:00', '07:00', '08:00', '09:00', '10:00', '11:00', '12:00']
11
+ lines:
12
+ - { label: Line 1 PET 0.5 L, value: 412, max: 480, state: good }
13
+ - { label: Line 2 PET 1.5 L, value: 301, max: 360, state: good }
14
+ - { label: Line 3 glass, value: 188, max: 300, state: warning }
15
+ - { label: Line 4 cans, value: 0, max: 600, state: danger }
16
+ downtime:
17
+ - { label: Changeover, value: 52 }
18
+ - { label: Glue pump, value: 41 }
19
+ - { label: No preforms, value: 27 }
20
+ - { label: Micro stops, value: 19 }
21
+ - { label: CIP cleaning, value: 15 }
22
+ messages:
23
+ - 'Changeover on Line 3 at 13:00, bring format parts'
24
+ - 'Forklift route B closed until 15:00'
25
+ - 'QA sample every 30 min, record on tablet'
@@ -0,0 +1,55 @@
1
+ # yaml-language-server: $schema=https://signagekit.514sid.com/schema.json
2
+ # OEE board for a bottling plant floor, landscape.
3
+ colors:
4
+ scheme: dark
5
+ accent: '#0ea5e9'
6
+
7
+ layout:
8
+ design: landscape
9
+ gap: 2
10
+ flow:
11
+ - { zone: head, span: 9, height: 120px }
12
+ - { zone: clock, span: 3, height: 120px }
13
+ - { zone: oee, span: 4, height: 2 }
14
+ - { zone: trend, span: 8, height: 2 }
15
+ - { zone: lines, span: 6, height: 3 }
16
+ - { zone: downtime, span: 6, height: 3 }
17
+ - { zone: news, height: 100px }
18
+
19
+ zones:
20
+ head: { type: heading, text: Filling hall 2 OEE, surface: raised }
21
+ clock: { type: clock, surface: raised }
22
+ oee:
23
+ type: stat
24
+ title: OEE today
25
+ value: { bind: /oee/value }
26
+ unit: '%'
27
+ state: { bind: /oee/state }
28
+ trend: { bind: /oee/trend }
29
+ delta: { bind: /oee/delta }
30
+ good_when: up
31
+ spark: { bind: /oee/spark }
32
+ trend:
33
+ type: chart
34
+ kind: line
35
+ title: OEE by hour vs target
36
+ labels: { bind: /hours }
37
+ series:
38
+ - { name: OEE, values: { bind: /oee/hourly } }
39
+ - { name: Target, values: { bind: /oee/target } }
40
+ lines:
41
+ type: meters
42
+ title: Line speed
43
+ unit: bpm
44
+ items: { bind: /lines }
45
+ downtime:
46
+ type: bars
47
+ title: Downtime today
48
+ unit: min
49
+ limit: 5
50
+ items: { bind: /downtime }
51
+ news:
52
+ type: cycle
53
+ surface: raised
54
+ seconds: 6
55
+ items: { bind: /messages }
@@ -0,0 +1,25 @@
1
+ # Readings from the floor sensors. Every value in YAML data is read as text.
2
+ floor: Floor 3, east wing
3
+ co2:
4
+ now: 742
5
+ trend: down
6
+ delta: -58 since 10:00
7
+ label: Fresh
8
+ temp:
9
+ now: 21.8
10
+ label: Comfortable
11
+ state: good
12
+ humidity: 46
13
+ rooms:
14
+ - { label: Harbour, value: 1180, max: 1600 }
15
+ - { label: Lighthouse, value: 960, max: 1600 }
16
+ - { label: Quay, value: 812, max: 1600 }
17
+ - { label: Dockside, value: 655, max: 1600 }
18
+ - { label: Pier, value: 540, max: 1600 }
19
+ day:
20
+ hours: ['08:00', '09:00', '10:00', '11:00', '12:00', '13:00', '14:00']
21
+ co2: [520, 690, 800, 940, 1080, 870, 742]
22
+ tips:
23
+ - Harbour is getting stuffy, open the window or take a break
24
+ - Windows on the south side open with the grey handle
25
+ - Plants on this floor are watered on Mondays and Thursdays
@@ -0,0 +1,71 @@
1
+ # yaml-language-server: $schema=https://signagekit.514sid.com/schema.json
2
+ # Air quality on an office floor, for the screen by the kitchen.
3
+ version: 1
4
+ colors:
5
+ scheme: dark
6
+ accent: '#0ea5e9'
7
+
8
+ layout:
9
+ flow:
10
+ - { zone: head, span: 9, height: 130px }
11
+ - { zone: clock, span: 3, height: 130px }
12
+ - { zone: co2, span: 4, height: 2 }
13
+ - { zone: temp, span: 4, height: 2 }
14
+ - { zone: humidity, span: 4, height: 2 }
15
+ - { zone: rooms, span: 5, height: 3 }
16
+ - { zone: today, span: 7, height: 3 }
17
+ - { zone: tips, height: 100px }
18
+
19
+ zones:
20
+ head:
21
+ type: heading
22
+ title: Air quality
23
+ text: { bind: /floor }
24
+ clock:
25
+ type: clock
26
+ surface: raised
27
+ show_date: true
28
+ co2:
29
+ type: stat
30
+ title: CO₂, open plan
31
+ value: { bind: /co2/now }
32
+ unit: ppm
33
+ thresholds: { warning: 1000, danger: 1400 }
34
+ trend: { bind: /co2/trend }
35
+ delta: { bind: /co2/delta }
36
+ good_when: down
37
+ label: { bind: /co2/label }
38
+ temp:
39
+ type: stat
40
+ title: Temperature
41
+ value: { bind: /temp/now }
42
+ unit: °C
43
+ label: { bind: /temp/label }
44
+ state: { bind: /temp/state }
45
+ humidity:
46
+ type: meter
47
+ title: Humidity
48
+ value: { bind: /humidity }
49
+ max: 100
50
+ unit: '%'
51
+ thresholds: { warning: 60, danger: 70 }
52
+ rooms:
53
+ type: meters
54
+ title: CO₂ by meeting room, ppm
55
+ items: { bind: /rooms }
56
+ thresholds: { warning: 1000, danger: 1400 }
57
+ today:
58
+ type: chart
59
+ kind: area
60
+ title: CO₂ today, open plan
61
+ labels: { bind: /day/hours }
62
+ series:
63
+ - name: CO₂
64
+ values: { bind: /day/co2 }
65
+ target: 1000
66
+ target_label: Open a window above 1000
67
+ tips:
68
+ type: cycle
69
+ surface: raised
70
+ items: { bind: /tips }
71
+ seconds: 8
@@ -0,0 +1,28 @@
1
+ {
2
+ "kpi": {
3
+ "revenue": 134210,
4
+ "vs_target": 105,
5
+ "target_label": "Day target 128K",
6
+ "state": "good",
7
+ "trend": "up",
8
+ "delta": "+2.4 pts"
9
+ },
10
+ "hourly": {
11
+ "labels": ["09:00", "10:00", "11:00", "12:00", "13:00", "14:00", "15:00", "16:00"],
12
+ "revenue": [9.1, 12.4, 14.8, 16.2, 17.5, 19.9, 21.3, 23.0]
13
+ },
14
+ "reps": [
15
+ { "label": "Dana Reyes", "value": 31.2 },
16
+ { "label": "Marcus Okafor", "value": 28.4 },
17
+ { "label": "Lena Brandt", "value": 26.9 },
18
+ { "label": "Sam Whitfield", "value": 22.1 },
19
+ { "label": "Aiko Tanaka", "value": 19.7 },
20
+ { "label": "Joel Mensah", "value": 17.4 }
21
+ ],
22
+ "regions": [
23
+ { "label": "North", "value": 104 },
24
+ { "label": "East", "value": 97 },
25
+ { "label": "South", "value": 78 },
26
+ { "label": "West", "value": 62 }
27
+ ]
28
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "colors": { "scheme": "light", "background": "#ffffff", "accent": "#1d4ed8" },
3
+ "layout": {
4
+ "design": "landscape",
5
+ "flow": [
6
+ { "zone": "head", "span": 5, "height": "150px" },
7
+ { "zone": "revenue", "span": 4, "height": "150px" },
8
+ { "zone": "target", "span": 3, "height": "150px" },
9
+ { "zone": "hourly", "span": 8, "height": 3 },
10
+ { "zone": "reps", "span": 4, "height": 3 },
11
+ { "zone": "regions", "span": 12, "height": 2 }
12
+ ]
13
+ },
14
+ "zones": {
15
+ "head": { "type": "heading", "text": "Sales today" },
16
+ "revenue": {
17
+ "type": "stat",
18
+ "surface": "raised",
19
+ "title": "Revenue",
20
+ "value": { "bind": "/kpi/revenue" },
21
+ "label": "Since midnight",
22
+ "format": "compact"
23
+ },
24
+ "target": {
25
+ "type": "stat",
26
+ "surface": "raised",
27
+ "title": "Against target",
28
+ "value": { "bind": "/kpi/vs_target" },
29
+ "unit": "%",
30
+ "label": { "bind": "/kpi/target_label" },
31
+ "state": { "bind": "/kpi/state", "fallback": "neutral" },
32
+ "trend": { "bind": "/kpi/trend" },
33
+ "delta": { "bind": "/kpi/delta" },
34
+ "good_when": "up"
35
+ },
36
+ "hourly": {
37
+ "type": "chart",
38
+ "kind": "column",
39
+ "title": "Revenue by hour, thousands",
40
+ "labels": { "bind": "/hourly/labels" },
41
+ "series": [
42
+ { "name": "Revenue", "values": { "bind": "/hourly/revenue" } }
43
+ ],
44
+ "target": 15,
45
+ "target_label": "Hourly target 15K"
46
+ },
47
+ "reps": {
48
+ "type": "bars",
49
+ "title": "Top reps, $K",
50
+ "items": { "bind": "/reps" },
51
+ "limit": 6
52
+ },
53
+ "regions": {
54
+ "type": "meters",
55
+ "title": "Quota attainment by region",
56
+ "items": { "bind": "/regions" },
57
+ "max": 120,
58
+ "unit": "%",
59
+ "thresholds": { "warning": 85, "danger": 70 }
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,28 @@
1
+ lunch:
2
+ - [Monday, Pasta bake]
3
+ - [Tuesday, Chicken wrap]
4
+ - [Wednesday, Veggie chili]
5
+ - [Thursday, Fish fingers]
6
+ - [Friday, Pizza]
7
+ week:
8
+ - Picture day is Wednesday
9
+ - Library books due Thursday
10
+ - Parent evening Friday at 18:00
11
+ messages:
12
+ - Please sign the field trip form
13
+ - Lost property is by the gym
14
+ - Bake sale on Friday
15
+
16
+ alert:
17
+ level: warning
18
+ icon: snow
19
+ title: School closed tomorrow
20
+ message: 'Heavy snow is forecast overnight. Maple Ridge Elementary is closed on Tuesday.'
21
+ steps:
22
+ - School buses will not run
23
+ - Online lessons start at 9:00
24
+ - After-school club is cancelled
25
+ - Check the district app for updates
26
+ footer: 'Office 555-0178. Posted Monday at 15:10'
27
+ mode: takeover
28
+ until: '2026-11-15T00:00:00Z'
@@ -0,0 +1,35 @@
1
+ {
2
+ "version": 1,
3
+ "colors": { "scheme": "light", "accent": "#0f766e" },
4
+ "layout": {
5
+ "design": "landscape",
6
+ "flow": [
7
+ { "zone": "head", "span": 9, "height": "170px" },
8
+ { "zone": "clock", "span": 3, "height": "170px" },
9
+ { "zone": "lunch", "span": 6, "height": 2 },
10
+ { "zone": "info", "span": 6, "height": 2 },
11
+ { "zone": "news", "height": "110px" }
12
+ ]
13
+ },
14
+ "zones": {
15
+ "head": { "type": "heading", "text": "Maple Ridge Elementary" },
16
+ "clock": { "type": "clock", "surface": "raised", "show_date": true },
17
+ "lunch": {
18
+ "type": "table",
19
+ "title": "Lunch menu",
20
+ "columns": ["Day", "Main"],
21
+ "rows": { "bind": "/lunch" }
22
+ },
23
+ "info": {
24
+ "type": "list",
25
+ "title": "This week",
26
+ "items": { "bind": "/week" }
27
+ },
28
+ "news": {
29
+ "type": "cycle",
30
+ "surface": "raised",
31
+ "items": { "bind": "/messages" }
32
+ }
33
+ },
34
+ "alert": { "bind": "/alert" }
35
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "alert": {
3
+ "level": "warning",
4
+ "icon": "delay",
5
+ "title": "Delays to Amsterdam",
6
+ "message": "Signal fault near Breukelen. Allow 15 minutes extra.",
7
+ "mode": "banner"
8
+ },
9
+ "departures": [
10
+ ["14:08", "Amsterdam Centraal", 5, "+12 min"],
11
+ ["14:12", "Rotterdam Centraal", 6, "On time"],
12
+ ["14:17", "Arnhem Centraal", 4, "On time"],
13
+ ["14:20", "Den Haag Centraal", 7, "Cancelled"],
14
+ ["14:23", "Schiphol Airport", 5, "+12 min"],
15
+ ["14:28", "Eindhoven Centraal", 6, "On time"],
16
+ ["14:34", "Amersfoort Centraal", 4, "On time"],
17
+ ["14:38", "Amsterdam Centraal", 5, "+8 min"]
18
+ ],
19
+ "messages": [
20
+ "Lift to platform 6 out of service",
21
+ "Mind the gap",
22
+ "Lost property at the service desk, hall 2"
23
+ ]
24
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "version": 1,
3
+ "colors": { "scheme": "dark", "accent": "#facc15", "on_accent": "#111827" },
4
+ "alert": { "bind": "/alert" },
5
+ "layout": {
6
+ "design": "landscape",
7
+ "gap": 2,
8
+ "flow": [
9
+ { "zone": "head", "span": 8, "height": "160px" },
10
+ { "zone": "clock", "span": 4, "height": "160px" },
11
+ { "zone": "board", "height": 6 },
12
+ { "zone": "foot", "height": "110px" }
13
+ ]
14
+ },
15
+ "zones": {
16
+ "head": { "type": "heading", "text": "Departures, platforms 4 to 7", "icon": "location" },
17
+ "clock": { "type": "clock", "surface": "accent", "hour12": false },
18
+ "board": {
19
+ "type": "table",
20
+ "columns": ["Time", "To", "Plat.", "Status"],
21
+ "align": ["start", "start", "end", "end"],
22
+ "widths": [1.2, 4, 1, 2.2],
23
+ "page_rows": 8,
24
+ "seconds": 10,
25
+ "rows": { "bind": "/departures" }
26
+ },
27
+ "foot": {
28
+ "type": "cycle",
29
+ "surface": "raised",
30
+ "seconds": 8,
31
+ "items": { "bind": "/messages" }
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,18 @@
1
+ offer:
2
+ headline: Buy any two Northfield own-label snack multipacks and take the canvas tote home free while stocks last
3
+ ends: '2026-11-22T21:00:00Z'
4
+ promo:
5
+ images:
6
+ - /examples/images/snacks.svg
7
+ - /examples/images/tote.svg
8
+ - /examples/images/hamper.svg
9
+ featured:
10
+ src: /examples/images/kettle.svg
11
+ join:
12
+ url: https://example.com/club
13
+ ticker:
14
+ - Loyalty points are doubled every Thursday
15
+ - Returns accepted for 60 days with a receipt
16
+ - The bakery counter opens at 06:30 on weekdays
17
+ - ''
18
+ - Parking after 16:00 is free for members
@@ -0,0 +1,54 @@
1
+ colors:
2
+ scheme: dark
3
+ accent: '#f97316'
4
+
5
+ layout:
6
+ design: landscape
7
+ gap: 2
8
+ flow:
9
+ - { zone: hero, span: 8, height: 3 }
10
+ - { zone: clock, span: 4, height: 1 }
11
+ - { zone: offer, span: 4, height: 2 }
12
+ - { zone: featured, span: 4, height: 2 }
13
+ - { zone: join, span: 4, height: 2 }
14
+ - { zone: ticker, span: 12, height: 70px }
15
+
16
+ zones:
17
+ hero:
18
+ type: slideshow
19
+ images: { bind: /promo/images }
20
+ seconds: 8
21
+ fit: contain
22
+ clock:
23
+ type: clock
24
+ title: Store time
25
+ show_date: true
26
+ hour12: false
27
+ offer:
28
+ type: stack
29
+ title: This week
30
+ direction: column
31
+ items:
32
+ - type: text
33
+ text: { bind: /offer/headline }
34
+ fit: true
35
+ align: start
36
+ - type: countdown
37
+ to: { bind: /offer/ends }
38
+ label: Ends
39
+ featured:
40
+ type: image
41
+ title: Staff pick
42
+ src: { bind: /featured/src }
43
+ fit: contain
44
+ alt: Staff pick of the week
45
+ join:
46
+ type: qr
47
+ title: Join the club
48
+ value: { bind: /join/url }
49
+ label: Scan for double points
50
+ ticker:
51
+ type: cycle
52
+ items: { bind: /ticker }
53
+ seconds: 9
54
+ align: center
@@ -0,0 +1,20 @@
1
+ {
2
+ "alert": {
3
+ "level": "warning",
4
+ "icon": "storm",
5
+ "title": "Storm warning",
6
+ "message": "Gusts up to 90 km/h until 18:00. Routes 14 and 22 may not run.",
7
+ "footer": "Check the operator app before you travel.",
8
+ "mode": "banner",
9
+ "until": "2026-11-14T18:00:00Z"
10
+ },
11
+ "departures": [
12
+ ["09:40", "14", "Harbour Quay", "Late 10 min"],
13
+ ["09:45", "22", "Ferndale", "Cancelled"],
14
+ ["09:55", "7", "Canal Street", "On time"],
15
+ ["10:05", "31", "Airport", "On time"],
16
+ ["10:15", "9", "Westgate", "Cancelled"]
17
+ ],
18
+ "running": 38,
19
+ "cancelled": 3
20
+ }