bsmnt 0.7.0 → 0.9.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/dist/application/add-hooks/index.d.ts.map +1 -1
- package/dist/application/add-hooks/index.js +1 -0
- package/dist/application/add-hooks/index.js.map +1 -1
- package/dist/application/add-integration/index.d.ts.map +1 -1
- package/dist/application/add-integration/index.js +1 -0
- package/dist/application/add-integration/index.js.map +1 -1
- package/dist/core/create/execute-plan.d.ts +2 -0
- package/dist/core/create/execute-plan.d.ts.map +1 -1
- package/dist/core/create/execute-plan.js +3 -0
- package/dist/core/create/execute-plan.js.map +1 -1
- package/dist/domain/version.d.ts +14 -0
- package/dist/domain/version.d.ts.map +1 -0
- package/dist/domain/version.js +81 -0
- package/dist/domain/version.js.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/create/executor.d.ts.map +1 -1
- package/dist/infrastructure/create/executor.js +2 -0
- package/dist/infrastructure/create/executor.js.map +1 -1
- package/dist/infrastructure/create/render-generated-docs.d.ts +18 -0
- package/dist/infrastructure/create/render-generated-docs.d.ts.map +1 -0
- package/dist/infrastructure/create/render-generated-docs.js +72 -0
- package/dist/infrastructure/create/render-generated-docs.js.map +1 -0
- package/dist/infrastructure/create/setup-dotenvx.d.ts.map +1 -1
- package/dist/infrastructure/create/setup-dotenvx.js +10 -4
- package/dist/infrastructure/create/setup-dotenvx.js.map +1 -1
- package/dist/infrastructure/create/setup-remote.d.ts +6 -1
- package/dist/infrastructure/create/setup-remote.d.ts.map +1 -1
- package/dist/infrastructure/create/setup-remote.js +7 -2
- package/dist/infrastructure/create/setup-remote.js.map +1 -1
- package/dist/infrastructure/update/cache.d.ts +14 -0
- package/dist/infrastructure/update/cache.d.ts.map +1 -0
- package/dist/infrastructure/update/cache.js +41 -0
- package/dist/infrastructure/update/cache.js.map +1 -0
- package/dist/infrastructure/update/check-version.d.ts +2 -0
- package/dist/infrastructure/update/check-version.d.ts.map +1 -0
- package/dist/infrastructure/update/check-version.js +33 -0
- package/dist/infrastructure/update/check-version.js.map +1 -0
- package/dist/infrastructure/update/notifier.d.ts +8 -0
- package/dist/infrastructure/update/notifier.d.ts.map +1 -0
- package/dist/infrastructure/update/notifier.js +141 -0
- package/dist/infrastructure/update/notifier.js.map +1 -0
- package/dist/modules/features/cms/sanity-pagebuilder/config.d.ts.map +1 -1
- package/dist/modules/features/cms/sanity-pagebuilder/config.js +2 -0
- package/dist/modules/features/cms/sanity-pagebuilder/config.js.map +1 -1
- package/package.json +2 -1
- package/src/agent-skills/manage-env/SKILL.md +5 -3
- package/src/modules/features/cms/sanity/files/app/blog/[slug]/page.tsx +10 -9
- package/src/modules/features/cms/sanity/files/app/blog/page.tsx +5 -5
- package/src/modules/features/cms/sanity/files/lib/scripts/copy-sanity-mcp.ts +6 -6
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/block-actions-item.tsx +81 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/icons.ts +2 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-builder-config.ts +7 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-tree-pane.tsx +4 -6
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/queries.ts +72 -21
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/index.ts +1 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/gated-content.ts +178 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/index.ts +9 -1
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/layout/redirect.ts +5 -4
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/metadata.ts +54 -1
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/page-builder.ts +4 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/page.ts +11 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/structure.ts +4 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/utils/page-builder-markdown.ts +20 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/scripts/sanity-typegen.ts +1 -1
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/json-ld.tsx +1 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/metadata.ts +27 -5
- package/src/modules/features/env/dotenvx/files/decrypt-env.mjs +12 -12
- package/src/modules/features/env/dotenvx/files/push-keys.mjs +3 -3
- package/src/modules/features/env/dotenvx/files/save-key.mjs +3 -3
- package/src/modules/features/env/dotenvx/files/setup-remote.ts +3 -1
- package/src/modules/features/env/dotenvx/files/write-env.mjs +6 -6
- package/src/modules/features/forms/hubspot/files/lib/integrations/hubspot/hubspot-form.css +2 -0
- package/src/templates/next-default/.env.example +8 -0
- package/src/templates/next-default/.github/workflows/ci.yml +7 -0
- package/src/templates/next-default/README.md +14 -0
- package/src/templates/next-default/biome.json +1 -1
- package/src/templates/next-default/components/basement.svg +1 -1
- package/src/templates/next-default/knip.json +8 -6
- package/src/templates/next-default/lefthook.yml +0 -5
- package/src/templates/next-experiments/.env.example +8 -0
- package/src/templates/next-experiments/.github/workflows/ci.yml +7 -0
- package/src/templates/next-experiments/README.md +14 -0
- package/src/templates/next-experiments/biome.json +1 -1
- package/src/templates/next-experiments/components/basement.svg +1 -1
- package/src/templates/next-experiments/knip.json +8 -6
- package/src/templates/next-experiments/lefthook.yml +0 -5
- package/src/templates/next-pagebuilder/.env.example +8 -0
- package/src/templates/next-pagebuilder/.github/PULL_REQUEST_TEMPLATE.md +13 -0
- package/src/templates/next-pagebuilder/.github/workflows/ci.yml +15 -0
- package/src/templates/next-pagebuilder/README.md +14 -0
- package/src/templates/next-pagebuilder/app/(content)/[[...slug]]/page.tsx +2 -2
- package/src/templates/next-pagebuilder/app/actions/unlock-gated-content.ts +39 -0
- package/src/templates/next-pagebuilder/biome.json +1 -1
- package/src/templates/next-pagebuilder/components/page-builder/components/gated-content/index.tsx +169 -0
- package/src/templates/next-pagebuilder/components/page-builder/renderer.tsx +3 -0
- package/src/templates/next-pagebuilder/knip.json +8 -6
- package/src/templates/next-pagebuilder/lefthook.yml +0 -5
- package/src/templates/next-pagebuilder/lib/integrations/sanity/sanity.types.ts +81 -0
- package/src/templates/next-webgl/.env.example +8 -0
- package/src/templates/next-webgl/.github/workflows/ci.yml +7 -0
- package/src/templates/next-webgl/README.md +14 -0
- package/src/templates/next-webgl/biome.json +1 -1
- package/src/templates/next-webgl/components/basement.svg +1 -1
- package/src/templates/next-webgl/knip.json +8 -6
- package/src/templates/next-webgl/lefthook.yml +0 -5
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use server"
|
|
2
|
+
|
|
3
|
+
import { fetchSanity } from "@/lib/integrations/sanity/live"
|
|
4
|
+
import { GATED_CONTENT_QUERY } from "@/lib/integrations/sanity/queries"
|
|
5
|
+
import type { GATED_CONTENT_QUERY_RESULT } from "@/lib/integrations/sanity/sanity.types"
|
|
6
|
+
|
|
7
|
+
export type GatedContentPayload = NonNullable<GATED_CONTENT_QUERY_RESULT>
|
|
8
|
+
|
|
9
|
+
export type UnlockResult =
|
|
10
|
+
| { ok: true; payload: GatedContentPayload }
|
|
11
|
+
| { ok: false; error: string }
|
|
12
|
+
|
|
13
|
+
type UnlockInput = { documentId: string; email: string }
|
|
14
|
+
|
|
15
|
+
export async function unlockGatedContent({
|
|
16
|
+
documentId,
|
|
17
|
+
email,
|
|
18
|
+
}: UnlockInput): Promise<UnlockResult> {
|
|
19
|
+
if (!documentId) return { ok: false, error: "Missing content id." }
|
|
20
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
|
21
|
+
return { ok: false, error: "Enter a valid email address." }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Lead-capture seam: forward `email` to your CRM / email provider here.
|
|
25
|
+
// This is not access control — the payload is withheld from the page until
|
|
26
|
+
// this action runs, but anyone who submits the form receives it.
|
|
27
|
+
|
|
28
|
+
const { data } = await fetchSanity<GATED_CONTENT_QUERY_RESULT>({
|
|
29
|
+
query: GATED_CONTENT_QUERY,
|
|
30
|
+
params: { id: documentId },
|
|
31
|
+
// stega must stay off: it injects invisible characters into strings, which
|
|
32
|
+
// would corrupt the asset URLs returned for download/playback.
|
|
33
|
+
stega: false,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
if (!data) return { ok: false, error: "Content not found." }
|
|
37
|
+
|
|
38
|
+
return { ok: true, payload: data }
|
|
39
|
+
}
|
package/src/templates/next-pagebuilder/components/page-builder/components/gated-content/index.tsx
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from "react"
|
|
4
|
+
import {
|
|
5
|
+
type GatedContentPayload,
|
|
6
|
+
unlockGatedContent,
|
|
7
|
+
} from "@/app/actions/unlock-gated-content"
|
|
8
|
+
import type { PageBuilderBlock } from "@/components/page-builder/types"
|
|
9
|
+
import { RichText } from "@/components/sanity/rich-text"
|
|
10
|
+
import { Link } from "@/components/ui/link"
|
|
11
|
+
|
|
12
|
+
type GatedContentBlock = Extract<PageBuilderBlock, { _type: "gatedContent" }>
|
|
13
|
+
|
|
14
|
+
type GatedContentProps = {
|
|
15
|
+
block: GatedContentBlock
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type GateState = "locked" | "loading" | "unlocked"
|
|
19
|
+
|
|
20
|
+
const STORAGE_PREFIX = "gated-content:"
|
|
21
|
+
|
|
22
|
+
export function GatedContent({ block }: GatedContentProps) {
|
|
23
|
+
const storageKey = `${STORAGE_PREFIX}${block._id}`
|
|
24
|
+
const [state, setState] = useState<GateState>("locked")
|
|
25
|
+
const [payload, setPayload] = useState<GatedContentPayload | null>(null)
|
|
26
|
+
const [error, setError] = useState<string | null>(null)
|
|
27
|
+
const [justUnlocked, setJustUnlocked] = useState(false)
|
|
28
|
+
|
|
29
|
+
// The payload is withheld from the page query, so it never reaches the client
|
|
30
|
+
// until this action runs. We remember the submitted email so a returning
|
|
31
|
+
// visitor re-fetches without seeing the form again.
|
|
32
|
+
const unlock = async (email: string, persist: boolean) => {
|
|
33
|
+
setState("loading")
|
|
34
|
+
setError(null)
|
|
35
|
+
|
|
36
|
+
const result = await unlockGatedContent({ documentId: block._id, email })
|
|
37
|
+
|
|
38
|
+
if (!result.ok) {
|
|
39
|
+
setError(result.error)
|
|
40
|
+
setState("locked")
|
|
41
|
+
if (!persist) window.localStorage.removeItem(storageKey)
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setPayload(result.payload)
|
|
46
|
+
setState("unlocked")
|
|
47
|
+
if (persist) {
|
|
48
|
+
window.localStorage.setItem(storageKey, email)
|
|
49
|
+
setJustUnlocked(true)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: re-fetch only when the block changes; unlock closes over stable values
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
const savedEmail = window.localStorage.getItem(storageKey)
|
|
56
|
+
if (savedEmail) void unlock(savedEmail, false)
|
|
57
|
+
}, [storageKey])
|
|
58
|
+
|
|
59
|
+
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
|
60
|
+
event.preventDefault()
|
|
61
|
+
const email =
|
|
62
|
+
new FormData(event.currentTarget).get("email")?.toString() ?? ""
|
|
63
|
+
void unlock(email, true)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<section className="py-8 md:py-12">
|
|
68
|
+
{block.teaserHeading ? (
|
|
69
|
+
<h2 className="mb-4 font-semibold text-2xl tracking-tight md:text-4xl">
|
|
70
|
+
{block.teaserHeading}
|
|
71
|
+
</h2>
|
|
72
|
+
) : null}
|
|
73
|
+
|
|
74
|
+
{block.teaserBody ? (
|
|
75
|
+
<div className="max-w-[62ch] space-y-4 text-base/7 text-current/80 md:text-lg/8">
|
|
76
|
+
<RichText content={block.teaserBody} />
|
|
77
|
+
</div>
|
|
78
|
+
) : null}
|
|
79
|
+
|
|
80
|
+
{state === "unlocked" && payload ? (
|
|
81
|
+
<div className="mt-8">
|
|
82
|
+
{justUnlocked && block.successMessage ? (
|
|
83
|
+
<p className="mb-6 rounded-lg bg-black/[0.04] px-4 py-3 text-current/72 text-sm">
|
|
84
|
+
{block.successMessage}
|
|
85
|
+
</p>
|
|
86
|
+
) : null}
|
|
87
|
+
<GatedReveal payload={payload} />
|
|
88
|
+
</div>
|
|
89
|
+
) : (
|
|
90
|
+
<form
|
|
91
|
+
onSubmit={handleSubmit}
|
|
92
|
+
className="mt-8 flex max-w-md flex-col gap-4 rounded-[1.5rem] border border-black/10 bg-black/[0.02] p-6"
|
|
93
|
+
>
|
|
94
|
+
{block.gateHeadline ? (
|
|
95
|
+
<h3 className="font-semibold text-lg">{block.gateHeadline}</h3>
|
|
96
|
+
) : null}
|
|
97
|
+
{block.gateDescription ? (
|
|
98
|
+
<p className="text-current/72 text-sm">{block.gateDescription}</p>
|
|
99
|
+
) : null}
|
|
100
|
+
<input
|
|
101
|
+
type="email"
|
|
102
|
+
name="email"
|
|
103
|
+
required
|
|
104
|
+
placeholder="you@example.com"
|
|
105
|
+
className="rounded-lg border border-black/10 bg-white px-4 py-2.5 text-sm outline-none focus:border-black/40"
|
|
106
|
+
/>
|
|
107
|
+
{error ? <p className="text-red-600 text-sm">{error}</p> : null}
|
|
108
|
+
<button
|
|
109
|
+
type="submit"
|
|
110
|
+
disabled={state === "loading"}
|
|
111
|
+
className="rounded-lg bg-black px-4 py-2.5 font-medium text-sm text-white transition-colors hover:bg-black/80 disabled:opacity-60"
|
|
112
|
+
>
|
|
113
|
+
{state === "loading" ? "Unlocking…" : block.submitLabel || "Unlock"}
|
|
114
|
+
</button>
|
|
115
|
+
</form>
|
|
116
|
+
)}
|
|
117
|
+
</section>
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function GatedReveal({ payload }: { payload: GatedContentPayload }) {
|
|
122
|
+
if (payload.kind === "richText" && payload.content) {
|
|
123
|
+
return (
|
|
124
|
+
<div className="max-w-[62ch] space-y-4 text-base/7 text-current/80 md:text-lg/8">
|
|
125
|
+
<RichText content={payload.content} />
|
|
126
|
+
</div>
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (payload.kind === "file" && payload.file?.url) {
|
|
131
|
+
return (
|
|
132
|
+
<Link
|
|
133
|
+
href={payload.file.url}
|
|
134
|
+
download
|
|
135
|
+
className="inline-flex items-center gap-2 rounded-lg bg-black px-4 py-2.5 font-medium text-sm text-white transition-colors hover:bg-black/80"
|
|
136
|
+
>
|
|
137
|
+
Download {payload.file.originalFilename ?? "file"}
|
|
138
|
+
</Link>
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (payload.kind === "video") {
|
|
143
|
+
if (payload.video.url) {
|
|
144
|
+
return (
|
|
145
|
+
<div className="aspect-video w-full max-w-3xl overflow-hidden rounded-lg">
|
|
146
|
+
<iframe
|
|
147
|
+
src={payload.video.url}
|
|
148
|
+
title="Gated video"
|
|
149
|
+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
150
|
+
allowFullScreen
|
|
151
|
+
className="h-full w-full border-0"
|
|
152
|
+
/>
|
|
153
|
+
</div>
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
if (payload.video.file?.url) {
|
|
157
|
+
return (
|
|
158
|
+
// biome-ignore lint/a11y/useMediaCaption: editor-supplied video without a caption track
|
|
159
|
+
<video
|
|
160
|
+
controls
|
|
161
|
+
src={payload.video.file.url}
|
|
162
|
+
className="w-full max-w-3xl rounded-lg"
|
|
163
|
+
/>
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return null
|
|
169
|
+
}
|
|
@@ -2,6 +2,7 @@ import { ArticleContent } from "./components/article-content"
|
|
|
2
2
|
import { ContentCollection } from "./components/content-collection"
|
|
3
3
|
import type { ContentCollectionSearchParams } from "./components/content-collection/types"
|
|
4
4
|
import { Description } from "./components/description"
|
|
5
|
+
import { GatedContent } from "./components/gated-content"
|
|
5
6
|
import { Hero } from "./components/hero"
|
|
6
7
|
import type { PageBuilderBlock, PageBuilderBlocks } from "./types"
|
|
7
8
|
|
|
@@ -42,6 +43,8 @@ function PageBuilderNode({
|
|
|
42
43
|
return <Hero block={block} />
|
|
43
44
|
case "description":
|
|
44
45
|
return <Description block={block} />
|
|
46
|
+
case "gatedContent":
|
|
47
|
+
return <GatedContent block={block} />
|
|
45
48
|
default:
|
|
46
49
|
return null
|
|
47
50
|
}
|
|
@@ -22,11 +22,13 @@
|
|
|
22
22
|
"rxjs",
|
|
23
23
|
"gsap",
|
|
24
24
|
"@gsap/react",
|
|
25
|
-
"motion"
|
|
25
|
+
"motion",
|
|
26
|
+
"detect-gpu",
|
|
27
|
+
"lodash-es",
|
|
28
|
+
"@types/lodash-es",
|
|
29
|
+
"react-device-detect",
|
|
30
|
+
"zustand"
|
|
26
31
|
],
|
|
27
|
-
"ignoreBinaries": [
|
|
28
|
-
|
|
29
|
-
"op",
|
|
30
|
-
"vercel"
|
|
31
|
-
]
|
|
32
|
+
"ignoreBinaries": ["gh", "op", "vercel"],
|
|
33
|
+
"ignoreFiles": [".agents/**", ".claude/**", "hooks/**"]
|
|
32
34
|
}
|
|
@@ -50,6 +50,13 @@ export type SanityImageAssetReference = {
|
|
|
50
50
|
[internalGroqTypeReferenceTo]?: "sanity.imageAsset"
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
export type SanityFileAssetReference = {
|
|
54
|
+
_ref: string
|
|
55
|
+
_type: "reference"
|
|
56
|
+
_weak?: boolean
|
|
57
|
+
[internalGroqTypeReferenceTo]?: "sanity.fileAsset"
|
|
58
|
+
}
|
|
59
|
+
|
|
53
60
|
export type StructuredData = {
|
|
54
61
|
_id: string
|
|
55
62
|
_type: "structuredData"
|
|
@@ -307,6 +314,33 @@ export type BlogCollection = {
|
|
|
307
314
|
subtitle?: string
|
|
308
315
|
}
|
|
309
316
|
|
|
317
|
+
export type GatedContent = {
|
|
318
|
+
_id: string
|
|
319
|
+
_type: "gatedContent"
|
|
320
|
+
_createdAt: string
|
|
321
|
+
_updatedAt: string
|
|
322
|
+
_rev: string
|
|
323
|
+
internalTitle?: string
|
|
324
|
+
teaserHeading?: string
|
|
325
|
+
teaserBody?: RichText
|
|
326
|
+
gateType?: "form"
|
|
327
|
+
gateHeadline?: string
|
|
328
|
+
gateDescription?: string
|
|
329
|
+
submitLabel?: string
|
|
330
|
+
successMessage?: string
|
|
331
|
+
kind?: "richText" | "file" | "video"
|
|
332
|
+
content?: RichText
|
|
333
|
+
file?: {
|
|
334
|
+
asset?: SanityFileAssetReference
|
|
335
|
+
_type: "file"
|
|
336
|
+
}
|
|
337
|
+
videoUrl?: string
|
|
338
|
+
videoFile?: {
|
|
339
|
+
asset?: SanityFileAssetReference
|
|
340
|
+
_type: "file"
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
310
344
|
export type NavItem = {
|
|
311
345
|
_type: "navItem"
|
|
312
346
|
title?: string
|
|
@@ -475,6 +509,13 @@ export type BlogCollectionReference = {
|
|
|
475
509
|
[internalGroqTypeReferenceTo]?: "blogCollection"
|
|
476
510
|
}
|
|
477
511
|
|
|
512
|
+
export type GatedContentReference = {
|
|
513
|
+
_ref: string
|
|
514
|
+
_type: "reference"
|
|
515
|
+
_weak?: boolean
|
|
516
|
+
[internalGroqTypeReferenceTo]?: "gatedContent"
|
|
517
|
+
}
|
|
518
|
+
|
|
478
519
|
export type PageBuilder = Array<
|
|
479
520
|
| ({
|
|
480
521
|
_key: string
|
|
@@ -488,6 +529,9 @@ export type PageBuilder = Array<
|
|
|
488
529
|
| ({
|
|
489
530
|
_key: string
|
|
490
531
|
} & BlogCollectionReference)
|
|
532
|
+
| ({
|
|
533
|
+
_key: string
|
|
534
|
+
} & GatedContentReference)
|
|
491
535
|
>
|
|
492
536
|
|
|
493
537
|
export type Metadata = {
|
|
@@ -699,6 +743,7 @@ export type AllSanitySchemaTypes =
|
|
|
699
743
|
| Slug
|
|
700
744
|
| Redirect
|
|
701
745
|
| SanityImageAssetReference
|
|
746
|
+
| SanityFileAssetReference
|
|
702
747
|
| StructuredData
|
|
703
748
|
| SanityImageCrop
|
|
704
749
|
| SanityImageHotspot
|
|
@@ -715,6 +760,7 @@ export type AllSanitySchemaTypes =
|
|
|
715
760
|
| RichText
|
|
716
761
|
| Author
|
|
717
762
|
| BlogCollection
|
|
763
|
+
| GatedContent
|
|
718
764
|
| NavItem
|
|
719
765
|
| NavMegaMenu
|
|
720
766
|
| NavColumn
|
|
@@ -730,6 +776,7 @@ export type AllSanitySchemaTypes =
|
|
|
730
776
|
| DescriptionReference
|
|
731
777
|
| BlogContentReference
|
|
732
778
|
| BlogCollectionReference
|
|
779
|
+
| GatedContentReference
|
|
733
780
|
| PageBuilder
|
|
734
781
|
| Metadata
|
|
735
782
|
| ExternalLink
|
|
@@ -768,6 +815,20 @@ export type PAGE_QUERY_RESULT = {
|
|
|
768
815
|
_rev: string
|
|
769
816
|
subtitle?: string
|
|
770
817
|
}
|
|
818
|
+
| {
|
|
819
|
+
_key: string
|
|
820
|
+
_id: string
|
|
821
|
+
_type: "gatedContent"
|
|
822
|
+
internalTitle: string | null
|
|
823
|
+
teaserHeading: string | null
|
|
824
|
+
teaserBody: RichText | null
|
|
825
|
+
gateType: string | null
|
|
826
|
+
gateHeadline: string | null
|
|
827
|
+
gateDescription: string | null
|
|
828
|
+
submitLabel: string | null
|
|
829
|
+
successMessage: string | null
|
|
830
|
+
kind: "richText" | "file" | "video" | null
|
|
831
|
+
}
|
|
771
832
|
| {
|
|
772
833
|
_key: string
|
|
773
834
|
_id: string
|
|
@@ -897,6 +958,26 @@ export type PAGE_QUERY_RESULT = {
|
|
|
897
958
|
_updatedAt: string
|
|
898
959
|
} | null
|
|
899
960
|
|
|
961
|
+
// Source: queries.ts
|
|
962
|
+
// Variable: GATED_CONTENT_QUERY
|
|
963
|
+
export type GATED_CONTENT_QUERY_RESULT = {
|
|
964
|
+
kind: "richText" | "file" | "video" | null
|
|
965
|
+
content: RichText | null
|
|
966
|
+
file: {
|
|
967
|
+
url: string | null
|
|
968
|
+
originalFilename: string | null
|
|
969
|
+
mimeType: string | null
|
|
970
|
+
size: number | null
|
|
971
|
+
} | null
|
|
972
|
+
video: {
|
|
973
|
+
url: string | null
|
|
974
|
+
file: {
|
|
975
|
+
url: string | null
|
|
976
|
+
mimeType: string | null
|
|
977
|
+
} | null
|
|
978
|
+
}
|
|
979
|
+
} | null
|
|
980
|
+
|
|
900
981
|
// Source: queries.ts
|
|
901
982
|
// Variable: PAGE_METADATA_QUERY
|
|
902
983
|
// Query: *[ _type == "page" && ( ($slug == null && !defined(pageFolder._ref) && (!defined(slug.current) || slug.current == "" || slug.current == "/")) || select( defined(pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && (!defined(slug.current) || slug.current == "" || slug.current == "/") => pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current, defined(pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && (!defined(slug.current) || slug.current == "" || slug.current == "/") => pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current, defined(pageFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && (!defined(slug.current) || slug.current == "" || slug.current == "/") => pageFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current, defined(pageFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && (!defined(slug.current) || slug.current == "" || slug.current == "/") => pageFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current, defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && (!defined(slug.current) || slug.current == "" || slug.current == "/") => pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current, defined(pageFolder->slug.current) && (!defined(slug.current) || slug.current == "" || slug.current == "/") => pageFolder->slug.current, defined(pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && defined(slug.current) && slug.current != "" && slug.current != "/" => pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current + "/" + slug.current, defined(pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && defined(slug.current) && slug.current != "" && slug.current != "/" => pageFolder->parentFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current + "/" + slug.current, defined(pageFolder->parentFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && defined(slug.current) && slug.current != "" && slug.current != "/" => pageFolder->parentFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current + "/" + slug.current, defined(pageFolder->parentFolder->parentFolder->slug.current) && defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && defined(slug.current) && slug.current != "" && slug.current != "/" => pageFolder->parentFolder->parentFolder->slug.current + "/" + pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current + "/" + slug.current, defined(pageFolder->parentFolder->slug.current) && defined(pageFolder->slug.current) && defined(slug.current) && slug.current != "" && slug.current != "/" => pageFolder->parentFolder->slug.current + "/" + pageFolder->slug.current + "/" + slug.current, defined(pageFolder->slug.current) && defined(slug.current) && slug.current != "" && slug.current != "/" => pageFolder->slug.current + "/" + slug.current, slug.current ) == $slug ) ][0] { _id, title, metadata, _updatedAt }
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# ============================================
|
|
2
2
|
# Basement Next Starter - Environment Variables
|
|
3
3
|
# ============================================
|
|
4
|
+
# bsmnt:if dotenvx
|
|
4
5
|
# This project uses dotenvx (https://dotenvx.com): the committed `.env` holds
|
|
5
6
|
# shared values, with secrets encrypted there. The private keys live in
|
|
6
7
|
# `.env.keys` (gitignored) — restore them with `bun run env:setup`.
|
|
@@ -15,6 +16,13 @@
|
|
|
15
16
|
#
|
|
16
17
|
# This file just documents the available variables; real values live in `.env`.
|
|
17
18
|
# ============================================
|
|
19
|
+
# bsmnt:endif
|
|
20
|
+
# bsmnt:if !dotenvx
|
|
21
|
+
# Copy this file to `.env.local` and fill in the values you need.
|
|
22
|
+
# `.env.local` is gitignored, so real values stay off version control.
|
|
23
|
+
# Only NEXT_PUBLIC_* variables are exposed to the browser.
|
|
24
|
+
# ============================================
|
|
25
|
+
# bsmnt:endif
|
|
18
26
|
|
|
19
27
|
|
|
20
28
|
# ============================================
|
|
@@ -46,6 +46,7 @@ jobs:
|
|
|
46
46
|
- name: Lint
|
|
47
47
|
run: bun run lint
|
|
48
48
|
|
|
49
|
+
# bsmnt:if dotenvx
|
|
49
50
|
# dotenvx needs the private key to decrypt secrets at build time. It's
|
|
50
51
|
# pulled from 1Password via an org-wide service-account token + the op-ref
|
|
51
52
|
# committed in .env. Optional: builds pass without it (only plaintext /
|
|
@@ -70,6 +71,12 @@ jobs:
|
|
|
70
71
|
fi
|
|
71
72
|
bun run build
|
|
72
73
|
|
|
74
|
+
# bsmnt:endif
|
|
75
|
+
# bsmnt:if !dotenvx
|
|
76
|
+
- name: Build
|
|
77
|
+
run: bun run build
|
|
78
|
+
|
|
79
|
+
# bsmnt:endif
|
|
73
80
|
# Runs your tests if any exist; a fresh project with none passes cleanly.
|
|
74
81
|
- name: Test
|
|
75
82
|
run: |
|
|
@@ -22,6 +22,7 @@ bun dev
|
|
|
22
22
|
| `bun format` | Format the codebase |
|
|
23
23
|
| `bun typecheck` | Run TypeScript |
|
|
24
24
|
| `bun analyze` | Analyze the Next.js bundle |
|
|
25
|
+
<!-- bsmnt:if dotenvx -->
|
|
25
26
|
| `bun env:set KEY value` | Encrypt one value into `.env` (`--plain`, `--preview`/`--prod`) |
|
|
26
27
|
| `bun env:encrypt-all` | Bulk-encrypt every plaintext value in a file (`--preview`/`--prod`) |
|
|
27
28
|
| `bun env:setup` | Restore `.env.keys` from 1Password |
|
|
@@ -29,7 +30,9 @@ bun dev
|
|
|
29
30
|
| `bun env:setup-remote` | Push private keys to GitHub / Vercel (`github`/`vercel`, or pick) |
|
|
30
31
|
| `bun setup-remote` | Create the GitHub repo, link a Vercel project, and push the key to Vercel env |
|
|
31
32
|
| `bun env:save` | Save the private key to 1Password (Development vault) |
|
|
33
|
+
<!-- bsmnt:endif -->
|
|
32
34
|
|
|
35
|
+
<!-- bsmnt:if dotenvx -->
|
|
33
36
|
## Environment variables
|
|
34
37
|
|
|
35
38
|
Secrets are encrypted at rest with [dotenvx](https://dotenvx.com): the committed `.env` holds encrypted values, the private keys live in `.env.keys` (gitignored), and dev/build run through `dotenvx run` so values decrypt automatically.
|
|
@@ -53,6 +56,15 @@ Secrets are encrypted at rest with [dotenvx](https://dotenvx.com): the committed
|
|
|
53
56
|
|
|
54
57
|
A gitleaks pre-commit hook + CI scan block committed plaintext secrets (install: `brew install gitleaks`).
|
|
55
58
|
|
|
59
|
+
<!-- bsmnt:endif -->
|
|
60
|
+
<!-- bsmnt:if !dotenvx -->
|
|
61
|
+
## Environment variables
|
|
62
|
+
|
|
63
|
+
Copy `.env.example` to `.env.local` and fill in the values you need. `.env.local` is gitignored, so it stays off version control. Only `NEXT_PUBLIC_*` variables are exposed to the browser — everything else is server-only.
|
|
64
|
+
|
|
65
|
+
For deploys, set the same variables in your host's dashboard (e.g. Vercel → Settings → Environment Variables).
|
|
66
|
+
|
|
67
|
+
<!-- bsmnt:endif -->
|
|
56
68
|
## Project Structure
|
|
57
69
|
|
|
58
70
|
```txt
|
|
@@ -91,8 +103,10 @@ The workflow takes its runtime versions from your manifests, so there's a single
|
|
|
91
103
|
|
|
92
104
|
It also caches Bun's install cache between runs, and the test step is a no-op until you add real test files.
|
|
93
105
|
|
|
106
|
+
<!-- bsmnt:if dotenvx -->
|
|
94
107
|
The build decrypts the committed `.env` with the dotenvx private key, pulled from 1Password: set an **org-level** `OP_SERVICE_ACCOUNT_TOKEN` (a read-only [service account](https://developer.1password.com/docs/service-accounts/) scoped to the `Development` vault) — one secret for every repo — and CI reads the key via the op-ref committed in `.env`. A per-repo `DOTENV_PRIVATE_KEY` secret (`bun run env:setup-remote github`) works as a fallback; builds pass without either (only plaintext / `NEXT_PUBLIC_*` is read).
|
|
95
108
|
|
|
109
|
+
<!-- bsmnt:endif -->
|
|
96
110
|
### Branch protection
|
|
97
111
|
|
|
98
112
|
To block merges when CI fails, enable branch protection on `main`:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg width="123" height="18" viewBox="0 0 123 18" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M4.43626 6.76458V.252441H.381348V17.1671H4.33011v-3.0447c.40337 2.1989 1.78331 3.2984 4.13983 3.2984 3.96996 0 4.86166-.9515 4.86166-5.6664V9.91493c0-4.7361-.8704-5.66641-4.64937-5.66641-2.54758 0-3.77892.54973-4.24597 2.51606Zm.02123 5.94122V9.42863c.10615-1.14174.84919-1.69146 2.29282-1.69146 1.95315 0 2.31406.42286 2.31406 2.30463v1.628c0 1.8395-.36091 2.2623-2.31406 2.2623-1.4224 0-2.16544-.4228-2.29282-1.2263Zm10.23281.8035c0 3.4252.7643 4.0384 4.9253 3.9115 1.9956-.0211 3.418-.8035 3.97-2.4949v2.2412h4.0337V8.62519c0-3.70008-.8917-4.37667-5.6259-4.37667h-.9766c-4.9678 0-5.9019.65544-5.9019 4.14409v.50744h4.0337c-.0425-1.45889.3184-1.71261 2.314-1.71261 1.7833 0 2.123.25372 2.123 1.71261v.71887l-4.0337.02114c-4.0973 0-4.8616.61314-4.8616 3.86924Zm4.246.0423c0-.7823.2123-.9303 1.3162-.9303l3.3331-.0212v.5497c0 .9938-.6793 1.3744-2.4627 1.4166h-.2122c-1.656 0-1.9744-.1691-1.9744-1.0148Zm10.0417-.3383c0 3.5309.8917 4.2075 5.5622 4.2075h.9766c5.3499 0 6.3265-.592 6.3265-3.6367 0-1.9451-.4883-3.108-2.5051-3.7-1.104-.31718-2.0805-.5709-4.1611-.90919-1.3799-.21143-1.762-.46515-1.762-.99373 0-.78231.4246-.99374 1.9956-.99374 1.6347 0 2.0805.29601 2.0805 1.33203v.38058h4.0337v-.38058c0-3.61551-.8917-4.27095-5.6259-4.27095h-.9766c-4.8192 0-5.7533.57087-5.7533 3.8058 0 1.69146.4458 2.64288 2.1867 3.31948 1.2738.4863 3.2057.7823 3.9487.9303 1.8682.3383 2.3141.6766 2.3141 1.184 0 .7612-.4883.9726-2.3141.9726-1.9744 0-2.5051-.2748-2.5051-1.2474v-.2749H28.978v.2749Zm14.0967-2.3681c0 5.5396.9765 6.5756 6.1779 6.5756h.9765c5.1589 0 6.1142-.6766 6.1142-4.271h-4.2459c0 1.0784-.3609 1.3109-2.3353 1.3109-2.0593 0-2.4415-.3594-2.4415-2.1989v-.0634h9.1289v-1.9875c0-5.03207-.9766-5.96238-6.2204-5.96238h-.9765c-5.2014 0-6.1779 1.01488-6.1779 6.59668Zm4.2459-1.628v-.06343c0-1.64918.3822-1.96633 2.4415-1.96633 1.9956 0 2.4202.31715 2.4414 2.02976h-4.8829Zm10.9122 7.9499h4.0337V9.83035c0-1.48003.7006-2.22004 2.1017-2.22004 1.6135 0 1.932.31715 1.932 1.96632v7.59047h4.0124l-.0212-7.46361c.0424-1.39546.743-2.09318 2.1017-2.09318 1.6135 0 1.8895.31715 1.8895 1.96632v7.59047h4.0337l-.0212-8.20362c0-3.97494-.7219-4.71496-4.6069-4.71496-2.1443 0-3.4393.90916-3.9063 2.91778-.1699-2.41034-.8705-2.91778-4.0974-2.91778-1.8895 0-2.9722.76116-3.418 2.66406V4.50224h-4.0337V17.1671Zm21.6545-6.3219c0 5.5396.9766 6.5756 6.1991 6.5756h.9766c5.1164 0 6.0717-.6766 6.0717-4.271H88.91c0 1.0784-.3609 1.3109-2.3141 1.3109-2.1017 0-2.4839-.3594-2.4839-2.1989v-.0634h9.1289v-1.9875c0-5.03207-.9766-5.96238-6.1779-5.96238h-.9766c-5.2225 0-6.1991 1.01488-6.1991 6.59668Zm4.2247-1.628v-.06343c0-1.64918.3822-1.96633 2.4839-1.96633 1.9744 0 2.399.31715 2.4202 2.02976H84.112Zm10.891 7.9499h4.0337V9.61892c.0212-1.35317.7642-2.00861 2.2293-2.00861 1.868 0 2.208.35943 2.208 2.30462v7.25217h4.033l-.021-8.20362c0-3.97494-.7-4.71496-4.394-4.71496-2.336 0-3.5671.76116-4.0553 2.81206V4.50224H95.003V17.1671Zm13.545-9.30307h1.252v5.05327c0 3.5732.828 4.2498 5.095 4.2498h2.76v-3.5944h-2.335c-1.253 0-1.486-.2114-1.486-1.2686V7.86403h3.63V4.50224h-3.63V1.77476h-3.821v2.72748h-1.465v3.36179Zm10.636 9.30307h3.63v-3.5944h-3.63v3.5944Z" fill="#EFEFEF"/></svg>
|
|
1
|
+
<svg width="123" height="18" viewBox="0 0 123 18" fill="none" xmlns="http://www.w3.org/2000/svg"><title>basement</title><path d="M4.43626 6.76458V.252441H.381348V17.1671H4.33011v-3.0447c.40337 2.1989 1.78331 3.2984 4.13983 3.2984 3.96996 0 4.86166-.9515 4.86166-5.6664V9.91493c0-4.7361-.8704-5.66641-4.64937-5.66641-2.54758 0-3.77892.54973-4.24597 2.51606Zm.02123 5.94122V9.42863c.10615-1.14174.84919-1.69146 2.29282-1.69146 1.95315 0 2.31406.42286 2.31406 2.30463v1.628c0 1.8395-.36091 2.2623-2.31406 2.2623-1.4224 0-2.16544-.4228-2.29282-1.2263Zm10.23281.8035c0 3.4252.7643 4.0384 4.9253 3.9115 1.9956-.0211 3.418-.8035 3.97-2.4949v2.2412h4.0337V8.62519c0-3.70008-.8917-4.37667-5.6259-4.37667h-.9766c-4.9678 0-5.9019.65544-5.9019 4.14409v.50744h4.0337c-.0425-1.45889.3184-1.71261 2.314-1.71261 1.7833 0 2.123.25372 2.123 1.71261v.71887l-4.0337.02114c-4.0973 0-4.8616.61314-4.8616 3.86924Zm4.246.0423c0-.7823.2123-.9303 1.3162-.9303l3.3331-.0212v.5497c0 .9938-.6793 1.3744-2.4627 1.4166h-.2122c-1.656 0-1.9744-.1691-1.9744-1.0148Zm10.0417-.3383c0 3.5309.8917 4.2075 5.5622 4.2075h.9766c5.3499 0 6.3265-.592 6.3265-3.6367 0-1.9451-.4883-3.108-2.5051-3.7-1.104-.31718-2.0805-.5709-4.1611-.90919-1.3799-.21143-1.762-.46515-1.762-.99373 0-.78231.4246-.99374 1.9956-.99374 1.6347 0 2.0805.29601 2.0805 1.33203v.38058h4.0337v-.38058c0-3.61551-.8917-4.27095-5.6259-4.27095h-.9766c-4.8192 0-5.7533.57087-5.7533 3.8058 0 1.69146.4458 2.64288 2.1867 3.31948 1.2738.4863 3.2057.7823 3.9487.9303 1.8682.3383 2.3141.6766 2.3141 1.184 0 .7612-.4883.9726-2.3141.9726-1.9744 0-2.5051-.2748-2.5051-1.2474v-.2749H28.978v.2749Zm14.0967-2.3681c0 5.5396.9765 6.5756 6.1779 6.5756h.9765c5.1589 0 6.1142-.6766 6.1142-4.271h-4.2459c0 1.0784-.3609 1.3109-2.3353 1.3109-2.0593 0-2.4415-.3594-2.4415-2.1989v-.0634h9.1289v-1.9875c0-5.03207-.9766-5.96238-6.2204-5.96238h-.9765c-5.2014 0-6.1779 1.01488-6.1779 6.59668Zm4.2459-1.628v-.06343c0-1.64918.3822-1.96633 2.4415-1.96633 1.9956 0 2.4202.31715 2.4414 2.02976h-4.8829Zm10.9122 7.9499h4.0337V9.83035c0-1.48003.7006-2.22004 2.1017-2.22004 1.6135 0 1.932.31715 1.932 1.96632v7.59047h4.0124l-.0212-7.46361c.0424-1.39546.743-2.09318 2.1017-2.09318 1.6135 0 1.8895.31715 1.8895 1.96632v7.59047h4.0337l-.0212-8.20362c0-3.97494-.7219-4.71496-4.6069-4.71496-2.1443 0-3.4393.90916-3.9063 2.91778-.1699-2.41034-.8705-2.91778-4.0974-2.91778-1.8895 0-2.9722.76116-3.418 2.66406V4.50224h-4.0337V17.1671Zm21.6545-6.3219c0 5.5396.9766 6.5756 6.1991 6.5756h.9766c5.1164 0 6.0717-.6766 6.0717-4.271H88.91c0 1.0784-.3609 1.3109-2.3141 1.3109-2.1017 0-2.4839-.3594-2.4839-2.1989v-.0634h9.1289v-1.9875c0-5.03207-.9766-5.96238-6.1779-5.96238h-.9766c-5.2225 0-6.1991 1.01488-6.1991 6.59668Zm4.2247-1.628v-.06343c0-1.64918.3822-1.96633 2.4839-1.96633 1.9744 0 2.399.31715 2.4202 2.02976H84.112Zm10.891 7.9499h4.0337V9.61892c.0212-1.35317.7642-2.00861 2.2293-2.00861 1.868 0 2.208.35943 2.208 2.30462v7.25217h4.033l-.021-8.20362c0-3.97494-.7-4.71496-4.394-4.71496-2.336 0-3.5671.76116-4.0553 2.81206V4.50224H95.003V17.1671Zm13.545-9.30307h1.252v5.05327c0 3.5732.828 4.2498 5.095 4.2498h2.76v-3.5944h-2.335c-1.253 0-1.486-.2114-1.486-1.2686V7.86403h3.63V4.50224h-3.63V1.77476h-3.821v2.72748h-1.465v3.36179Zm10.636 9.30307h3.63v-3.5944h-3.63v3.5944Z" fill="#EFEFEF"/></svg>
|
|
@@ -11,11 +11,13 @@
|
|
|
11
11
|
"@svgr/webpack",
|
|
12
12
|
"gsap",
|
|
13
13
|
"@gsap/react",
|
|
14
|
-
"motion"
|
|
14
|
+
"motion",
|
|
15
|
+
"detect-gpu",
|
|
16
|
+
"lodash-es",
|
|
17
|
+
"@types/lodash-es",
|
|
18
|
+
"react-device-detect",
|
|
19
|
+
"zustand"
|
|
15
20
|
],
|
|
16
|
-
"ignoreBinaries": [
|
|
17
|
-
|
|
18
|
-
"gh",
|
|
19
|
-
"vercel"
|
|
20
|
-
]
|
|
21
|
+
"ignoreBinaries": ["op", "gh", "vercel"],
|
|
22
|
+
"ignoreFiles": [".agents/**", ".claude/**", "hooks/**"]
|
|
21
23
|
}
|