@fecommunity/reactpress-template-hello-world 1.0.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/LICENSE +21 -0
- package/README.md +297 -0
- package/bin/create-hello-world.js +139 -0
- package/components/Footer.tsx +35 -0
- package/components/Header.tsx +113 -0
- package/next-env.d.ts +5 -0
- package/next.config.js +10 -0
- package/package.json +27 -0
- package/pages/404.tsx +152 -0
- package/pages/about.tsx +295 -0
- package/pages/index.tsx +356 -0
- package/pages/toolkit-demo.tsx +490 -0
- package/tsconfig.json +30 -0
package/pages/404.tsx
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import Head from 'next/head';
|
|
2
|
+
import Link from 'next/link';
|
|
3
|
+
import Header from '../components/Header';
|
|
4
|
+
import Footer from '../components/Footer';
|
|
5
|
+
|
|
6
|
+
export default function Custom404() {
|
|
7
|
+
return (
|
|
8
|
+
<div className="container">
|
|
9
|
+
<Head>
|
|
10
|
+
<title>404 - Page Not Found</title>
|
|
11
|
+
<meta name="description" content="Page not found" />
|
|
12
|
+
<link rel="icon" href="/favicon.ico" />
|
|
13
|
+
</Head>
|
|
14
|
+
|
|
15
|
+
<Header />
|
|
16
|
+
|
|
17
|
+
<main className="main">
|
|
18
|
+
<div className="content-wrapper">
|
|
19
|
+
<div className="error-page">
|
|
20
|
+
<h1 className="error-code">404</h1>
|
|
21
|
+
<h2 className="error-title">Page Not Found</h2>
|
|
22
|
+
<p className="error-description">
|
|
23
|
+
Sorry, the page you are looking for could not be found.
|
|
24
|
+
</p>
|
|
25
|
+
<div className="cta-section">
|
|
26
|
+
<Link href="/">
|
|
27
|
+
<a className="back-home-link">← Back to Home</a>
|
|
28
|
+
</Link>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</main>
|
|
33
|
+
|
|
34
|
+
<Footer />
|
|
35
|
+
|
|
36
|
+
<style jsx>{`
|
|
37
|
+
.container {
|
|
38
|
+
min-height: 100vh;
|
|
39
|
+
display: flex;
|
|
40
|
+
flex-direction: column;
|
|
41
|
+
background-color: #f8f9fa;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.main {
|
|
45
|
+
flex: 1;
|
|
46
|
+
padding: 3rem 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.content-wrapper {
|
|
50
|
+
max-width: 1200px;
|
|
51
|
+
margin: 0 auto;
|
|
52
|
+
padding: 0 2rem;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.error-page {
|
|
56
|
+
text-align: center;
|
|
57
|
+
padding: 4rem 0;
|
|
58
|
+
max-width: 600px;
|
|
59
|
+
margin: 0 auto;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.error-code {
|
|
63
|
+
font-size: 6rem;
|
|
64
|
+
font-weight: 800;
|
|
65
|
+
color: #3b82f6;
|
|
66
|
+
margin: 0 0 1rem 0;
|
|
67
|
+
line-height: 1;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.error-title {
|
|
71
|
+
font-size: 2rem;
|
|
72
|
+
font-weight: 700;
|
|
73
|
+
color: #111827;
|
|
74
|
+
margin: 0 0 1.5rem 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.error-description {
|
|
78
|
+
color: #6b7280;
|
|
79
|
+
font-size: 1.25rem;
|
|
80
|
+
margin: 0 0 2.5rem 0;
|
|
81
|
+
line-height: 1.7;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.back-home-link {
|
|
85
|
+
display: inline-block;
|
|
86
|
+
color: #3b82f6;
|
|
87
|
+
text-decoration: none;
|
|
88
|
+
font-weight: 600;
|
|
89
|
+
padding: 0.875rem 1.75rem;
|
|
90
|
+
border: 2px solid #3b82f6;
|
|
91
|
+
border-radius: 12px;
|
|
92
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
93
|
+
position: relative;
|
|
94
|
+
overflow: hidden;
|
|
95
|
+
background: transparent;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.back-home-link::before {
|
|
99
|
+
content: '';
|
|
100
|
+
position: absolute;
|
|
101
|
+
top: 0;
|
|
102
|
+
left: 0;
|
|
103
|
+
width: 100%;
|
|
104
|
+
height: 100%;
|
|
105
|
+
background: linear-gradient(135deg, #3b82f6, #8b5cf6);
|
|
106
|
+
z-index: -1;
|
|
107
|
+
opacity: 0;
|
|
108
|
+
transition: opacity 0.3s ease;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.back-home-link:hover {
|
|
112
|
+
color: #fff;
|
|
113
|
+
transform: translateY(-3px);
|
|
114
|
+
box-shadow: 0 6px 15px rgba(59, 130, 246, 0.3);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.back-home-link:hover::before {
|
|
118
|
+
opacity: 1;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* Responsive Design */
|
|
122
|
+
@media (max-width: 768px) {
|
|
123
|
+
.error-code {
|
|
124
|
+
font-size: 4rem;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.error-title {
|
|
128
|
+
font-size: 1.75rem;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.error-description {
|
|
132
|
+
font-size: 1.1rem;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
`}</style>
|
|
136
|
+
|
|
137
|
+
<style jsx global>{`
|
|
138
|
+
html,
|
|
139
|
+
body {
|
|
140
|
+
padding: 0;
|
|
141
|
+
margin: 0;
|
|
142
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
|
143
|
+
background-color: #f8f9fa;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
* {
|
|
147
|
+
box-sizing: border-box;
|
|
148
|
+
}
|
|
149
|
+
`}</style>
|
|
150
|
+
</div>
|
|
151
|
+
);
|
|
152
|
+
}
|
package/pages/about.tsx
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { GetStaticProps } from 'next';
|
|
2
|
+
import Head from 'next/head';
|
|
3
|
+
import Link from 'next/link';
|
|
4
|
+
import { createApiInstance } from '@fecommunity/reactpress-toolkit';
|
|
5
|
+
import { types, utils } from '@fecommunity/reactpress-toolkit';
|
|
6
|
+
import Header from '../components/Header';
|
|
7
|
+
import Footer from '../components/Footer';
|
|
8
|
+
|
|
9
|
+
// Create a custom API instance with the desired baseURL
|
|
10
|
+
const customApi = createApiInstance({
|
|
11
|
+
baseURL: 'https://api.gaoredu.com/'
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
// Type definitions from the toolkit
|
|
15
|
+
type ISetting = types.ISetting;
|
|
16
|
+
|
|
17
|
+
interface AboutProps {
|
|
18
|
+
siteInfo: {
|
|
19
|
+
siteName: string;
|
|
20
|
+
siteDescription: string;
|
|
21
|
+
} | null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default function About({ siteInfo }: AboutProps) {
|
|
25
|
+
return (
|
|
26
|
+
<div className="container">
|
|
27
|
+
<Head>
|
|
28
|
+
<title>About - Hello World Template</title>
|
|
29
|
+
<meta name="description" content="About the hello-world template for ReactPress" />
|
|
30
|
+
<link rel="icon" href="/favicon.ico" />
|
|
31
|
+
</Head>
|
|
32
|
+
|
|
33
|
+
<Header currentPage="about" />
|
|
34
|
+
|
|
35
|
+
<main className="main">
|
|
36
|
+
<div className="content-wrapper">
|
|
37
|
+
<div className="page-header">
|
|
38
|
+
<h1 className="page-title">About This Template</h1>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div className="content">
|
|
42
|
+
<p className="description">
|
|
43
|
+
This is a minimal hello-world template for ReactPress, built with Next.js Pages Router.
|
|
44
|
+
It provides a simple starting point for building your own blog or website.
|
|
45
|
+
</p>
|
|
46
|
+
|
|
47
|
+
<div className="features">
|
|
48
|
+
<h2 className="section-title">Features</h2>
|
|
49
|
+
<ul className="features-list">
|
|
50
|
+
<li>Minimal and clean design</li>
|
|
51
|
+
<li>Responsive layout</li>
|
|
52
|
+
<li>Built with TypeScript</li>
|
|
53
|
+
<li>Next.js Pages Router</li>
|
|
54
|
+
<li>Integrated with ReactPress Toolkit</li>
|
|
55
|
+
<li>Type-safe with toolkit types</li>
|
|
56
|
+
<li>Utility functions included</li>
|
|
57
|
+
</ul>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
{siteInfo && (
|
|
61
|
+
<div className="site-info">
|
|
62
|
+
<h2 className="section-title">Site Information</h2>
|
|
63
|
+
<div className="info-grid">
|
|
64
|
+
<div className="info-item">
|
|
65
|
+
<span className="info-label">Site Name:</span>
|
|
66
|
+
<span className="info-value">{siteInfo.siteName}</span>
|
|
67
|
+
</div>
|
|
68
|
+
<div className="info-item">
|
|
69
|
+
<span className="info-label">Description:</span>
|
|
70
|
+
<span className="info-value">{siteInfo.siteDescription}</span>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
)}
|
|
75
|
+
|
|
76
|
+
<div className="cta-section">
|
|
77
|
+
<Link href="/">
|
|
78
|
+
<a className="back-link">← Back to Home</a>
|
|
79
|
+
</Link>
|
|
80
|
+
<Link href="/toolkit-demo">
|
|
81
|
+
<a className="demo-link">Toolkit Demo →</a>
|
|
82
|
+
</Link>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</main>
|
|
87
|
+
|
|
88
|
+
<Footer />
|
|
89
|
+
|
|
90
|
+
<style jsx>{`
|
|
91
|
+
.container {
|
|
92
|
+
min-height: 100vh;
|
|
93
|
+
display: flex;
|
|
94
|
+
flex-direction: column;
|
|
95
|
+
background-color: #f8f9fa;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.main {
|
|
99
|
+
flex: 1;
|
|
100
|
+
padding: 3rem 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.content-wrapper {
|
|
104
|
+
max-width: 1200px;
|
|
105
|
+
margin: 0 auto;
|
|
106
|
+
padding: 0 2rem;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.page-header {
|
|
110
|
+
text-align: center;
|
|
111
|
+
margin-bottom: 3rem;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.page-title {
|
|
115
|
+
font-size: 2.5rem;
|
|
116
|
+
font-weight: 800;
|
|
117
|
+
color: #111827;
|
|
118
|
+
margin: 0 0 1rem 0;
|
|
119
|
+
letter-spacing: -0.025em;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.content {
|
|
123
|
+
max-width: 800px;
|
|
124
|
+
margin: 0 auto;
|
|
125
|
+
background: #fff;
|
|
126
|
+
border-radius: 16px;
|
|
127
|
+
padding: 2.5rem;
|
|
128
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.description {
|
|
132
|
+
color: #6b7280;
|
|
133
|
+
font-size: 1.15rem;
|
|
134
|
+
line-height: 1.7;
|
|
135
|
+
margin-bottom: 2rem;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.features {
|
|
139
|
+
margin: 2.5rem 0;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.section-title {
|
|
143
|
+
font-size: 1.75rem;
|
|
144
|
+
font-weight: 700;
|
|
145
|
+
color: #111827;
|
|
146
|
+
margin: 0 0 1.5rem 0;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.features-list {
|
|
150
|
+
list-style-type: none;
|
|
151
|
+
padding: 0;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.features-list li {
|
|
155
|
+
padding: 0.75rem 0;
|
|
156
|
+
border-bottom: 1px solid #f3f4f6;
|
|
157
|
+
color: #4b5563;
|
|
158
|
+
font-size: 1.1rem;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.features-list li:before {
|
|
162
|
+
content: "✓";
|
|
163
|
+
color: #3b82f6;
|
|
164
|
+
font-weight: bold;
|
|
165
|
+
display: inline-block;
|
|
166
|
+
width: 1.5rem;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.site-info {
|
|
170
|
+
margin: 2.5rem 0;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.info-grid {
|
|
174
|
+
display: grid;
|
|
175
|
+
grid-template-columns: 1fr 1fr;
|
|
176
|
+
gap: 1rem;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.info-item {
|
|
180
|
+
display: flex;
|
|
181
|
+
flex-direction: column;
|
|
182
|
+
gap: 0.25rem;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.info-label {
|
|
186
|
+
font-weight: 600;
|
|
187
|
+
color: #111827;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.info-value {
|
|
191
|
+
color: #6b7280;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.cta-section {
|
|
195
|
+
display: flex;
|
|
196
|
+
justify-content: space-between;
|
|
197
|
+
margin-top: 2.5rem;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.back-link, .demo-link {
|
|
201
|
+
display: inline-block;
|
|
202
|
+
color: #3b82f6;
|
|
203
|
+
text-decoration: none;
|
|
204
|
+
font-weight: 600;
|
|
205
|
+
padding: 0.75rem 1.5rem;
|
|
206
|
+
border: 2px solid #3b82f6;
|
|
207
|
+
border-radius: 12px;
|
|
208
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.back-link:hover, .demo-link:hover {
|
|
212
|
+
background-color: #3b82f6;
|
|
213
|
+
color: #fff;
|
|
214
|
+
transform: translateY(-2px);
|
|
215
|
+
box-shadow: 0 4px 10px rgba(59, 130, 246, 0.3);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.demo-link {
|
|
219
|
+
background-color: #3b82f6;
|
|
220
|
+
color: #fff;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/* Responsive Design */
|
|
224
|
+
@media (max-width: 768px) {
|
|
225
|
+
.content {
|
|
226
|
+
padding: 1.5rem;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.page-title {
|
|
230
|
+
font-size: 2rem;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.info-grid {
|
|
234
|
+
grid-template-columns: 1fr;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.cta-section {
|
|
238
|
+
flex-direction: column;
|
|
239
|
+
gap: 1rem;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
`}</style>
|
|
243
|
+
|
|
244
|
+
<style jsx global>{`
|
|
245
|
+
html,
|
|
246
|
+
body {
|
|
247
|
+
padding: 0;
|
|
248
|
+
margin: 0;
|
|
249
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
|
250
|
+
background-color: #f8f9fa;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
* {
|
|
254
|
+
box-sizing: border-box;
|
|
255
|
+
}
|
|
256
|
+
`}</style>
|
|
257
|
+
</div>
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export const getStaticProps: GetStaticProps<AboutProps> = async () => {
|
|
262
|
+
try {
|
|
263
|
+
// Fetch site information using the ReactPress toolkit
|
|
264
|
+
// Cast to any to access the actual response data
|
|
265
|
+
const settingsResponse = await customApi.setting.findAll() as any;
|
|
266
|
+
|
|
267
|
+
// Extract site information from settings
|
|
268
|
+
const settings = settingsResponse?.data?.data || [];
|
|
269
|
+
const siteInfo = {
|
|
270
|
+
siteName: settings.find((s: any) => s.key === 'siteName')?.value || 'ReactPress Site',
|
|
271
|
+
siteDescription: settings.find((s: any) => s.key === 'siteDescription')?.value || 'A ReactPress powered site',
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
return {
|
|
275
|
+
props: {
|
|
276
|
+
siteInfo,
|
|
277
|
+
},
|
|
278
|
+
revalidate: 60, // Revalidate at most once per minute
|
|
279
|
+
};
|
|
280
|
+
} catch (error) {
|
|
281
|
+
console.error('Failed to fetch site info:', error);
|
|
282
|
+
|
|
283
|
+
// Example of using utils.ApiError
|
|
284
|
+
if (utils.ApiError.isInstance(error)) {
|
|
285
|
+
console.error(`API Error ${error.code}: ${error.message}`);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
props: {
|
|
290
|
+
siteInfo: null,
|
|
291
|
+
},
|
|
292
|
+
revalidate: 60,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
};
|