@djangocfg/nextjs 1.0.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 (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +449 -0
  3. package/package.json +133 -0
  4. package/src/components/HomePage.tsx +73 -0
  5. package/src/components/index.ts +7 -0
  6. package/src/config/base-next-config.ts +262 -0
  7. package/src/config/index.ts +6 -0
  8. package/src/contact/index.ts +13 -0
  9. package/src/contact/route.ts +102 -0
  10. package/src/contact/submit.ts +80 -0
  11. package/src/errors/ErrorLayout.tsx +228 -0
  12. package/src/errors/errorConfig.ts +118 -0
  13. package/src/errors/index.ts +10 -0
  14. package/src/health/index.ts +7 -0
  15. package/src/health/route.ts +65 -0
  16. package/src/health/types.ts +19 -0
  17. package/src/index.ts +36 -0
  18. package/src/legal/LegalPage.tsx +85 -0
  19. package/src/legal/configs.ts +131 -0
  20. package/src/legal/index.ts +24 -0
  21. package/src/legal/pages.tsx +58 -0
  22. package/src/legal/types.ts +15 -0
  23. package/src/navigation/index.ts +9 -0
  24. package/src/navigation/types.ts +68 -0
  25. package/src/navigation/utils.ts +181 -0
  26. package/src/og-image/README.md +66 -0
  27. package/src/og-image/components/DefaultTemplate.tsx +369 -0
  28. package/src/og-image/components/index.ts +9 -0
  29. package/src/og-image/index.ts +27 -0
  30. package/src/og-image/route.tsx +253 -0
  31. package/src/og-image/types.ts +46 -0
  32. package/src/og-image/utils/fonts.ts +150 -0
  33. package/src/og-image/utils/index.ts +28 -0
  34. package/src/og-image/utils/metadata.ts +235 -0
  35. package/src/og-image/utils/url.ts +327 -0
  36. package/src/sitemap/generator.ts +64 -0
  37. package/src/sitemap/index.ts +8 -0
  38. package/src/sitemap/route.ts +74 -0
  39. package/src/sitemap/types.ts +20 -0
  40. package/src/types.ts +35 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Reforms.ai
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,449 @@
1
+ # @djangocfg/nextjs
2
+
3
+ > Comprehensive Next.js utilities and components: sitemap generation, health checks, OG images, legal pages, error pages, and more
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@djangocfg/nextjs.svg)](https://www.npmjs.com/package/@djangocfg/nextjs)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ **Part of [DjangoCFG](https://djangocfg.com)** — a modern Django framework for building production-ready SaaS applications. All `@djangocfg/*` packages are designed to work together, providing type-safe configuration, real-time features, and beautiful admin interfaces out of the box.
9
+
10
+ ---
11
+
12
+ ## Overview
13
+
14
+ `@djangocfg/nextjs` provides a comprehensive set of utilities and components for Next.js applications. From SEO optimization with sitemaps to health monitoring, from dynamic OG images to ready-to-use legal pages, this package covers common Next.js needs out of the box.
15
+
16
+ ## Features
17
+
18
+ - **Base Next.js Config** - Universal, reusable Next.js configuration factory for monorepos
19
+ - **Sitemap Generation** - Dynamic XML sitemap generation for SEO
20
+ - **Health Checks** - Production-ready health monitoring endpoints
21
+ - **OG Images** - Dynamic Open Graph image generation with templates
22
+ - **Navigation Utilities** - Route definitions, menu generation, and navigation helpers
23
+ - **Legal Pages** - Pre-built privacy, terms, cookies, and security pages
24
+ - **Error Pages** - Reusable 404 and 500 error layouts
25
+ - **HomePage Component** - Smart authentication redirect component
26
+ - **TypeScript** - Full type safety throughout
27
+ - **Self-Contained** - No external dependencies beyond Next.js
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ npm install @djangocfg/nextjs
33
+ # or
34
+ pnpm add @djangocfg/nextjs
35
+ # or
36
+ yarn add @djangocfg/nextjs
37
+ ```
38
+
39
+ ## Quick Start
40
+
41
+ ### Base Next.js Configuration
42
+
43
+ Create a reusable base configuration for all your Next.js projects:
44
+
45
+ ```tsx
46
+ // next.config.ts
47
+ import { createBaseNextConfig } from '@djangocfg/nextjs/config';
48
+ import bundleAnalyzer from '@next/bundle-analyzer';
49
+
50
+ const withBundleAnalyzer = bundleAnalyzer({
51
+ enabled: process.env.ANALYZE === 'true',
52
+ });
53
+
54
+ export default withBundleAnalyzer(createBaseNextConfig({
55
+ // Base path for static builds
56
+ basePath: process.env.NEXT_PUBLIC_STATIC_BUILD === 'true' ? '/cfg/admin' : undefined,
57
+
58
+ // Add custom transpile packages
59
+ transpilePackages: ['my-custom-package'],
60
+
61
+ // Custom webpack configuration (called after base webpack logic)
62
+ webpack: (config, options) => {
63
+ // Your custom webpack rules
64
+ return config;
65
+ },
66
+ }));
67
+ ```
68
+
69
+ ### Sitemap Generation
70
+
71
+ Generate dynamic XML sitemaps for SEO:
72
+
73
+ ```tsx
74
+ // app/sitemap.ts
75
+ import { createSitemapHandler } from '@djangocfg/nextjs/sitemap';
76
+
77
+ export default createSitemapHandler({
78
+ siteUrl: 'https://example.com',
79
+ staticPages: [
80
+ { loc: '/', changefreq: 'daily', priority: 1.0 },
81
+ { loc: '/about', changefreq: 'monthly', priority: 0.8 },
82
+ ],
83
+ dynamicPages: async () => {
84
+ const posts = await fetchPosts();
85
+ return posts.map(post => ({
86
+ loc: `/posts/${post.slug}`,
87
+ lastmod: post.updatedAt,
88
+ changefreq: 'weekly',
89
+ priority: 0.7,
90
+ }));
91
+ },
92
+ });
93
+ ```
94
+
95
+ ### Health Check Endpoint
96
+
97
+ Create a health monitoring endpoint:
98
+
99
+ ```tsx
100
+ // app/api/health/route.ts
101
+ import { createHealthHandler } from '@djangocfg/nextjs/health';
102
+
103
+ export const GET = createHealthHandler({
104
+ version: process.env.NEXT_PUBLIC_APP_VERSION || '1.0.0',
105
+ checks: [
106
+ {
107
+ name: 'database',
108
+ check: async () => {
109
+ // Check database connection
110
+ return await checkDatabase();
111
+ },
112
+ },
113
+ ],
114
+ });
115
+ ```
116
+
117
+ ### OG Image Generation
118
+
119
+ Generate dynamic Open Graph images with custom templates:
120
+
121
+ ```tsx
122
+ // app/api/og/route.tsx
123
+ import { createOgImageHandler } from '@djangocfg/nextjs/og-image';
124
+ import { OgImageTemplate } from '@/components/OgImageTemplate';
125
+
126
+ export const runtime = 'edge';
127
+
128
+ const handler = createOgImageHandler({
129
+ template: OgImageTemplate,
130
+ defaultProps: {
131
+ siteName: 'My App',
132
+ logo: '/logo.svg',
133
+ },
134
+ fonts: [
135
+ { family: 'Manrope', weight: 700 },
136
+ { family: 'Manrope', weight: 500 },
137
+ ],
138
+ size: { width: 1200, height: 630 },
139
+ });
140
+
141
+ export async function GET(request: NextRequest) {
142
+ return handler.GET(request);
143
+ }
144
+ ```
145
+
146
+ Automatically add OG images to page metadata:
147
+
148
+ ```tsx
149
+ // app/page.tsx
150
+ import { generateMetadata } from '@core/metadata';
151
+
152
+ export const metadata = generateMetadata({
153
+ title: 'My Page',
154
+ description: 'Page description',
155
+ });
156
+ ```
157
+
158
+ ### Legal Pages
159
+
160
+ Use pre-built legal pages:
161
+
162
+ ```tsx
163
+ // app/legal/privacy/page.tsx
164
+ import { PrivacyPage } from '@djangocfg/nextjs/legal';
165
+
166
+ export default PrivacyPage;
167
+ ```
168
+
169
+ Available pages:
170
+ - `PrivacyPage` - Privacy policy
171
+ - `TermsPage` - Terms of service
172
+ - `CookiesPage` - Cookie policy
173
+ - `SecurityPage` - Security policy
174
+
175
+ ### Error Pages
176
+
177
+ Use reusable error layouts:
178
+
179
+ ```tsx
180
+ // app/not-found.tsx
181
+ import { ErrorLayout } from '@djangocfg/nextjs/errors';
182
+
183
+ export default function NotFound() {
184
+ return <ErrorLayout code={404} supportEmail="support@example.com" />;
185
+ }
186
+ ```
187
+
188
+ ```tsx
189
+ // app/error.tsx
190
+ 'use client';
191
+
192
+ import { useEffect } from 'react';
193
+ import { ErrorLayout } from '@djangocfg/nextjs/errors';
194
+
195
+ export default function Error({ error, reset }: { error: Error; reset: () => void }) {
196
+ useEffect(() => {
197
+ console.error('Error:', error);
198
+ }, [error]);
199
+
200
+ return <ErrorLayout code={500} supportEmail="support@example.com" />;
201
+ }
202
+ ```
203
+
204
+ ### HomePage Component
205
+
206
+ Smart authentication redirect component:
207
+
208
+ ```tsx
209
+ // app/page.tsx
210
+ import { HomePage } from '@djangocfg/nextjs/components';
211
+
212
+ export default function Page() {
213
+ return (
214
+ <HomePage
215
+ authenticatedPath="/dashboard"
216
+ unauthenticatedPath="/auth"
217
+ loadingText="Loading..."
218
+ />
219
+ );
220
+ }
221
+ ```
222
+
223
+ ## Exports
224
+
225
+ | Path | Description |
226
+ |------|-------------|
227
+ | `@djangocfg/nextjs` | Main exports (all modules) |
228
+ | `@djangocfg/nextjs/config` | Base Next.js configuration factory |
229
+ | `@djangocfg/nextjs/sitemap` | Sitemap generation utilities |
230
+ | `@djangocfg/nextjs/health` | Health check handlers |
231
+ | `@djangocfg/nextjs/og-image` | OG image generation |
232
+ | `@djangocfg/nextjs/og-image/utils` | OG image URL and metadata utilities |
233
+ | `@djangocfg/nextjs/navigation` | Route definitions, menu generation, navigation helpers |
234
+ | `@djangocfg/nextjs/legal` | Legal page components |
235
+ | `@djangocfg/nextjs/errors` | Error page layouts |
236
+ | `@djangocfg/nextjs/components` | Reusable components |
237
+
238
+ ## API Reference
239
+
240
+ ### Base Configuration
241
+
242
+ #### `createBaseNextConfig(options)`
243
+
244
+ Creates a reusable base Next.js configuration with standard DjangoCFG settings.
245
+
246
+ ```tsx
247
+ createBaseNextConfig({
248
+ basePath?: string; // Base path for static builds
249
+ transpilePackages?: string[]; // Additional packages to transpile
250
+ optimizePackageImports?: string[]; // Additional packages to optimize
251
+ webpack?: (config, options) => config; // Custom webpack configuration
252
+ experimental?: NextConfig['experimental']; // Custom experimental options
253
+ env?: Record<string, string>; // Custom environment variables
254
+ // ... any other NextConfig options
255
+ })
256
+ ```
257
+
258
+ **Features:**
259
+ - Automatic dev/production optimizations
260
+ - Filesystem caching for faster rebuilds
261
+ - Compression plugins for static builds (Gzip + Brotli)
262
+ - Standard transpile packages for monorepo
263
+ - Type-safe configuration merging
264
+
265
+ ### Sitemap
266
+
267
+ #### `createSitemapHandler(options)`
268
+
269
+ Creates a Next.js route handler for sitemap generation.
270
+
271
+ ```tsx
272
+ createSitemapHandler({
273
+ siteUrl: string;
274
+ staticPages?: SitemapUrl[];
275
+ dynamicPages?: SitemapUrl[] | (() => Promise<SitemapUrl[]>);
276
+ cacheControl?: string;
277
+ })
278
+ ```
279
+
280
+ ### Health
281
+
282
+ #### `createHealthHandler(config)`
283
+
284
+ Creates a health check route handler.
285
+
286
+ ```tsx
287
+ createHealthHandler({
288
+ version?: string;
289
+ checks?: Array<{ name: string; check: () => Promise<boolean> }>;
290
+ customData?: Record<string, any>;
291
+ })
292
+ ```
293
+
294
+ ### OG Image
295
+
296
+ #### `createOgImageHandler(config)`
297
+
298
+ Creates an OG image generation handler with custom template component.
299
+
300
+ ```tsx
301
+ createOgImageHandler({
302
+ template: (props: OgImageTemplateProps) => ReactElement; // Template component
303
+ defaultProps?: Partial<OgImageTemplateProps>; // Default props
304
+ fonts?: Array<{ family: string; weight: number }>; // Google Fonts to load
305
+ size?: { width: number; height: number }; // Image dimensions
306
+ debug?: boolean; // Enable debug mode
307
+ })
308
+ ```
309
+
310
+ #### `generateOgImageMetadata(metadata, params?, options?)`
311
+
312
+ Automatically adds OG image to Next.js metadata.
313
+
314
+ ```tsx
315
+ generateOgImageMetadata(
316
+ metadata: Metadata, // Base metadata
317
+ ogImageParams?: Partial<OgImageUrlParams>, // Optional explicit params
318
+ options?: {
319
+ ogImageBaseUrl?: string; // Default: '/api/og'
320
+ siteUrl?: string; // Auto-detected if not provided
321
+ defaultParams?: Partial<OgImageUrlParams>; // Default params
322
+ useBase64?: boolean; // Default: true
323
+ }
324
+ )
325
+ ```
326
+
327
+ #### `generateOgImageUrl(baseUrl, params, useBase64?)`
328
+
329
+ Generates OG image URL with base64-encoded parameters.
330
+
331
+ ```tsx
332
+ generateOgImageUrl('/api/og', {
333
+ title: 'My Page',
334
+ description: 'Page description',
335
+ siteName: 'My Site',
336
+ logo: '/logo.svg',
337
+ }, true) // useBase64 = true (default)
338
+ ```
339
+
340
+ ### Navigation
341
+
342
+ #### `defineRoute(path, metadata, config?)`
343
+
344
+ Defines a route with metadata.
345
+
346
+ ```tsx
347
+ defineRoute('/dashboard', {
348
+ title: 'Dashboard',
349
+ description: 'Dashboard overview',
350
+ }, {
351
+ basePath: '/admin',
352
+ isStaticBuild: false,
353
+ })
354
+ ```
355
+
356
+ #### `isActive(current, target, allRoutes?)`
357
+
358
+ Checks if a route is currently active.
359
+
360
+ ```tsx
361
+ isActive('/admin/dashboard', '/admin/dashboard') // true
362
+ isActive('/admin/dashboard/settings', '/admin/dashboard') // true
363
+ isActive('/admin/dashboard', '/admin/settings') // false
364
+ ```
365
+
366
+ #### `routesToMenuItems(routes)`
367
+
368
+ Converts route definitions to menu items.
369
+
370
+ ```tsx
371
+ const menuItems = routesToMenuItems(allRoutes);
372
+ ```
373
+
374
+ ### Legal Pages
375
+
376
+ #### `PrivacyPage`, `TermsPage`, `CookiesPage`, `SecurityPage`
377
+
378
+ Pre-built legal page components with default content. Can be customized:
379
+
380
+ ```tsx
381
+ import { PrivacyPage, privacyConfig } from '@djangocfg/nextjs/legal';
382
+
383
+ // Use default
384
+ export default PrivacyPage;
385
+
386
+ // Or customize
387
+ export default function CustomPrivacy() {
388
+ return <PrivacyPage config={{
389
+ ...privacyConfig,
390
+ lastUpdated: '2024-01-01',
391
+ }} />;
392
+ }
393
+ ```
394
+
395
+ ### Error Pages
396
+
397
+ #### `ErrorLayout`
398
+
399
+ Reusable error page layout component.
400
+
401
+ ```tsx
402
+ <ErrorLayout
403
+ code={404 | 500 | string | number}
404
+ title?: string
405
+ description?: string
406
+ supportEmail?: string
407
+ actions?: React.ReactNode
408
+ showDefaultActions?: boolean
409
+ />
410
+ ```
411
+
412
+ ### Components
413
+
414
+ #### `HomePage`
415
+
416
+ Authentication redirect component.
417
+
418
+ ```tsx
419
+ <HomePage
420
+ authenticatedPath?: string // Default: '/private'
421
+ unauthenticatedPath?: string // Default: '/auth'
422
+ loadingText?: string // Default: 'Loading...'
423
+ />
424
+ ```
425
+
426
+ ## Requirements
427
+
428
+ - Next.js >= 13.0.0 (App Router)
429
+ - React >= 18.0.0
430
+ - TypeScript >= 5.0.0
431
+
432
+ ## Peer Dependencies
433
+
434
+ - `@djangocfg/layouts` - For auth context in HomePage
435
+ - `@djangocfg/ui` - For UI components in legal/error pages
436
+ - `lucide-react` - For icons
437
+
438
+ ## Documentation
439
+
440
+ Full documentation available at [djangocfg.com](https://djangocfg.com)
441
+
442
+ ## Contributing
443
+
444
+ Issues and pull requests are welcome at [GitHub](https://github.com/markolofsen/django-cfg)
445
+
446
+ ## License
447
+
448
+ MIT - see [LICENSE](./LICENSE) for details
449
+
package/package.json ADDED
@@ -0,0 +1,133 @@
1
+ {
2
+ "name": "@djangocfg/nextjs",
3
+ "version": "1.0.1",
4
+ "description": "Next.js utilities and components: sitemap, health, OG images, legal pages, error pages",
5
+ "keywords": [
6
+ "nextjs",
7
+ "sitemap",
8
+ "health",
9
+ "og-image",
10
+ "legal-pages",
11
+ "error-pages",
12
+ "react",
13
+ "typescript"
14
+ ],
15
+ "author": {
16
+ "name": "DjangoCFG",
17
+ "url": "https://djangocfg.com"
18
+ },
19
+ "homepage": "https://djangocfg.com",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/markolofsen/django-cfg.git",
23
+ "directory": "packages/nextjs"
24
+ },
25
+ "bugs": {
26
+ "url": "https://github.com/markolofsen/django-cfg/issues"
27
+ },
28
+ "license": "MIT",
29
+ "main": "./src/index.ts",
30
+ "types": "./src/index.ts",
31
+ "exports": {
32
+ ".": {
33
+ "types": "./src/index.ts",
34
+ "import": "./src/index.ts",
35
+ "default": "./src/index.ts"
36
+ },
37
+ "./sitemap": {
38
+ "types": "./src/sitemap/index.ts",
39
+ "import": "./src/sitemap/index.ts",
40
+ "default": "./src/sitemap/index.ts"
41
+ },
42
+ "./health": {
43
+ "types": "./src/health/index.ts",
44
+ "import": "./src/health/index.ts",
45
+ "default": "./src/health/index.ts"
46
+ },
47
+ "./og-image": {
48
+ "types": "./src/og-image/index.ts",
49
+ "import": "./src/og-image/index.ts",
50
+ "default": "./src/og-image/index.ts"
51
+ },
52
+ "./og-image/utils": {
53
+ "types": "./src/og-image/utils/index.ts",
54
+ "import": "./src/og-image/utils/index.ts",
55
+ "default": "./src/og-image/utils/index.ts"
56
+ },
57
+ "./og-image/components": {
58
+ "types": "./src/og-image/components/index.ts",
59
+ "import": "./src/og-image/components/index.ts",
60
+ "default": "./src/og-image/components/index.ts"
61
+ },
62
+ "./legal": {
63
+ "types": "./src/legal/index.ts",
64
+ "import": "./src/legal/index.ts",
65
+ "default": "./src/legal/index.ts"
66
+ },
67
+ "./errors": {
68
+ "types": "./src/errors/index.ts",
69
+ "import": "./src/errors/index.ts",
70
+ "default": "./src/errors/index.ts"
71
+ },
72
+ "./components": {
73
+ "types": "./src/components/index.ts",
74
+ "import": "./src/components/index.ts",
75
+ "default": "./src/components/index.ts"
76
+ },
77
+ "./contact": {
78
+ "types": "./src/contact/index.ts",
79
+ "import": "./src/contact/index.ts",
80
+ "default": "./src/contact/index.ts"
81
+ },
82
+ "./navigation": {
83
+ "types": "./src/navigation/index.ts",
84
+ "import": "./src/navigation/index.ts",
85
+ "default": "./src/navigation/index.ts"
86
+ },
87
+ "./config": {
88
+ "types": "./src/config/index.ts",
89
+ "import": "./src/config/index.ts",
90
+ "default": "./src/config/index.ts"
91
+ }
92
+ },
93
+ "files": [
94
+ "src",
95
+ "README.md",
96
+ "LICENSE"
97
+ ],
98
+ "scripts": {
99
+ "build": "tsup",
100
+ "dev": "tsup --watch",
101
+ "clean": "rm -rf dist",
102
+ "lint": "eslint .",
103
+ "check": "tsc --noEmit"
104
+ },
105
+ "dependencies": {
106
+ "@vercel/og": "^0.8.5"
107
+ },
108
+ "peerDependencies": {
109
+ "next": "^15.4.4",
110
+ "react": "^19.1.0",
111
+ "react-dom": "^19.1.0",
112
+ "@djangocfg/ui": "^1.4.31",
113
+ "@djangocfg/layouts": "^2.0.1",
114
+ "@djangocfg/api": "^1.4.31",
115
+ "lucide-react": "^0.469.0"
116
+ },
117
+ "devDependencies": {
118
+ "@djangocfg/typescript-config": "^1.4.31",
119
+ "@djangocfg/layouts": "^2.0.1",
120
+ "@types/node": "^24.7.2",
121
+ "@types/react": "19.2.2",
122
+ "@types/react-dom": "19.2.1",
123
+ "@types/webpack": "^5.28.5",
124
+ "eslint": "^9.37.0",
125
+ "lucide-react": "^0.469.0",
126
+ "tsup": "^8.0.1",
127
+ "typescript": "^5.9.3"
128
+ },
129
+ "publishConfig": {
130
+ "access": "public"
131
+ }
132
+ }
133
+
@@ -0,0 +1,73 @@
1
+ 'use client';
2
+
3
+ import { useEffect } from 'react';
4
+ import { useRouter } from 'next/navigation';
5
+ import { useAuth } from '@djangocfg/layouts';
6
+ import { Loader2 } from 'lucide-react';
7
+
8
+ export interface HomePageProps {
9
+ /**
10
+ * Path to redirect to when user is authenticated
11
+ * @default '/private'
12
+ */
13
+ authenticatedPath?: string;
14
+ /**
15
+ * Path to redirect to when user is not authenticated
16
+ * @default '/auth'
17
+ */
18
+ unauthenticatedPath?: string;
19
+ /**
20
+ * Custom loading text
21
+ * @default 'Loading...'
22
+ */
23
+ loadingText?: string;
24
+ }
25
+
26
+ /**
27
+ * HomePage - Root page component that handles authentication redirect
28
+ *
29
+ * Redirects authenticated users to authenticatedPath, otherwise to unauthenticatedPath
30
+ *
31
+ * Usage:
32
+ * ```tsx
33
+ * // app/page.tsx
34
+ * import { HomePage } from '@djangocfg/nextjs/components';
35
+ *
36
+ * export default function Page() {
37
+ * return (
38
+ * <HomePage
39
+ * authenticatedPath="/private"
40
+ * unauthenticatedPath="/auth"
41
+ * />
42
+ * );
43
+ * }
44
+ * ```
45
+ */
46
+ export function HomePage({
47
+ authenticatedPath = '/private',
48
+ unauthenticatedPath = '/auth',
49
+ loadingText = 'Loading...',
50
+ }: HomePageProps) {
51
+ const { isAuthenticated } = useAuth();
52
+ const router = useRouter();
53
+
54
+ useEffect(() => {
55
+ if (!isAuthenticated) {
56
+ router.push(unauthenticatedPath);
57
+ } else {
58
+ router.push(authenticatedPath);
59
+ }
60
+ }, [isAuthenticated, router, authenticatedPath, unauthenticatedPath]);
61
+
62
+ return (
63
+ <div className="flex items-center justify-center min-h-screen bg-background">
64
+ <div className="flex flex-col items-center gap-4">
65
+ <Loader2 className="animate-spin text-primary" style={{ width: '48px', height: '48px' }} />
66
+ <span className="text-lg font-medium text-muted-foreground">
67
+ {loadingText}
68
+ </span>
69
+ </div>
70
+ </div>
71
+ );
72
+ }
73
+
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Components exports
3
+ */
4
+
5
+ export { HomePage } from './HomePage';
6
+ export type { HomePageProps } from './HomePage';
7
+