@nextsparkjs/theme-default 0.1.0-beta.49 → 0.1.0-beta.51
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/api/ai/chat/stream/route.ts +4 -1
- package/api/ai/orchestrator/route.ts +10 -3
- package/api/ai/single-agent/route.ts +10 -3
- package/api/ai/usage/route.ts +4 -1
- package/blocks/text-content/component.tsx +10 -8
- package/config/dashboard.config.ts +14 -0
- package/config/permissions.config.ts +11 -0
- package/messages/en/admin.json +12 -1
- package/messages/es/admin.json +12 -1
- package/migrations/093_pages_sample_data.sql +7 -7
- package/migrations/098_patterns_sample_data.sql +234 -0
- package/package.json +3 -3
- package/tests/cypress/e2e/_utils/selectors/block-editor.bdd.md +127 -3
- package/tests/cypress/e2e/_utils/selectors/block-editor.cy.ts +124 -0
- package/tests/cypress/e2e/ai/chat-api.cy.ts +50 -38
- package/tests/cypress/e2e/api/_core/security/security-headers.cy.ts +601 -0
- package/tests/cypress/e2e/patterns/patterns-in-pages.cy.ts +367 -0
- package/tests/cypress/fixtures/entities.json +9 -0
- package/tests/cypress/src/entities/PatternsPOM.ts +329 -0
- package/tests/cypress/src/entities/index.ts +2 -0
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
import { NextRequest } from 'next/server'
|
|
27
27
|
import { z } from 'zod'
|
|
28
28
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
29
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
29
30
|
import { streamChat } from '@/plugins/langchain/lib/agent-factory'
|
|
30
31
|
import { createSSEEncoder } from '@/plugins/langchain/lib/streaming'
|
|
31
32
|
import { loadSystemPrompt } from '@/themes/default/lib/langchain/agents'
|
|
@@ -46,7 +47,7 @@ const StreamChatRequestSchema = z.object({
|
|
|
46
47
|
/**
|
|
47
48
|
* POST - Stream chat response
|
|
48
49
|
*/
|
|
49
|
-
|
|
50
|
+
const postHandler = async (request: NextRequest) => {
|
|
50
51
|
try {
|
|
51
52
|
// 1. Authentication
|
|
52
53
|
const authResult = await authenticateRequest(request)
|
|
@@ -210,3 +211,5 @@ export async function POST(request: NextRequest) {
|
|
|
210
211
|
) as any
|
|
211
212
|
}
|
|
212
213
|
}
|
|
214
|
+
|
|
215
|
+
export const POST = withRateLimitTier(postHandler, 'write')
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
4
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
4
5
|
import { processMessage } from '@/themes/default/lib/langchain/orchestrator'
|
|
5
6
|
import { dbMemoryStore } from '@/plugins/langchain/lib/db-memory-store'
|
|
6
7
|
import type { ChatMessage } from '@/plugins/langchain/types/langchain.types'
|
|
@@ -52,7 +53,7 @@ function convertToApiMessages(
|
|
|
52
53
|
* - Sub-agents: task-assistant, customer-assistant, page-assistant
|
|
53
54
|
* - Handles ambiguous requests by asking for clarification
|
|
54
55
|
*/
|
|
55
|
-
|
|
56
|
+
const postHandler = async (req: NextRequest) => {
|
|
56
57
|
try {
|
|
57
58
|
// 1. Dual authentication (API key or session)
|
|
58
59
|
const authResult = await authenticateRequest(req)
|
|
@@ -118,10 +119,12 @@ export async function POST(req: NextRequest) {
|
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
121
|
|
|
122
|
+
export const POST = withRateLimitTier(postHandler, 'write')
|
|
123
|
+
|
|
121
124
|
/**
|
|
122
125
|
* GET - Retrieve conversation history
|
|
123
126
|
*/
|
|
124
|
-
|
|
127
|
+
const getHandler = async (req: NextRequest) => {
|
|
125
128
|
const { searchParams } = new URL(req.url)
|
|
126
129
|
const sessionId = searchParams.get('sessionId')
|
|
127
130
|
|
|
@@ -187,10 +190,12 @@ export async function GET(req: NextRequest) {
|
|
|
187
190
|
}
|
|
188
191
|
}
|
|
189
192
|
|
|
193
|
+
export const GET = withRateLimitTier(getHandler, 'read')
|
|
194
|
+
|
|
190
195
|
/**
|
|
191
196
|
* DELETE - Clear conversation
|
|
192
197
|
*/
|
|
193
|
-
|
|
198
|
+
const deleteHandler = async (req: NextRequest) => {
|
|
194
199
|
const authResult = await authenticateRequest(req)
|
|
195
200
|
if (!authResult.success || !authResult.user) {
|
|
196
201
|
return NextResponse.json({ success: false, error: 'Unauthorized' }, { status: 401 })
|
|
@@ -224,3 +229,5 @@ export async function DELETE(req: NextRequest) {
|
|
|
224
229
|
return NextResponse.json({ success: false, error: 'Failed to clear' }, { status: 500 })
|
|
225
230
|
}
|
|
226
231
|
}
|
|
232
|
+
|
|
233
|
+
export const DELETE = withRateLimitTier(deleteHandler, 'write')
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import { NextRequest, NextResponse } from 'next/server'
|
|
15
15
|
import { z } from 'zod'
|
|
16
16
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
17
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
17
18
|
import { createAgent } from '@/plugins/langchain/lib/agent-factory'
|
|
18
19
|
import {
|
|
19
20
|
dbMemoryStore,
|
|
@@ -74,7 +75,7 @@ function convertToApiMessages(
|
|
|
74
75
|
/**
|
|
75
76
|
* POST - Send message to single agent
|
|
76
77
|
*/
|
|
77
|
-
|
|
78
|
+
const postHandler = async (req: NextRequest) => {
|
|
78
79
|
try {
|
|
79
80
|
// 1. Authentication
|
|
80
81
|
const authResult = await authenticateRequest(req)
|
|
@@ -181,10 +182,12 @@ export async function POST(req: NextRequest) {
|
|
|
181
182
|
}
|
|
182
183
|
}
|
|
183
184
|
|
|
185
|
+
export const POST = withRateLimitTier(postHandler, 'write')
|
|
186
|
+
|
|
184
187
|
/**
|
|
185
188
|
* GET - Retrieve conversation history
|
|
186
189
|
*/
|
|
187
|
-
|
|
190
|
+
const getHandler = async (req: NextRequest) => {
|
|
188
191
|
const { searchParams } = new URL(req.url)
|
|
189
192
|
const sessionId = searchParams.get('sessionId')
|
|
190
193
|
|
|
@@ -252,10 +255,12 @@ export async function GET(req: NextRequest) {
|
|
|
252
255
|
}
|
|
253
256
|
}
|
|
254
257
|
|
|
258
|
+
export const GET = withRateLimitTier(getHandler, 'read')
|
|
259
|
+
|
|
255
260
|
/**
|
|
256
261
|
* DELETE - Clear conversation
|
|
257
262
|
*/
|
|
258
|
-
|
|
263
|
+
const deleteHandler = async (req: NextRequest) => {
|
|
259
264
|
const authResult = await authenticateRequest(req)
|
|
260
265
|
if (!authResult.success || !authResult.user) {
|
|
261
266
|
return NextResponse.json({ success: false, error: 'Unauthorized' }, { status: 401 })
|
|
@@ -289,3 +294,5 @@ export async function DELETE(req: NextRequest) {
|
|
|
289
294
|
return NextResponse.json({ success: false, error: 'Failed to clear' }, { status: 500 })
|
|
290
295
|
}
|
|
291
296
|
}
|
|
297
|
+
|
|
298
|
+
export const DELETE = withRateLimitTier(deleteHandler, 'write')
|
package/api/ai/usage/route.ts
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
import { NextRequest, NextResponse } from 'next/server'
|
|
22
22
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
23
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
23
24
|
import { tokenTracker } from '@/plugins/langchain/lib/token-tracker'
|
|
24
25
|
import { queryOne } from '@nextsparkjs/core/lib/db'
|
|
25
26
|
|
|
@@ -28,7 +29,7 @@ type Period = 'today' | '7d' | '30d' | 'all'
|
|
|
28
29
|
/**
|
|
29
30
|
* GET - Retrieve token usage statistics
|
|
30
31
|
*/
|
|
31
|
-
|
|
32
|
+
const getHandler = async (request: NextRequest) => {
|
|
32
33
|
try {
|
|
33
34
|
// 1. Authentication
|
|
34
35
|
const authResult = await authenticateRequest(request)
|
|
@@ -120,3 +121,5 @@ export async function GET(request: NextRequest) {
|
|
|
120
121
|
)
|
|
121
122
|
}
|
|
122
123
|
}
|
|
124
|
+
|
|
125
|
+
export const GET = withRateLimitTier(getHandler, 'read')
|
|
@@ -65,14 +65,16 @@ export function TextContentBlock({
|
|
|
65
65
|
)}
|
|
66
66
|
|
|
67
67
|
{/* Rich Text Content */}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
68
|
+
{content && (
|
|
69
|
+
<div
|
|
70
|
+
className={cn(
|
|
71
|
+
'prose prose-lg dark:prose-invert',
|
|
72
|
+
maxWidthClasses[maxWidth],
|
|
73
|
+
alignmentClasses[alignment]
|
|
74
|
+
)}
|
|
75
|
+
dangerouslySetInnerHTML={{ __html: content }}
|
|
76
|
+
/>
|
|
77
|
+
)}
|
|
76
78
|
|
|
77
79
|
{/* Optional CTA */}
|
|
78
80
|
{cta && (
|
|
@@ -94,6 +94,20 @@ export const DASHBOARD_CONFIG = {
|
|
|
94
94
|
enabled: true,
|
|
95
95
|
},
|
|
96
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Settings menu dropdown (gear icon)
|
|
99
|
+
*/
|
|
100
|
+
settingsMenu: {
|
|
101
|
+
enabled: true,
|
|
102
|
+
links: [
|
|
103
|
+
{
|
|
104
|
+
label: 'navigation.patterns',
|
|
105
|
+
href: '/dashboard/patterns',
|
|
106
|
+
icon: 'layers',
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
},
|
|
110
|
+
|
|
97
111
|
/**
|
|
98
112
|
* User menu dropdown
|
|
99
113
|
*/
|
|
@@ -110,6 +110,17 @@ export const PERMISSIONS_CONFIG_OVERRIDES: ThemePermissionsConfig = {
|
|
|
110
110
|
{ action: 'delete', label: 'Delete Pages', description: 'Can delete pages', roles: ['owner', 'admin'], dangerous: true },
|
|
111
111
|
{ action: 'publish', label: 'Publish Pages', description: 'Can publish pages to make them public', roles: ['owner', 'admin'] },
|
|
112
112
|
],
|
|
113
|
+
|
|
114
|
+
// ------------------------------------------
|
|
115
|
+
// PATTERNS
|
|
116
|
+
// ------------------------------------------
|
|
117
|
+
patterns: [
|
|
118
|
+
{ action: 'create', label: 'Create Patterns', description: 'Can create reusable patterns', roles: ['owner', 'admin'] },
|
|
119
|
+
{ action: 'read', label: 'View Patterns', description: 'Can view pattern details', roles: ['owner', 'admin', 'member', 'viewer'] },
|
|
120
|
+
{ action: 'list', label: 'List Patterns', description: 'Can see the patterns list', roles: ['owner', 'admin', 'member', 'viewer'] },
|
|
121
|
+
{ action: 'update', label: 'Edit Patterns', description: 'Can modify patterns', roles: ['owner', 'admin'] },
|
|
122
|
+
{ action: 'delete', label: 'Delete Patterns', description: 'Can delete patterns', roles: ['owner', 'admin'], dangerous: true },
|
|
123
|
+
],
|
|
113
124
|
},
|
|
114
125
|
|
|
115
126
|
// ==========================================
|
package/messages/en/admin.json
CHANGED
|
@@ -258,7 +258,18 @@
|
|
|
258
258
|
"noDesignFields": "No design fields",
|
|
259
259
|
"noAdvancedFields": "No advanced fields"
|
|
260
260
|
},
|
|
261
|
-
"noFields": "This block has no configurable fields"
|
|
261
|
+
"noFields": "This block has no configurable fields",
|
|
262
|
+
"pattern": {
|
|
263
|
+
"title": "Pattern Reference",
|
|
264
|
+
"locked": {
|
|
265
|
+
"title": "Pattern is read-only",
|
|
266
|
+
"description": "To edit this pattern's content, edit the pattern directly. Changes will be reflected everywhere it's used."
|
|
267
|
+
},
|
|
268
|
+
"actions": {
|
|
269
|
+
"edit": "Edit Pattern",
|
|
270
|
+
"remove": "Remove from page"
|
|
271
|
+
}
|
|
272
|
+
}
|
|
262
273
|
}
|
|
263
274
|
}
|
|
264
275
|
}
|
package/messages/es/admin.json
CHANGED
|
@@ -258,7 +258,18 @@
|
|
|
258
258
|
"noDesignFields": "Sin campos de diseño",
|
|
259
259
|
"noAdvancedFields": "Sin campos avanzados"
|
|
260
260
|
},
|
|
261
|
-
"noFields": "Este bloque no tiene campos configurables"
|
|
261
|
+
"noFields": "Este bloque no tiene campos configurables",
|
|
262
|
+
"pattern": {
|
|
263
|
+
"title": "Referencia de Patrón",
|
|
264
|
+
"locked": {
|
|
265
|
+
"title": "El patrón es de solo lectura",
|
|
266
|
+
"description": "Para editar el contenido de este patrón, edítalo directamente. Los cambios se reflejarán en todos los lugares donde se usa."
|
|
267
|
+
},
|
|
268
|
+
"actions": {
|
|
269
|
+
"edit": "Editar Patrón",
|
|
270
|
+
"remove": "Quitar de la página"
|
|
271
|
+
}
|
|
272
|
+
}
|
|
262
273
|
}
|
|
263
274
|
}
|
|
264
275
|
}
|
|
@@ -20,7 +20,7 @@ INSERT INTO public.pages (
|
|
|
20
20
|
"createdAt",
|
|
21
21
|
"updatedAt"
|
|
22
22
|
) VALUES (
|
|
23
|
-
|
|
23
|
+
'00000000-0000-4000-a000-000000000001',
|
|
24
24
|
'usr-carlos-001',
|
|
25
25
|
'team-everpoint-001',
|
|
26
26
|
'home',
|
|
@@ -332,7 +332,7 @@ INSERT INTO public.pages (
|
|
|
332
332
|
"createdAt",
|
|
333
333
|
"updatedAt"
|
|
334
334
|
) VALUES (
|
|
335
|
-
|
|
335
|
+
'00000000-0000-4000-a000-000000000002',
|
|
336
336
|
'usr-carlos-001',
|
|
337
337
|
'team-everpoint-001',
|
|
338
338
|
'features',
|
|
@@ -500,7 +500,7 @@ INSERT INTO public.pages (
|
|
|
500
500
|
"createdAt",
|
|
501
501
|
"updatedAt"
|
|
502
502
|
) VALUES (
|
|
503
|
-
|
|
503
|
+
'00000000-0000-4000-a000-000000000003',
|
|
504
504
|
'usr-carlos-001',
|
|
505
505
|
'team-everpoint-001',
|
|
506
506
|
'pricing',
|
|
@@ -644,7 +644,7 @@ INSERT INTO public.pages (
|
|
|
644
644
|
"createdAt",
|
|
645
645
|
"updatedAt"
|
|
646
646
|
) VALUES (
|
|
647
|
-
|
|
647
|
+
'00000000-0000-4000-a000-000000000004',
|
|
648
648
|
'usr-carlos-001',
|
|
649
649
|
'team-everpoint-001',
|
|
650
650
|
'about',
|
|
@@ -803,7 +803,7 @@ INSERT INTO public.pages (
|
|
|
803
803
|
"createdAt",
|
|
804
804
|
"updatedAt"
|
|
805
805
|
) VALUES (
|
|
806
|
-
|
|
806
|
+
'00000000-0000-4000-a000-000000000005',
|
|
807
807
|
'usr-carlos-001',
|
|
808
808
|
'team-everpoint-001',
|
|
809
809
|
'getting-started',
|
|
@@ -955,7 +955,7 @@ INSERT INTO public.pages (
|
|
|
955
955
|
"createdAt",
|
|
956
956
|
"updatedAt"
|
|
957
957
|
) VALUES (
|
|
958
|
-
|
|
958
|
+
'00000000-0000-4000-a000-000000000006',
|
|
959
959
|
'usr-carlos-001',
|
|
960
960
|
'team-everpoint-001',
|
|
961
961
|
'contact',
|
|
@@ -1068,7 +1068,7 @@ INSERT INTO public.pages (
|
|
|
1068
1068
|
"createdAt",
|
|
1069
1069
|
"updatedAt"
|
|
1070
1070
|
) VALUES (
|
|
1071
|
-
|
|
1071
|
+
'00000000-0000-4000-a000-000000000007',
|
|
1072
1072
|
'usr-carlos-001',
|
|
1073
1073
|
'team-everpoint-001',
|
|
1074
1074
|
'demo',
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
-- Migration: 098_patterns_sample_data.sql
|
|
2
|
+
-- Description: Sample patterns for testing pattern references and usage tracking
|
|
3
|
+
-- Date: 2025-01-17
|
|
4
|
+
|
|
5
|
+
-- =====================================================
|
|
6
|
+
-- PATTERNS SAMPLE DATA
|
|
7
|
+
-- =====================================================
|
|
8
|
+
|
|
9
|
+
-- Pattern 1: Newsletter CTA (Published)
|
|
10
|
+
INSERT INTO public.patterns (
|
|
11
|
+
id,
|
|
12
|
+
"userId",
|
|
13
|
+
"teamId",
|
|
14
|
+
title,
|
|
15
|
+
slug,
|
|
16
|
+
blocks,
|
|
17
|
+
status,
|
|
18
|
+
description,
|
|
19
|
+
"createdAt",
|
|
20
|
+
"updatedAt"
|
|
21
|
+
) VALUES (
|
|
22
|
+
'00000000-0000-4000-b000-000000000001',
|
|
23
|
+
'usr-carlos-001',
|
|
24
|
+
'team-everpoint-001',
|
|
25
|
+
'Newsletter CTA',
|
|
26
|
+
'newsletter-cta',
|
|
27
|
+
'[
|
|
28
|
+
{
|
|
29
|
+
"id": "newsletter-cta-block",
|
|
30
|
+
"blockSlug": "cta-section",
|
|
31
|
+
"props": {
|
|
32
|
+
"title": "Stay Updated",
|
|
33
|
+
"content": "Subscribe to our newsletter for the latest updates, tips, and exclusive content delivered straight to your inbox.",
|
|
34
|
+
"backgroundColor": "primary",
|
|
35
|
+
"textColor": "white",
|
|
36
|
+
"primaryCta": {
|
|
37
|
+
"label": "Subscribe Now",
|
|
38
|
+
"url": "/newsletter",
|
|
39
|
+
"variant": "secondary"
|
|
40
|
+
},
|
|
41
|
+
"secondaryCta": {
|
|
42
|
+
"label": "Learn More",
|
|
43
|
+
"url": "/about",
|
|
44
|
+
"variant": "outline"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
]',
|
|
49
|
+
'published',
|
|
50
|
+
'Reusable newsletter call-to-action section for pages',
|
|
51
|
+
NOW() - INTERVAL '7 days',
|
|
52
|
+
NOW() - INTERVAL '2 days'
|
|
53
|
+
) ON CONFLICT (id) DO UPDATE SET
|
|
54
|
+
title = EXCLUDED.title,
|
|
55
|
+
slug = EXCLUDED.slug,
|
|
56
|
+
blocks = EXCLUDED.blocks,
|
|
57
|
+
status = EXCLUDED.status,
|
|
58
|
+
description = EXCLUDED.description,
|
|
59
|
+
"updatedAt" = EXCLUDED."updatedAt";
|
|
60
|
+
|
|
61
|
+
-- Pattern 2: Footer Links (Published)
|
|
62
|
+
INSERT INTO public.patterns (
|
|
63
|
+
id,
|
|
64
|
+
"userId",
|
|
65
|
+
"teamId",
|
|
66
|
+
title,
|
|
67
|
+
slug,
|
|
68
|
+
blocks,
|
|
69
|
+
status,
|
|
70
|
+
description,
|
|
71
|
+
"createdAt",
|
|
72
|
+
"updatedAt"
|
|
73
|
+
) VALUES (
|
|
74
|
+
'00000000-0000-4000-b000-000000000002',
|
|
75
|
+
'usr-carlos-001',
|
|
76
|
+
'team-everpoint-001',
|
|
77
|
+
'Footer Links',
|
|
78
|
+
'footer-links',
|
|
79
|
+
'[
|
|
80
|
+
{
|
|
81
|
+
"id": "footer-links-block",
|
|
82
|
+
"blockSlug": "text-content",
|
|
83
|
+
"props": {
|
|
84
|
+
"content": "## Quick Links\n\n- [Home](/)\n- [Features](/features)\n- [Pricing](/pricing)\n- [About](/about)\n- [Contact](/contact)\n\n## Resources\n\n- [Documentation](/getting-started)\n- [API Reference](/api)\n- [Support](/support)\n- [Blog](/blog)",
|
|
85
|
+
"textAlign": "left",
|
|
86
|
+
"maxWidth": "4xl",
|
|
87
|
+
"padding": "lg"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
]',
|
|
91
|
+
'published',
|
|
92
|
+
'Common footer links section for all pages',
|
|
93
|
+
NOW() - INTERVAL '14 days',
|
|
94
|
+
NOW() - INTERVAL '5 days'
|
|
95
|
+
) ON CONFLICT (id) DO UPDATE SET
|
|
96
|
+
title = EXCLUDED.title,
|
|
97
|
+
slug = EXCLUDED.slug,
|
|
98
|
+
blocks = EXCLUDED.blocks,
|
|
99
|
+
status = EXCLUDED.status,
|
|
100
|
+
description = EXCLUDED.description,
|
|
101
|
+
"updatedAt" = EXCLUDED."updatedAt";
|
|
102
|
+
|
|
103
|
+
-- Pattern 3: Hero Header (Draft)
|
|
104
|
+
INSERT INTO public.patterns (
|
|
105
|
+
id,
|
|
106
|
+
"userId",
|
|
107
|
+
"teamId",
|
|
108
|
+
title,
|
|
109
|
+
slug,
|
|
110
|
+
blocks,
|
|
111
|
+
status,
|
|
112
|
+
description,
|
|
113
|
+
"createdAt",
|
|
114
|
+
"updatedAt"
|
|
115
|
+
) VALUES (
|
|
116
|
+
'00000000-0000-4000-b000-000000000003',
|
|
117
|
+
'usr-carlos-001',
|
|
118
|
+
'team-everpoint-001',
|
|
119
|
+
'Hero Header',
|
|
120
|
+
'hero-header',
|
|
121
|
+
'[
|
|
122
|
+
{
|
|
123
|
+
"id": "hero-header-block",
|
|
124
|
+
"blockSlug": "hero",
|
|
125
|
+
"props": {
|
|
126
|
+
"title": "Welcome to NextSpark",
|
|
127
|
+
"content": "The complete SaaS boilerplate for modern web applications. Build faster, scale smarter.",
|
|
128
|
+
"textAlign": "center",
|
|
129
|
+
"size": "lg",
|
|
130
|
+
"cta": {
|
|
131
|
+
"text": "Get Started",
|
|
132
|
+
"link": "/signup",
|
|
133
|
+
"variant": "default"
|
|
134
|
+
},
|
|
135
|
+
"secondaryCta": {
|
|
136
|
+
"text": "View Demo",
|
|
137
|
+
"link": "/demo",
|
|
138
|
+
"variant": "outline"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
]',
|
|
143
|
+
'draft',
|
|
144
|
+
'Standard hero header for landing pages (work in progress)',
|
|
145
|
+
NOW() - INTERVAL '3 days',
|
|
146
|
+
NOW() - INTERVAL '1 day'
|
|
147
|
+
) ON CONFLICT (id) DO UPDATE SET
|
|
148
|
+
title = EXCLUDED.title,
|
|
149
|
+
slug = EXCLUDED.slug,
|
|
150
|
+
blocks = EXCLUDED.blocks,
|
|
151
|
+
status = EXCLUDED.status,
|
|
152
|
+
description = EXCLUDED.description,
|
|
153
|
+
"updatedAt" = EXCLUDED."updatedAt";
|
|
154
|
+
|
|
155
|
+
-- =====================================================
|
|
156
|
+
-- PATTERN USAGES SAMPLE DATA
|
|
157
|
+
-- =====================================================
|
|
158
|
+
|
|
159
|
+
-- Usage 1: Newsletter CTA used in Home page
|
|
160
|
+
INSERT INTO public.pattern_usages (
|
|
161
|
+
id,
|
|
162
|
+
"patternId",
|
|
163
|
+
"entityType",
|
|
164
|
+
"entityId",
|
|
165
|
+
"teamId",
|
|
166
|
+
"createdAt"
|
|
167
|
+
) VALUES (
|
|
168
|
+
'00000000-0000-4000-c000-000000000001',
|
|
169
|
+
'00000000-0000-4000-b000-000000000001',
|
|
170
|
+
'pages',
|
|
171
|
+
'00000000-0000-4000-a000-000000000001',
|
|
172
|
+
'team-everpoint-001',
|
|
173
|
+
NOW() - INTERVAL '5 days'
|
|
174
|
+
) ON CONFLICT ("patternId", "entityType", "entityId") DO NOTHING;
|
|
175
|
+
|
|
176
|
+
-- Usage 2: Newsletter CTA used in Features page
|
|
177
|
+
INSERT INTO public.pattern_usages (
|
|
178
|
+
id,
|
|
179
|
+
"patternId",
|
|
180
|
+
"entityType",
|
|
181
|
+
"entityId",
|
|
182
|
+
"teamId",
|
|
183
|
+
"createdAt"
|
|
184
|
+
) VALUES (
|
|
185
|
+
'00000000-0000-4000-c000-000000000002',
|
|
186
|
+
'00000000-0000-4000-b000-000000000001',
|
|
187
|
+
'pages',
|
|
188
|
+
'00000000-0000-4000-a000-000000000002',
|
|
189
|
+
'team-everpoint-001',
|
|
190
|
+
NOW() - INTERVAL '4 days'
|
|
191
|
+
) ON CONFLICT ("patternId", "entityType", "entityId") DO NOTHING;
|
|
192
|
+
|
|
193
|
+
-- Usage 3: Footer Links used in Home page
|
|
194
|
+
INSERT INTO public.pattern_usages (
|
|
195
|
+
id,
|
|
196
|
+
"patternId",
|
|
197
|
+
"entityType",
|
|
198
|
+
"entityId",
|
|
199
|
+
"teamId",
|
|
200
|
+
"createdAt"
|
|
201
|
+
) VALUES (
|
|
202
|
+
'00000000-0000-4000-c000-000000000003',
|
|
203
|
+
'00000000-0000-4000-b000-000000000002',
|
|
204
|
+
'pages',
|
|
205
|
+
'00000000-0000-4000-a000-000000000001',
|
|
206
|
+
'team-everpoint-001',
|
|
207
|
+
NOW() - INTERVAL '10 days'
|
|
208
|
+
) ON CONFLICT ("patternId", "entityType", "entityId") DO NOTHING;
|
|
209
|
+
|
|
210
|
+
-- Usage 4: Footer Links used in About page
|
|
211
|
+
INSERT INTO public.pattern_usages (
|
|
212
|
+
id,
|
|
213
|
+
"patternId",
|
|
214
|
+
"entityType",
|
|
215
|
+
"entityId",
|
|
216
|
+
"teamId",
|
|
217
|
+
"createdAt"
|
|
218
|
+
) VALUES (
|
|
219
|
+
'00000000-0000-4000-c000-000000000004',
|
|
220
|
+
'00000000-0000-4000-b000-000000000002',
|
|
221
|
+
'pages',
|
|
222
|
+
'00000000-0000-4000-a000-000000000004',
|
|
223
|
+
'team-everpoint-001',
|
|
224
|
+
NOW() - INTERVAL '8 days'
|
|
225
|
+
) ON CONFLICT ("patternId", "entityType", "entityId") DO NOTHING;
|
|
226
|
+
|
|
227
|
+
-- =====================================================
|
|
228
|
+
-- VERIFICATION QUERIES (for manual testing)
|
|
229
|
+
-- =====================================================
|
|
230
|
+
-- SELECT id, title, status FROM patterns WHERE id::text LIKE '00000000-0000-4000-b000-%';
|
|
231
|
+
-- Expected: 3 rows (newsletter, footer-links, hero-header)
|
|
232
|
+
|
|
233
|
+
-- SELECT id, "patternId", "entityType", "entityId" FROM pattern_usages WHERE id::text LIKE '00000000-0000-4000-c000-%';
|
|
234
|
+
-- Expected: 4 rows
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextsparkjs/theme-default",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.51",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./config/theme.config.ts",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"react-dom": "^19.0.0",
|
|
18
18
|
"react-markdown": "^10.1.0",
|
|
19
19
|
"zod": "^4.0.0",
|
|
20
|
-
"@nextsparkjs/core": "0.1.0-beta.
|
|
21
|
-
"@nextsparkjs/testing": "0.1.0-beta.
|
|
20
|
+
"@nextsparkjs/core": "0.1.0-beta.51",
|
|
21
|
+
"@nextsparkjs/testing": "0.1.0-beta.51"
|
|
22
22
|
},
|
|
23
23
|
"nextspark": {
|
|
24
24
|
"type": "theme",
|