@nextsparkjs/theme-blog 0.1.0-beta.1

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 (64) hide show
  1. package/README.md +65 -0
  2. package/about.md +93 -0
  3. package/api/authors/[username]/route.ts +150 -0
  4. package/api/authors/route.ts +63 -0
  5. package/api/posts/public/route.ts +151 -0
  6. package/components/ExportPostsButton.tsx +102 -0
  7. package/components/ImportPostsDialog.tsx +284 -0
  8. package/components/PostsToolbar.tsx +24 -0
  9. package/components/editor/FeaturedImageUpload.tsx +185 -0
  10. package/components/editor/WysiwygEditor.tsx +340 -0
  11. package/components/index.ts +4 -0
  12. package/components/public/AuthorBio.tsx +105 -0
  13. package/components/public/AuthorCard.tsx +130 -0
  14. package/components/public/BlogFooter.tsx +185 -0
  15. package/components/public/BlogNavbar.tsx +201 -0
  16. package/components/public/PostCard.tsx +306 -0
  17. package/components/public/ReadingProgress.tsx +70 -0
  18. package/components/public/RelatedPosts.tsx +78 -0
  19. package/config/app.config.ts +200 -0
  20. package/config/billing.config.ts +146 -0
  21. package/config/dashboard.config.ts +333 -0
  22. package/config/dev.config.ts +48 -0
  23. package/config/features.config.ts +196 -0
  24. package/config/flows.config.ts +333 -0
  25. package/config/permissions.config.ts +101 -0
  26. package/config/theme.config.ts +128 -0
  27. package/entities/categories/categories.config.ts +60 -0
  28. package/entities/categories/categories.fields.ts +115 -0
  29. package/entities/categories/categories.service.ts +333 -0
  30. package/entities/categories/categories.types.ts +58 -0
  31. package/entities/categories/messages/en.json +33 -0
  32. package/entities/categories/messages/es.json +33 -0
  33. package/entities/posts/messages/en.json +100 -0
  34. package/entities/posts/messages/es.json +100 -0
  35. package/entities/posts/migrations/001_posts_table.sql +110 -0
  36. package/entities/posts/migrations/002_add_featured.sql +19 -0
  37. package/entities/posts/migrations/003_post_categories_pivot.sql +47 -0
  38. package/entities/posts/posts.config.ts +61 -0
  39. package/entities/posts/posts.fields.ts +234 -0
  40. package/entities/posts/posts.service.ts +464 -0
  41. package/entities/posts/posts.types.ts +80 -0
  42. package/lib/selectors.ts +179 -0
  43. package/messages/en.json +113 -0
  44. package/messages/es.json +113 -0
  45. package/migrations/002_author_profile_fields.sql +37 -0
  46. package/migrations/003_categories_table.sql +90 -0
  47. package/migrations/999_sample_data.sql +412 -0
  48. package/migrations/999_theme_sample_data.sql +1070 -0
  49. package/package.json +18 -0
  50. package/permissions-matrix.md +63 -0
  51. package/styles/article.css +333 -0
  52. package/styles/components.css +204 -0
  53. package/styles/globals.css +327 -0
  54. package/styles/theme.css +167 -0
  55. package/templates/(public)/author/[username]/page.tsx +247 -0
  56. package/templates/(public)/authors/page.tsx +161 -0
  57. package/templates/(public)/layout.tsx +44 -0
  58. package/templates/(public)/page.tsx +276 -0
  59. package/templates/(public)/posts/[slug]/page.tsx +342 -0
  60. package/templates/dashboard/(main)/page.tsx +385 -0
  61. package/templates/dashboard/(main)/posts/[id]/edit/page.tsx +529 -0
  62. package/templates/dashboard/(main)/posts/[id]/page.tsx +33 -0
  63. package/templates/dashboard/(main)/posts/create/page.tsx +353 -0
  64. package/templates/dashboard/(main)/posts/page.tsx +833 -0
