@digitalygo/create-diggocms-app 0.1.1 → 0.1.3
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/README.md +96 -23
- package/bin/cli.js +52 -94
- package/package.json +1 -1
- package/templates/full/.env.local.example +3 -2
- package/templates/full/README.md +64 -22
- package/templates/full/components/PageLayout.tsx +40 -0
- package/templates/full/lib/data-fetching.ts +55 -10
- package/templates/full/lib/diggo-config.ts +4 -2
- package/templates/full/package.json +3 -1
- package/templates/full/pages/[...slug].tsx +93 -0
- package/templates/full/pages/_app.tsx +11 -0
- package/templates/full/pages/index.tsx +14 -0
- package/templates/full/postcss.config.js +6 -0
- package/templates/full/styles/globals.css +113 -0
- package/templates/full/tailwind.config.ts +14 -0
- package/templates/full/tsconfig.json +2 -1
- package/templates/minimal/.env.local.example +3 -2
- package/templates/minimal/README.md +44 -10
- package/templates/minimal/lib/data-fetching.ts +46 -12
- package/templates/minimal/lib/diggo-config.ts +2 -5
- package/templates/minimal/package.json +3 -1
- package/templates/minimal/pages/[...slug].tsx +73 -0
- package/templates/minimal/pages/_app.tsx +11 -0
- package/templates/minimal/pages/index.tsx +14 -0
- package/templates/minimal/postcss.config.js +6 -0
- package/templates/minimal/{app → styles}/globals.css +4 -0
- package/templates/minimal/tailwind.config.ts +14 -0
- package/templates/minimal/tsconfig.json +2 -1
- package/templates/with-mock/.env.local.example +3 -2
- package/templates/with-mock/README.md +61 -33
- package/templates/with-mock/components/PageLayout.tsx +40 -0
- package/templates/with-mock/lib/data-fetching.ts +56 -11
- package/templates/with-mock/lib/diggo-config.ts +4 -2
- package/templates/with-mock/package.json +7 -3
- package/templates/with-mock/pages/[...slug].tsx +117 -0
- package/templates/with-mock/pages/_app.tsx +11 -0
- package/templates/with-mock/pages/index.tsx +14 -0
- package/templates/with-mock/postcss.config.js +6 -0
- package/templates/with-mock/scripts/mock-server.ts +0 -6
- package/templates/with-mock/styles/globals.css +118 -0
- package/templates/with-mock/tailwind.config.ts +14 -0
- package/templates/with-mock/tsconfig.json +2 -1
- package/templates/full/app/[...slug]/page.tsx +0 -115
- package/templates/full/app/globals.css +0 -238
- package/templates/full/app/layout.tsx +0 -25
- package/templates/full/app/page.tsx +0 -6
- package/templates/full/tsconfig.tsbuildinfo +0 -1
- package/templates/minimal/app/[...slug]/page.tsx +0 -56
- package/templates/minimal/app/layout.tsx +0 -22
- package/templates/minimal/app/page.tsx +0 -6
- package/templates/with-mock/app/[...slug]/page.tsx +0 -115
- package/templates/with-mock/app/globals.css +0 -238
- package/templates/with-mock/app/layout.tsx +0 -25
- package/templates/with-mock/app/page.tsx +0 -6
- package/templates/with-mock/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { MenuPayload } from '@digitalygo/diggocms-sdk-core';
|
|
2
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
3
|
+
import { renderMenu } from '@digitalygo/diggocms-sdk-core/server';
|
|
4
|
+
import { navigationRegistry } from '@/lib/diggo-config';
|
|
5
|
+
|
|
6
|
+
interface PageLayoutProps {
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
menu: MenuPayload | null;
|
|
9
|
+
menuError: string | null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function PageLayout({ children, menu, menuError }: PageLayoutProps): ReactElement {
|
|
13
|
+
return (
|
|
14
|
+
<div className="page-shell">
|
|
15
|
+
<header className="site-header">
|
|
16
|
+
<div className="site-header__inner">
|
|
17
|
+
<a href="/home" className="site-brand">
|
|
18
|
+
DiggoCMS Demo
|
|
19
|
+
</a>
|
|
20
|
+
<div className="site-nav">
|
|
21
|
+
{menu ? (
|
|
22
|
+
renderMenu(menu, navigationRegistry)
|
|
23
|
+
) : (
|
|
24
|
+
<div className="menu-fallback" role="status">
|
|
25
|
+
Menu unavailable
|
|
26
|
+
</div>
|
|
27
|
+
)}
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
{menuError && (
|
|
31
|
+
<div className="menu-alert" role="status">
|
|
32
|
+
{menuError}
|
|
33
|
+
</div>
|
|
34
|
+
)}
|
|
35
|
+
</header>
|
|
36
|
+
|
|
37
|
+
<main className="page-content">{children}</main>
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -12,15 +12,39 @@ interface PageIndexItem {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
const DEFAULT_MOCK_API_URL = 'http://localhost:3001';
|
|
15
|
+
const FETCH_TIMEOUT_MS = 5000;
|
|
15
16
|
|
|
16
17
|
function getMockApiBaseUrl(): string {
|
|
17
18
|
return process.env.MOCK_API_URL ?? DEFAULT_MOCK_API_URL;
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
async function fetchWithTimeout(
|
|
22
|
+
url: string,
|
|
23
|
+
timeoutMs: number
|
|
24
|
+
): Promise<Response> {
|
|
25
|
+
const controller = new AbortController();
|
|
26
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
30
|
+
clearTimeout(timeoutId);
|
|
31
|
+
return response;
|
|
32
|
+
} catch (error) {
|
|
33
|
+
clearTimeout(timeoutId);
|
|
34
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
35
|
+
throw new Error(`Request timeout after ${timeoutMs}ms`);
|
|
36
|
+
}
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
20
41
|
async function fetchFromMockApi<T>(endpoint: string): Promise<T | null> {
|
|
21
42
|
try {
|
|
22
43
|
const baseUrl = getMockApiBaseUrl();
|
|
23
|
-
const response = await
|
|
44
|
+
const response = await fetchWithTimeout(
|
|
45
|
+
`${baseUrl}${endpoint}`,
|
|
46
|
+
FETCH_TIMEOUT_MS
|
|
47
|
+
);
|
|
24
48
|
|
|
25
49
|
if (!response.ok) {
|
|
26
50
|
return null;
|
|
@@ -99,7 +123,10 @@ export async function fetchPageData(slug: string): Promise<FetchPageResult> {
|
|
|
99
123
|
}
|
|
100
124
|
|
|
101
125
|
try {
|
|
102
|
-
const response = await
|
|
126
|
+
const response = await fetchWithTimeout(
|
|
127
|
+
`${sdkConfig.baseUrl}/pages/${slug}`,
|
|
128
|
+
FETCH_TIMEOUT_MS
|
|
129
|
+
);
|
|
103
130
|
|
|
104
131
|
if (!response.ok) {
|
|
105
132
|
return {
|
|
@@ -111,10 +138,14 @@ export async function fetchPageData(slug: string): Promise<FetchPageResult> {
|
|
|
111
138
|
|
|
112
139
|
const page = (await response.json()) as PagePayload;
|
|
113
140
|
return { page, error: null, usingMock: false };
|
|
114
|
-
} catch {
|
|
141
|
+
} catch (error) {
|
|
142
|
+
const errorMessage =
|
|
143
|
+
error instanceof Error ? error.message : 'Unknown error';
|
|
115
144
|
return {
|
|
116
145
|
page: null,
|
|
117
|
-
error: '
|
|
146
|
+
error: errorMessage.includes('timeout')
|
|
147
|
+
? 'Request to CMS timed out. Please check your BASE_URL and network connection.'
|
|
148
|
+
: 'Error connecting to CMS',
|
|
118
149
|
usingMock: false,
|
|
119
150
|
};
|
|
120
151
|
}
|
|
@@ -143,7 +174,10 @@ export async function fetchCollectionData(
|
|
|
143
174
|
}
|
|
144
175
|
|
|
145
176
|
try {
|
|
146
|
-
const response = await
|
|
177
|
+
const response = await fetchWithTimeout(
|
|
178
|
+
`${sdkConfig.baseUrl}/collections/${type}`,
|
|
179
|
+
FETCH_TIMEOUT_MS
|
|
180
|
+
);
|
|
147
181
|
|
|
148
182
|
if (!response.ok) {
|
|
149
183
|
return {
|
|
@@ -155,10 +189,14 @@ export async function fetchCollectionData(
|
|
|
155
189
|
|
|
156
190
|
const collection = (await response.json()) as CollectionPayload;
|
|
157
191
|
return { collection, error: null, usingMock: false };
|
|
158
|
-
} catch {
|
|
192
|
+
} catch (error) {
|
|
193
|
+
const errorMessage =
|
|
194
|
+
error instanceof Error ? error.message : 'Unknown error';
|
|
159
195
|
return {
|
|
160
196
|
collection: null,
|
|
161
|
-
error: '
|
|
197
|
+
error: errorMessage.includes('timeout')
|
|
198
|
+
? 'Request to CMS timed out. Please check your BASE_URL and network connection.'
|
|
199
|
+
: 'Error connecting to CMS',
|
|
162
200
|
usingMock: false,
|
|
163
201
|
};
|
|
164
202
|
}
|
|
@@ -183,7 +221,10 @@ export async function fetchMenuData(key: string): Promise<FetchMenuResult> {
|
|
|
183
221
|
}
|
|
184
222
|
|
|
185
223
|
try {
|
|
186
|
-
const response = await
|
|
224
|
+
const response = await fetchWithTimeout(
|
|
225
|
+
`${sdkConfig.baseUrl}/menus/${key}`,
|
|
226
|
+
FETCH_TIMEOUT_MS
|
|
227
|
+
);
|
|
187
228
|
|
|
188
229
|
if (!response.ok) {
|
|
189
230
|
return {
|
|
@@ -195,10 +236,14 @@ export async function fetchMenuData(key: string): Promise<FetchMenuResult> {
|
|
|
195
236
|
|
|
196
237
|
const menu = (await response.json()) as MenuPayload;
|
|
197
238
|
return { menu, error: null, usingMock: false };
|
|
198
|
-
} catch {
|
|
239
|
+
} catch (error) {
|
|
240
|
+
const errorMessage =
|
|
241
|
+
error instanceof Error ? error.message : 'Unknown error';
|
|
199
242
|
return {
|
|
200
243
|
menu: null,
|
|
201
|
-
error: '
|
|
244
|
+
error: errorMessage.includes('timeout')
|
|
245
|
+
? 'Request to CMS timed out. Please check your BASE_URL and network connection.'
|
|
246
|
+
: 'Error connecting to CMS',
|
|
202
247
|
usingMock: false,
|
|
203
248
|
};
|
|
204
249
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ComponentRegistry, NavigationRegistry, DiggoConfig } from '@digitalygo/diggocms-sdk-core';
|
|
2
2
|
import {
|
|
3
|
+
ExtendedTitle,
|
|
3
4
|
ExtendedImage,
|
|
4
5
|
ExtendedText,
|
|
5
6
|
ExtendedVideo,
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
} from '@/components/server-components';
|
|
11
12
|
|
|
12
13
|
export const componentsRegistry = {
|
|
14
|
+
title: ExtendedTitle,
|
|
13
15
|
image: ExtendedImage,
|
|
14
16
|
text: ExtendedText,
|
|
15
17
|
video: ExtendedVideo,
|
|
@@ -31,7 +33,7 @@ function getBaseUrl(): string {
|
|
|
31
33
|
return mockApiUrl ?? 'http://localhost:3001';
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
return baseUrl ?? '
|
|
36
|
+
return baseUrl ?? '';
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
export const sdkConfig: DiggoConfig = {
|
|
@@ -45,5 +47,5 @@ export function isMockMode(): boolean {
|
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
export function hasBaseUrl(): boolean {
|
|
48
|
-
return !!baseUrl;
|
|
50
|
+
return !!baseUrl && baseUrl.length > 0;
|
|
49
51
|
}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
"name": "my-diggocms-app",
|
|
3
3
|
"version": "0.1.0",
|
|
4
4
|
"private": true,
|
|
5
|
-
"type": "module",
|
|
6
5
|
"scripts": {
|
|
7
6
|
"dev": "next dev",
|
|
8
7
|
"build": "next build",
|
|
@@ -20,6 +19,9 @@
|
|
|
20
19
|
"@types/node": "^20.0.0",
|
|
21
20
|
"@types/react": "^18.3.0",
|
|
22
21
|
"@types/react-dom": "^18.3.0",
|
|
22
|
+
"autoprefixer": "^10.4.19",
|
|
23
|
+
"postcss": "^8.4.38",
|
|
24
|
+
"tailwindcss": "^3.4.4",
|
|
23
25
|
"typescript": "^5.5.0"
|
|
24
26
|
}
|
|
25
27
|
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { GetStaticPaths, GetStaticProps } from 'next';
|
|
2
|
+
import type { MenuPayload, PagePayload } from '@digitalygo/diggocms-sdk-core';
|
|
3
|
+
import { useRouter } from 'next/router';
|
|
4
|
+
import Head from 'next/head';
|
|
5
|
+
import { renderPage } from '@digitalygo/diggocms-sdk-core/server';
|
|
6
|
+
import { componentsRegistry } from '@/lib/diggo-config';
|
|
7
|
+
import { PageLayout } from '@/components/PageLayout';
|
|
8
|
+
import {
|
|
9
|
+
fetchMenuData,
|
|
10
|
+
fetchPageData,
|
|
11
|
+
FetchMenuResult,
|
|
12
|
+
FetchPageResult,
|
|
13
|
+
} from '@/lib/data-fetching';
|
|
14
|
+
|
|
15
|
+
interface CatchAllPageProps {
|
|
16
|
+
page: PagePayload | null;
|
|
17
|
+
error: string | null;
|
|
18
|
+
menu: MenuPayload | null;
|
|
19
|
+
menuError: string | null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default function CatchAllPage({ page, error, menu, menuError }: CatchAllPageProps) {
|
|
23
|
+
const router = useRouter();
|
|
24
|
+
|
|
25
|
+
if (router.isFallback) {
|
|
26
|
+
return (
|
|
27
|
+
<div className="min-h-screen flex items-center justify-center">
|
|
28
|
+
<div className="text-lg text-gray-600">Loading...</div>
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!page) {
|
|
34
|
+
return (
|
|
35
|
+
<PageLayout menu={menu} menuError={menuError}>
|
|
36
|
+
<h1 className="text-3xl font-bold text-gray-900 mb-4">Page Not Found</h1>
|
|
37
|
+
{error && (
|
|
38
|
+
<div className="bg-red-50 border border-red-200 text-red-800 p-4 rounded">
|
|
39
|
+
{error}
|
|
40
|
+
</div>
|
|
41
|
+
)}
|
|
42
|
+
</PageLayout>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<>
|
|
48
|
+
<Head>
|
|
49
|
+
<title>{page.title || 'My DiggoCMS App'}</title>
|
|
50
|
+
<meta name="description" content={page.title || 'DiggoCMS powered page'} />
|
|
51
|
+
</Head>
|
|
52
|
+
<PageLayout menu={menu} menuError={menuError}>
|
|
53
|
+
{error && (
|
|
54
|
+
<div className="bg-yellow-50 border border-yellow-200 text-yellow-800 p-4 mb-6 rounded">
|
|
55
|
+
<strong className="font-semibold">Warning:</strong> {error}
|
|
56
|
+
</div>
|
|
57
|
+
)}
|
|
58
|
+
{renderPage(page, componentsRegistry)}
|
|
59
|
+
</PageLayout>
|
|
60
|
+
</>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const getStaticPaths: GetStaticPaths = async () => {
|
|
65
|
+
return {
|
|
66
|
+
paths: [],
|
|
67
|
+
fallback: 'blocking',
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const getStaticProps: GetStaticProps<CatchAllPageProps> = async ({ params }) => {
|
|
72
|
+
const slugArray = params?.slug as string[] | undefined;
|
|
73
|
+
const slug = Array.isArray(slugArray) ? slugArray.join('/') : 'home';
|
|
74
|
+
|
|
75
|
+
const [{ page, error }, { menu, error: menuError }]: [FetchPageResult, FetchMenuResult] =
|
|
76
|
+
await Promise.all([fetchPageData(slug), fetchMenuData('main')]);
|
|
77
|
+
|
|
78
|
+
if (!page) {
|
|
79
|
+
return {
|
|
80
|
+
notFound: true,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
props: {
|
|
86
|
+
page,
|
|
87
|
+
error,
|
|
88
|
+
menu,
|
|
89
|
+
menuError,
|
|
90
|
+
},
|
|
91
|
+
revalidate: 60,
|
|
92
|
+
};
|
|
93
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AppProps } from 'next/app';
|
|
2
|
+
import { DiggoProvider } from '@/components/DiggoProvider';
|
|
3
|
+
import '@/styles/globals.css';
|
|
4
|
+
|
|
5
|
+
export default function App({ Component, pageProps }: AppProps) {
|
|
6
|
+
return (
|
|
7
|
+
<DiggoProvider>
|
|
8
|
+
<Component {...pageProps} />
|
|
9
|
+
</DiggoProvider>
|
|
10
|
+
);
|
|
11
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { GetStaticProps } from 'next';
|
|
2
|
+
|
|
3
|
+
export default function HomePage() {
|
|
4
|
+
return null;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const getStaticProps: GetStaticProps = async () => {
|
|
8
|
+
return {
|
|
9
|
+
redirect: {
|
|
10
|
+
destination: '/home',
|
|
11
|
+
permanent: false,
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
* {
|
|
6
|
+
margin: 0;
|
|
7
|
+
padding: 0;
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
body {
|
|
12
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
13
|
+
line-height: 1.6;
|
|
14
|
+
color: #333;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.page-shell {
|
|
18
|
+
@apply min-h-screen bg-gray-50;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.site-header {
|
|
22
|
+
@apply bg-white border-b border-gray-200 shadow-sm;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.site-header__inner {
|
|
26
|
+
@apply max-w-5xl mx-auto px-6 py-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.site-brand {
|
|
30
|
+
@apply text-lg font-semibold text-gray-900 hover:text-blue-600 transition-colors;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.site-nav {
|
|
34
|
+
@apply w-full md:w-auto;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.page-content {
|
|
38
|
+
@apply max-w-5xl mx-auto px-6 py-10;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* DiggoCMS Component Styles */
|
|
42
|
+
.diggo-title {
|
|
43
|
+
@apply text-3xl font-bold mb-4 text-gray-900;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.diggo-text {
|
|
47
|
+
@apply mb-4 text-gray-700 leading-relaxed;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.diggo-image {
|
|
51
|
+
@apply max-w-full h-auto rounded-lg shadow-md mb-6;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.diggo-video-block {
|
|
55
|
+
@apply mb-6;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.diggo-video {
|
|
59
|
+
@apply w-full rounded-lg shadow-md;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.diggo-media-caption {
|
|
63
|
+
@apply text-sm text-gray-600 mt-2 text-center;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.diggo-gallery {
|
|
67
|
+
@apply grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mb-6;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.diggo-gallery-image {
|
|
71
|
+
@apply w-full h-48 object-cover rounded-lg shadow-md;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.diggo-gallery-video {
|
|
75
|
+
@apply w-full h-48 rounded-lg shadow-md;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.diggo-card {
|
|
79
|
+
@apply border border-gray-200 rounded-lg p-6 shadow-sm mb-6 bg-white;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.diggo-card-link {
|
|
83
|
+
@apply inline-block mt-4 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* Navigation Styles */
|
|
87
|
+
.menu {
|
|
88
|
+
@apply w-full;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.menu-list {
|
|
92
|
+
@apply flex flex-wrap gap-4 items-center justify-start md:justify-end list-none;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.menu-item {
|
|
96
|
+
@apply relative;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.menu-link {
|
|
100
|
+
@apply text-gray-700 hover:text-blue-600 font-medium transition-colors;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.menu-link[aria-current="page"] {
|
|
104
|
+
@apply text-blue-600 font-semibold;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.menu-fallback {
|
|
108
|
+
@apply text-sm text-gray-500 bg-gray-100 border border-gray-200 rounded px-3 py-2 inline-flex items-center;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.menu-alert {
|
|
112
|
+
@apply bg-yellow-50 text-yellow-800 border-t border-yellow-200 px-6 py-3 text-sm;
|
|
113
|
+
}
|
|
@@ -14,10 +14,11 @@
|
|
|
14
14
|
"jsx": "preserve",
|
|
15
15
|
"incremental": true,
|
|
16
16
|
"plugins": [{ "name": "next" }],
|
|
17
|
+
"baseUrl": ".",
|
|
17
18
|
"paths": {
|
|
18
19
|
"@/*": ["./*"]
|
|
19
20
|
}
|
|
20
21
|
},
|
|
21
|
-
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"
|
|
22
|
+
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
|
22
23
|
"exclude": ["node_modules"]
|
|
23
24
|
}
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
# Copy this file to .env.local and update the values
|
|
3
3
|
|
|
4
4
|
# CMS API Configuration
|
|
5
|
-
# Set your DiggoCMS API base URL
|
|
6
|
-
BASE_URL=https://
|
|
5
|
+
# Set your DiggoCMS API base URL (required when not using mock mode)
|
|
6
|
+
# Example: BASE_URL=https://cms.example.com
|
|
7
|
+
BASE_URL=
|
|
7
8
|
|
|
8
9
|
# Mock Mode
|
|
9
10
|
# Set to 1 to use local mock data instead of a real API
|
|
@@ -1,26 +1,37 @@
|
|
|
1
1
|
# My DiggoCMS App
|
|
2
2
|
|
|
3
|
-
A minimal DiggoCMS application built with Next.js and the DiggoCMS SDK.
|
|
3
|
+
A minimal DiggoCMS application built with Next.js Pages Router and the DiggoCMS SDK.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Next.js 16 with Pages Router
|
|
8
|
+
- Static Site Generation (SSG) with `getStaticProps`/`getStaticPaths`
|
|
9
|
+
- Tailwind CSS for styling
|
|
10
|
+
- Hot reload via `next dev`
|
|
11
|
+
- DiggoCMS SDK integration
|
|
4
12
|
|
|
5
13
|
## Getting Started
|
|
6
14
|
|
|
7
15
|
1. Copy `.env.local.example` to `.env.local` and configure your environment:
|
|
16
|
+
|
|
8
17
|
```bash
|
|
9
18
|
cp .env.local.example .env.local
|
|
10
19
|
```
|
|
11
20
|
|
|
12
21
|
2. Install dependencies:
|
|
22
|
+
|
|
13
23
|
```bash
|
|
14
|
-
npm install
|
|
15
|
-
# or
|
|
16
24
|
bun install
|
|
25
|
+
# or
|
|
26
|
+
npm install
|
|
17
27
|
```
|
|
18
28
|
|
|
19
29
|
3. Run the development server:
|
|
30
|
+
|
|
20
31
|
```bash
|
|
21
|
-
npm run dev
|
|
22
|
-
# or
|
|
23
32
|
bun run dev
|
|
33
|
+
# or
|
|
34
|
+
npm run dev
|
|
24
35
|
```
|
|
25
36
|
|
|
26
37
|
4. Open [http://localhost:3000](http://localhost:3000) in your browser.
|
|
@@ -29,29 +40,50 @@ A minimal DiggoCMS application built with Next.js and the DiggoCMS SDK.
|
|
|
29
40
|
|
|
30
41
|
### Using a Real CMS API
|
|
31
42
|
|
|
32
|
-
Set your CMS API base URL
|
|
43
|
+
Set your CMS API base URL in `.env.local`:
|
|
44
|
+
|
|
33
45
|
```env
|
|
34
46
|
BASE_URL=https://your-cms-api.com
|
|
35
47
|
MOCK=0
|
|
36
48
|
```
|
|
37
49
|
|
|
50
|
+
Note: The template defaults to an empty `BASE_URL`. You must configure it before running in non-mock mode. Requests timeout after 5 seconds to prevent hanging.
|
|
51
|
+
|
|
38
52
|
### Using Mock Mode
|
|
39
53
|
|
|
40
|
-
Enable mock mode to use local
|
|
54
|
+
Enable mock mode to use a local mock API:
|
|
55
|
+
|
|
41
56
|
```env
|
|
42
57
|
MOCK=1
|
|
43
58
|
MOCK_API_URL=http://localhost:3001
|
|
44
59
|
```
|
|
45
60
|
|
|
61
|
+
When `MOCK=1`, the `BASE_URL` setting is ignored.
|
|
62
|
+
|
|
46
63
|
## Project Structure
|
|
47
64
|
|
|
48
|
-
```
|
|
49
|
-
app/ # Next.js app router
|
|
65
|
+
```text
|
|
50
66
|
components/ # React components (add your extended components here)
|
|
51
67
|
lib/ # Utility functions and SDK configuration
|
|
68
|
+
pages/ # Next.js pages (Pages Router)
|
|
69
|
+
├── _app.tsx # App wrapper with DiggoProvider
|
|
70
|
+
├── index.tsx # Home redirect
|
|
71
|
+
└── [...slug].tsx # Dynamic catch-all route
|
|
52
72
|
public/ # Static assets
|
|
73
|
+
styles/ # Global styles
|
|
74
|
+
├── globals.css # Tailwind imports + global styles
|
|
53
75
|
```
|
|
54
76
|
|
|
77
|
+
## Scripts
|
|
78
|
+
|
|
79
|
+
| Script | Description |
|
|
80
|
+
|--------|-------------|
|
|
81
|
+
| `bun run dev` | Start development server with hot reload |
|
|
82
|
+
| `bun run build` | Build for static export |
|
|
83
|
+
| `bun run start` | Start production server |
|
|
84
|
+
| `bun run lint` | Run ESLint |
|
|
85
|
+
| `bun run typecheck` | Run TypeScript check |
|
|
86
|
+
|
|
55
87
|
## Next Steps
|
|
56
88
|
|
|
57
89
|
This is a minimal template. To extend it:
|
|
@@ -60,8 +92,10 @@ This is a minimal template. To extend it:
|
|
|
60
92
|
2. Register them in `lib/diggo-config.ts`
|
|
61
93
|
3. Add navigation components if needed
|
|
62
94
|
4. Set up your CMS API or mock server
|
|
95
|
+
5. Configure `getStaticPaths` in `[...slug].tsx` to pre-generate pages at build time
|
|
63
96
|
|
|
64
97
|
## Documentation
|
|
65
98
|
|
|
66
99
|
- [DiggoCMS SDK Documentation](https://github.com/digitalygo/diggocms-sdk)
|
|
67
|
-
- [Next.js Documentation](https://nextjs.org/docs)
|
|
100
|
+
- [Next.js Pages Router Documentation](https://nextjs.org/docs/pages)
|
|
101
|
+
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
|