@the-smithy/create-hearth-site 0.16.0 → 0.18.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@the-smithy/create-hearth-site",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Start a new client website powered by Hearth: pnpm create @the-smithy/hearth-site",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
],
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"vitest": "^5.0.3",
|
|
32
|
-
"@the-smithy/hearth-schema": "^0.
|
|
32
|
+
"@the-smithy/hearth-schema": "^0.18.0"
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
35
35
|
"test": "node --test \"test/**/*.test.js\" && vitest run test/blocks.test.ts"
|
package/template/CLAUDE.md
CHANGED
|
@@ -37,6 +37,10 @@ Do these before writing code, and tell the developer what you found:
|
|
|
37
37
|
- **Previews come from the SDK.** `<HearthPreview />` in the root layout shows drafts and refreshes as editors
|
|
38
38
|
work in Hearth. Don't build a preview banner of your own.
|
|
39
39
|
- **Forms** post through `submitHearthForm` in `src/app/actions.ts`. Keep the hidden `_gotcha` field.
|
|
40
|
+
- **Analytics comes from the SDK.** `<HearthAnalytics />` in the root layout counts visits for the site's Traffic
|
|
41
|
+
page in Hearth: cookieless, so no consent banner. Don't add Google Analytics or other trackers. Marketing tags
|
|
42
|
+
(ads pixels) need a consent banner and are a separate, opt-in feature. Use `track("name")` from
|
|
43
|
+
`@the-smithy/hearth/analytics` for meaningful actions (a booking, a sign-up).
|
|
40
44
|
|
|
41
45
|
## Checks
|
|
42
46
|
|
package/template/next.config.ts
CHANGED
|
@@ -5,7 +5,8 @@ import type { NextConfig } from "next";
|
|
|
5
5
|
const securityHeaders = [
|
|
6
6
|
{ key: "X-Content-Type-Options", value: "nosniff" },
|
|
7
7
|
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
|
|
8
|
-
|
|
8
|
+
// Only this site and Hearth's side-by-side preview may show it in a frame (X-Frame-Options would block the preview).
|
|
9
|
+
{ key: "Content-Security-Policy", value: "frame-ancestors 'self' https://hearth.thesmithy.io" },
|
|
9
10
|
{ key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=()" },
|
|
10
11
|
];
|
|
11
12
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
|
+
import { HearthAnalytics } from "@the-smithy/hearth/analytics";
|
|
2
3
|
import { siteLang } from "@the-smithy/hearth/next";
|
|
3
4
|
import { HearthPreview } from "@the-smithy/hearth/preview";
|
|
4
5
|
import { SiteFooter } from "@/components/SiteFooter";
|
|
@@ -15,6 +16,7 @@ export const generateMetadata = () => hearthNext.siteMetadata();
|
|
|
15
16
|
|
|
16
17
|
export default async function RootLayout({ children }: { children: ReactNode }) {
|
|
17
18
|
const site = await hearthNext.getSite();
|
|
19
|
+
const preview = await hearthNext.isPreview();
|
|
18
20
|
return (
|
|
19
21
|
<html lang={siteLang(site)}>
|
|
20
22
|
<body className="flex min-h-dvh flex-col">
|
|
@@ -22,12 +24,14 @@ export default async function RootLayout({ children }: { children: ReactNode })
|
|
|
22
24
|
Skip to content
|
|
23
25
|
</a>
|
|
24
26
|
{/* Live draft preview from Hearth: shows while an editor previews, refreshes as they edit. */}
|
|
25
|
-
{
|
|
27
|
+
{preview ? <HearthPreview /> : null}
|
|
26
28
|
<SiteHeader site={site} />
|
|
27
29
|
<main id="main" className="flex-1">
|
|
28
30
|
{children}
|
|
29
31
|
</main>
|
|
30
32
|
<SiteFooter site={site} />
|
|
33
|
+
{/* Hearth's built-in visitor analytics (cookieless, no banner needed): off in draft preview and when the site turns it off. */}
|
|
34
|
+
{site.analytics && !preview ? <HearthAnalytics config={site.analytics} /> : null}
|
|
31
35
|
</body>
|
|
32
36
|
</html>
|
|
33
37
|
);
|
|
@@ -69,6 +69,18 @@ export function UpcomingEvents({ block }: { block: BlockOf<"upcomingEvents"> })
|
|
|
69
69
|
);
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
/** Events that have ended, most recent first (a talk archive). They keep their pages, so each still links to it. */
|
|
73
|
+
export function PastEvents({ block }: { block: BlockOf<"pastEvents"> }) {
|
|
74
|
+
const d = block.data;
|
|
75
|
+
if (!d.events.length) return null;
|
|
76
|
+
return (
|
|
77
|
+
<Section tone="muted">
|
|
78
|
+
<SectionHeading eyebrow={d.eyebrow} heading={d.heading} intro={d.intro} />
|
|
79
|
+
<EventList events={d.events} />
|
|
80
|
+
</Section>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
72
84
|
export function EventSpotlight({ block }: { block: BlockOf<"eventSpotlight"> }) {
|
|
73
85
|
const e = block.data.event;
|
|
74
86
|
if (!e) return null;
|
|
@@ -3,7 +3,7 @@ import { HearthBlocks, type BlockComponents } from "@the-smithy/hearth/react";
|
|
|
3
3
|
import { Section, SectionHeading } from "@/components/ui";
|
|
4
4
|
import { CollectionList } from "./collections";
|
|
5
5
|
import { CallToAction, CardGrid, Faq, Hero, MediaText, Pricing, Projects, Quote, RichText, Stats } from "./content";
|
|
6
|
-
import { EventSpotlight, UpcomingEvents } from "./events";
|
|
6
|
+
import { EventSpotlight, PastEvents, UpcomingEvents } from "./events";
|
|
7
7
|
import { CustomBlock } from "./custom";
|
|
8
8
|
import { EmberFormBlock } from "./EmberFormBlock";
|
|
9
9
|
import { HearthForm } from "./Form";
|
|
@@ -52,6 +52,7 @@ export const blocks: BlockComponents = {
|
|
|
52
52
|
schedule: Schedule,
|
|
53
53
|
form: FormBlock,
|
|
54
54
|
upcomingEvents: UpcomingEvents,
|
|
55
|
+
pastEvents: PastEvents,
|
|
55
56
|
eventSpotlight: EventSpotlight,
|
|
56
57
|
collectionList: CollectionList,
|
|
57
58
|
fundraiserSpotlight: FundraiserSpotlight,
|