@@ -0,0 +1,333 @@
1
+ /**
2
+ * Blog Theme - Dashboard Configuration
3
+ *
4
+ * Simplified dashboard focused on content creation.
5
+ */
6
+
7
+ export const DASHBOARD_CONFIG = {
8
+ // =============================================================================
9
+ // TOPBAR CONFIGURATION
10
+ // =============================================================================
11
+ topbar: {
12
+ search: {
13
+ enabled: true,
14
+ placeholder: 'dashboard.search.placeholder',
15
+ maxResults: 5,
16
+ },
17
+ notifications: {
18
+ enabled: false, // No notifications for single-user blog
19
+ },
20
+ themeToggle: {
21
+ enabled: true,
22
+ },
23
+ support: {
24
+ enabled: true,
25
+ type: 'dropdown',
26
+ links: [
27
+ {
28
+ label: 'common.help.documentation',
29
+ url: '/docs',
30
+ icon: 'book-open',
31
+ external: false,
32
+ },
33
+ ],
34
+ },
35
+ quickCreate: {
36
+ enabled: true,
37
+ },
38
+ /**
39
+ * Admin access button (Super Admin area)
40
+ */
41
+ adminAccess: {
42
+ enabled: true,
43
+ showToDevelopers: true,
44
+ },
45
+ /**
46
+ * Dev Zone access button (Developer area)
47
+ */
48
+ devtoolsAccess: {
49
+ enabled: true,
50
+ },
51
+ userMenu: {
52
+ enabled: true,
53
+ showAvatar: true,
54
+ showEmail: true,
55
+ showRole: false,
56
+ items: [
57
+ { type: 'link', label: 'navigation.profile', href: '/dashboard/settings/profile', icon: 'user' },
58
+ { type: 'link', label: 'navigation.settings', href: '/dashboard/settings', icon: 'settings' },
59
+ { type: 'divider' },
60
+ { type: 'link', label: 'blog.viewBlog', href: '/', icon: 'external-link' },
61
+ { type: 'divider' },
62
+ { type: 'action', label: 'buttons.signOut', action: 'signOut', icon: 'log-out' },
63
+ ],
64
+ },
65
+ },
66
+
67
+ // =============================================================================
68
+ // SIDEBAR CONFIGURATION
69
+ // =============================================================================
70
+ sidebar: {
71
+ defaultCollapsed: false,
72
+ rememberState: true,
73
+ collapsedWidth: '60px',
74
+ expandedWidth: '220px',
75
+ toggle: {
76
+ enabled: true,
77
+ showInTopbar: true,
78
+ hideOnMobile: false,
79
+ },
80
+ navigation: {
81
+ showEntityCounts: true,
82
+ groupEntities: false, // Simple flat navigation for blog
83
+ showRecents: true,
84
+ maxRecents: 3,
85
+ },
86
+ },
87
+
88
+ // =============================================================================
89
+ // SETTINGS PAGES
90
+ // =============================================================================
91
+ settings: {
92
+ pages: {
93
+ profile: {
94
+ enabled: true,
95
+ label: 'settings.pages.profile',
96
+ description: 'settings.pages.profileDescription',
97
+ icon: 'user',
98
+ order: 1,
99
+ features: {
100
+ avatarUpload: true,
101
+ nameChange: true,
102
+ emailChange: true,
103
+ localeChange: true,
104
+ timezoneChange: false,
105
+ },
106
+ },
107
+ security: {
108
+ enabled: true,
109
+ label: 'settings.pages.security',
110
+ description: 'settings.pages.securityDescription',
111
+ icon: 'shield',
112
+ order: 2,
113
+ features: {
114
+ twoFactorAuth: false, // Simplified for personal blog
115
+ sessionManagement: true,
116
+ loginHistory: false,
117
+ securityQuestions: false,
118
+ },
119
+ },
120
+ password: {
121
+ enabled: true,
122
+ label: 'settings.pages.password',
123
+ description: 'settings.pages.passwordDescription',
124
+ icon: 'key',
125
+ order: 3,
126
+ features: {
127
+ passwordChange: true,
128
+ passwordStrength: true,
129
+ passwordHistory: false,
130
+ },
131
+ },
132
+ notifications: {
133
+ enabled: false, // No notifications
134
+ label: 'settings.pages.notifications',
135
+ description: 'settings.pages.notificationsDescription',
136
+ icon: 'bell',
137
+ order: 4,
138
+ features: {},
139
+ },
140
+ 'api-keys': {
141
+ enabled: false, // Not needed for personal blog
142
+ label: 'settings.pages.apiKeys',
143
+ description: 'settings.pages.apiKeysDescription',
144
+ icon: 'key',
145
+ order: 5,
146
+ features: {},
147
+ },
148
+ billing: {
149
+ enabled: true,
150
+ label: 'settings.pages.billing',
151
+ description: 'settings.pages.billingDescription',
152
+ icon: 'credit-card',
153
+ order: 6,
154
+ features: {},
155
+ },
156
+ teams: {
157
+ enabled: false, // No teams in single-user mode
158
+ label: 'settings.pages.teams',
159
+ description: 'settings.pages.teamsDescription',
160
+ icon: 'users',
161
+ order: 7,
162
+ features: {},
163
+ },
164
+ plans: {
165
+ enabled: true,
166
+ label: 'settings.pages.plans',
167
+ description: 'settings.pages.plansDescription',
168
+ icon: 'credit-card',
169
+ order: 8,
170
+ features: {
171
+ planComparison: true,
172
+ planSelection: true,
173
+ },
174
+ },
175
+ },
176
+ layout: {
177
+ showDescription: true,
178
+ showIcons: true,
179
+ groupByCategory: false,
180
+ enableSearch: false,
181
+ },
182
+ },
183
+
184
+ // =============================================================================
185
+ // ENTITY PAGES
186
+ // =============================================================================
187
+ entities: {
188
+ defaultListView: {
189
+ pagination: {
190
+ defaultPageSize: 10,
191
+ allowedPageSizes: [10, 25, 50],
192
+ showSizeSelector: true,
193
+ },
194
+ sorting: {
195
+ enabled: true,
196
+ defaultSort: { field: 'createdAt', direction: 'desc' },
197
+ rememberSort: true,
198
+ },
199
+ filtering: {
200
+ enabled: true,
201
+ quickFilters: true,
202
+ advancedFilters: false,
203
+ rememberFilters: false,
204
+ },
205
+ search: {
206
+ enabled: true,
207
+ placeholder: 'dashboard.entities.searchPlaceholder',
208
+ searchableFields: ['title', 'content', 'excerpt'],
209
+ instantSearch: true,
210
+ debounceMs: 300,
211
+ },
212
+ },
213
+ defaultFormView: {
214
+ validation: {
215
+ validateOnBlur: true,
216
+ validateOnChange: false,
217
+ showFieldErrors: true,
218
+ showFormErrors: true,
219
+ },
220
+ autosave: {
221
+ enabled: true, // Autosave for blog posts
222
+ intervalMs: 30000,
223
+ showIndicator: true,
224
+ },
225
+ confirmation: {
226
+ showOnCreate: false,
227
+ showOnUpdate: false,
228
+ showOnDelete: true,
229
+ },
230
+ },
231
+ customizations: {
232
+ posts: {
233
+ listView: {
234
+ defaultSort: { field: 'createdAt', direction: 'desc' },
235
+ quickFilters: ['status'],
236
+ },
237
+ formView: {
238
+ autosave: { enabled: true },
239
+ },
240
+ },
241
+ },
242
+ },
243
+
244
+ // =============================================================================
245
+ // DASHBOARD HOMEPAGE
246
+ // =============================================================================
247
+ homepage: {
248
+ widgets: {
249
+ welcome: {
250
+ enabled: true,
251
+ showUserName: true,
252
+ showLastLogin: false,
253
+ showQuickActions: true,
254
+ },
255
+ stats: {
256
+ enabled: true,
257
+ entities: ['posts'],
258
+ timeframe: '30days',
259
+ showTrends: false,
260
+ },
261
+ recentActivity: {
262
+ enabled: true,
263
+ maxItems: 5,
264
+ entities: ['posts'],
265
+ showTimestamps: true,
266
+ },
267
+ quickActions: {
268
+ enabled: true,
269
+ actions: [
270
+ { entity: 'posts', action: 'create', label: 'blog.quickActions.writePost' },
271
+ ],
272
+ },
273
+ },
274
+ layout: {
275
+ columns: 2,
276
+ gutter: 'medium',
277
+ responsive: true,
278
+ },
279
+ },
280
+
281
+ // =============================================================================
282
+ // PERFORMANCE
283
+ // =============================================================================
284
+ performance: {
285
+ cache: {
286
+ entityConfigs: { enabled: true, duration: 5 * 60 * 1000 },
287
+ entityData: { enabled: true, duration: 2 * 60 * 1000 },
288
+ },
289
+ loading: {
290
+ showSkeletons: true,
291
+ showProgressBars: true,
292
+ minimumLoadingTime: 200,
293
+ },
294
+ errors: {
295
+ showErrorBoundaries: true,
296
+ logErrors: true,
297
+ enableRetry: true,
298
+ maxRetries: 2,
299
+ },
300
+ },
301
+
302
+ // =============================================================================
303
+ // ACCESSIBILITY
304
+ // =============================================================================
305
+ accessibility: {
306
+ keyboard: {
307
+ enabled: true,
308
+ showShortcuts: true,
309
+ customShortcuts: {
310
+ 'Ctrl+K': 'openSearch',
311
+ 'Ctrl+Shift+N': 'quickCreate',
312
+ 'Ctrl+B': 'toggleSidebar',
313
+ 'Esc': 'closeModals',
314
+ },
315
+ },
316
+ screenReader: {
317
+ announceNavigation: true,
318
+ announceActions: true,
319
+ announceErrors: true,
320
+ },
321
+ visual: {
322
+ showFocusOutlines: true,
323
+ highContrastMode: false,
324
+ reducedMotion: false,
325
+ },
326
+ },
327
+ } as const
328
+
329
+ export const TOPBAR_CONFIG = DASHBOARD_CONFIG.topbar
330
+ export const SIDEBAR_CONFIG = DASHBOARD_CONFIG.sidebar
331
+ export const SETTINGS_CONFIG = DASHBOARD_CONFIG.settings
332
+ export const ENTITIES_CONFIG = DASHBOARD_CONFIG.entities
333
+ export const HOMEPAGE_CONFIG = DASHBOARD_CONFIG.homepage
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Blog Theme - Development Configuration
3
+ *
4
+ * This file contains development-only settings that should never affect production.
5
+ * Settings like DevKeyring are only rendered in non-production environments.
6
+ *
7
+ * @see core/lib/config/types.ts for DevConfig interface
8
+ */
9
+
10
+ import type { DevConfig } from '@nextsparkjs/core/lib/config/types'
11
+
12
+ export const DEV_CONFIG_OVERRIDES: DevConfig = {
13
+ // =============================================================================
14
+ // DEV KEYRING (Development/QA Only)
15
+ // =============================================================================
16
+ /**
17
+ * DevKeyring - Quick login for Blog theme (multi-author mode)
18
+ * 3 sample authors with different niches
19
+ */
20
+ devKeyring: {
21
+ enabled: true,
22
+ users: [
23
+ {
24
+ id: 'marcos',
25
+ email: 'blog_author_marcos@nextspark.dev',
26
+ name: 'Marcos Tech',
27
+ password: 'Test1234',
28
+ teamRoles: 'Marcos Tech Blog (owner)',
29
+ },
30
+ {
31
+ id: 'lucia',
32
+ email: 'blog_author_lucia@nextspark.dev',
33
+ name: 'Lucia Lifestyle',
34
+ password: 'Test1234',
35
+ teamRoles: 'Lucia Lifestyle Blog (owner)',
36
+ },
37
+ {
38
+ id: 'carlos',
39
+ email: 'blog_author_carlos@nextspark.dev',
40
+ name: 'Carlos Finance',
41
+ password: 'Test1234',
42
+ teamRoles: 'Carlos Finance Blog (owner)',
43
+ },
44
+ ],
45
+ },
46
+ }
47
+
48
+ export default DEV_CONFIG_OVERRIDES
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Blog Theme - Features Configuration
3
+ *
4
+ * Defines all features of the application for this theme.
5
+ * Each feature key becomes a tag: @feat-{key}
6
+ *
7
+ * Features are enriched at build-time with:
8
+ * - Entity metadata (from entity-registry)
9
+ * - Permission details (from permissions-registry)
10
+ * - Documentation links (from docs-registry)
11
+ * - Test coverage (from tags-registry + test files)
12
+ */
13
+
14
+ import { defineFeatures } from '@nextsparkjs/core/lib/config/features-types'
15
+
16
+ export default defineFeatures({
17
+ // ===========================================================================
18
+ // ENTITY FEATURES
19
+ // Blog-specific entity CRUD features
20
+ // ===========================================================================
21
+
22
+ posts: {
23
+ name: 'Posts',
24
+ description: 'Blog posts with rich text editor, featured images, and publishing workflow',
25
+ category: 'entities',
26
+ icon: 'file-text',
27
+ entities: ['posts'],
28
+ permissions: ['posts.*'],
29
+ docs: [],
30
+ },
31
+
32
+ categories: {
33
+ name: 'Categories',
34
+ description: 'Post categorization and taxonomy management',
35
+ category: 'entities',
36
+ icon: 'folder',
37
+ entities: ['categories'],
38
+ permissions: ['categories.*'],
39
+ docs: [],
40
+ },
41
+
42
+ // ===========================================================================
43
+ // CONTENT FEATURES
44
+ // Content creation and editing tools
45
+ // ===========================================================================
46
+
47
+ 'post-editor': {
48
+ name: 'Post Editor',
49
+ description: 'WYSIWYG editor for creating and editing blog posts',
50
+ category: 'content',
51
+ icon: 'edit',
52
+ entities: ['posts'],
53
+ permissions: ['posts.create', 'posts.update'],
54
+ docs: [],
55
+ },
56
+
57
+ publishing: {
58
+ name: 'Publishing',
59
+ description: 'Post publishing workflow with draft, scheduled, and published states',
60
+ category: 'content',
61
+ icon: 'send',
62
+ entities: ['posts'],
63
+ permissions: ['posts.publish', 'posts.unpublish'],
64
+ docs: [],
65
+ },
66
+
67
+ // ===========================================================================
68
+ // IMPORT/EXPORT FEATURES
69
+ // Data management tools
70
+ // ===========================================================================
71
+
72
+ 'post-export': {
73
+ name: 'Export Posts',
74
+ description: 'Export posts to JSON format for backup or migration',
75
+ category: 'settings',
76
+ icon: 'download',
77
+ entities: ['posts'],
78
+ permissions: ['blog.export'],
79
+ docs: [],
80
+ },
81
+
82
+ 'post-import': {
83
+ name: 'Import Posts',
84
+ description: 'Import posts from JSON file',
85
+ category: 'settings',
86
+ icon: 'upload',
87
+ entities: ['posts'],
88
+ permissions: ['blog.import'],
89
+ docs: [],
90
+ },
91
+
92
+ // ===========================================================================
93
+ // PUBLIC FEATURES
94
+ // Public-facing blog features
95
+ // ===========================================================================
96
+
97
+ 'public-blog': {
98
+ name: 'Public Blog',
99
+ description: 'Public blog pages including home, post detail, and author pages',
100
+ category: 'public',
101
+ icon: 'globe',
102
+ entities: ['posts', 'categories'],
103
+ permissions: [],
104
+ docs: [],
105
+ },
106
+
107
+ authors: {
108
+ name: 'Authors',
109
+ description: 'Author profile pages and author listing',
110
+ category: 'public',
111
+ icon: 'users',
112
+ entities: [],
113
+ permissions: [],
114
+ docs: [],
115
+ },
116
+
117
+ // ===========================================================================
118
+ // CORE FEATURES
119
+ // Platform-level features
120
+ // ===========================================================================
121
+
122
+ auth: {
123
+ name: 'Authentication',
124
+ description: 'User authentication and account security (single-user mode)',
125
+ category: 'core',
126
+ icon: 'shield',
127
+ entities: [],
128
+ permissions: ['auth.*'],
129
+ docs: [],
130
+ },
131
+
132
+ // ===========================================================================
133
+ // SETTINGS FEATURES
134
+ // User settings
135
+ // ===========================================================================
136
+
137
+ users: {
138
+ name: 'User Profile',
139
+ description: 'User profile management and preferences',
140
+ category: 'settings',
141
+ icon: 'user',
142
+ entities: [],
143
+ permissions: ['profile.*'],
144
+ docs: [],
145
+ },
146
+
147
+ // ===========================================================================
148
+ // BILLING FEATURES
149
+ // Plans and payments
150
+ // ===========================================================================
151
+
152
+ plans: {
153
+ name: 'Plans',
154
+ description: 'Plan catalog and selection',
155
+ category: 'settings',
156
+ icon: 'credit-card',
157
+ entities: [],
158
+ permissions: ['plans.*'],
159
+ docs: [],
160
+ },
161
+
162
+ billing: {
163
+ name: 'Billing',
164
+ description: 'Subscription management and payments',
165
+ category: 'settings',
166
+ icon: 'receipt',
167
+ entities: [],
168
+ permissions: ['billing.*', 'subscriptions.*'],
169
+ docs: [],
170
+ },
171
+
172
+ // ===========================================================================
173
+ // ADMIN FEATURES
174
+ // Superadmin and developer tools
175
+ // ===========================================================================
176
+
177
+ superadmin: {
178
+ name: 'Superadmin',
179
+ description: 'Superadmin dashboard and system management',
180
+ category: 'admin',
181
+ icon: 'shield-check',
182
+ entities: [],
183
+ permissions: ['superadmin.*'],
184
+ docs: [],
185
+ },
186
+
187
+ devtools: {
188
+ name: 'Developer Tools',
189
+ description: 'Development tools and configuration inspectors',
190
+ category: 'admin',
191
+ icon: 'terminal',
192
+ entities: [],
193
+ permissions: ['developer.*'],
194
+ docs: [],
195
+ },
196
+ })