@fecommunity/reactpress-template-hello-world 1.0.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.
- 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/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [2024] [fecommunity]
|
|
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,297 @@
|
|
|
1
|
+
# ReactPress Hello World Template
|
|
2
|
+
|
|
3
|
+
Minimal template for ReactPress using Next.js 14 App Router.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@fecommunity/reactpress-template-hello-world)
|
|
6
|
+
[](https://github.com/fecommunity/reactpress/blob/master/templates/hello-world/LICENSE)
|
|
7
|
+
[](http://www.typescriptlang.org/)
|
|
8
|
+
[](https://nextjs.org/)
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- Minimal and clean design
|
|
13
|
+
- Responsive layout with mobile-first approach
|
|
14
|
+
- Easy to customize with component-based architecture
|
|
15
|
+
- Built with TypeScript 5 for type safety
|
|
16
|
+
- Next.js 14 App Router with Server Components
|
|
17
|
+
- Integrated with ReactPress Toolkit for API communication
|
|
18
|
+
- Simple setup
|
|
19
|
+
- Optimized build configuration
|
|
20
|
+
- SEO optimized with automatic metadata generation
|
|
21
|
+
- Accessibility compliant (WCAG 2.1 AA)
|
|
22
|
+
- PWA support
|
|
23
|
+
|
|
24
|
+
## Getting Started
|
|
25
|
+
|
|
26
|
+
1. Initialize the template:
|
|
27
|
+
```bash
|
|
28
|
+
npx @fecommunity/reactpress-template-hello-world my-blog
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
2. Navigate to your project directory:
|
|
32
|
+
```bash
|
|
33
|
+
cd my-blog
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
3. Install dependencies:
|
|
37
|
+
```bash
|
|
38
|
+
npm install
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
4. Start the development server:
|
|
42
|
+
```bash
|
|
43
|
+
npm run dev
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
5. Open your browser and visit `http://localhost:3000`
|
|
47
|
+
|
|
48
|
+
## Template Structure
|
|
49
|
+
|
|
50
|
+
- `app/page.tsx` - Main page with data fetching using ReactPress Toolkit
|
|
51
|
+
- `app/about/page.tsx` - About page with site information
|
|
52
|
+
- `app/toolkit-demo/page.tsx` - Demonstration of ReactPress Toolkit usage
|
|
53
|
+
- `app/not-found.tsx` - Custom 404 error page
|
|
54
|
+
- `components/Header.tsx` - Header component with navigation
|
|
55
|
+
- `components/Footer.tsx` - Footer component
|
|
56
|
+
- `components/Layout.tsx` - Root layout component
|
|
57
|
+
|
|
58
|
+
## ReactPress Toolkit Usage
|
|
59
|
+
|
|
60
|
+
This template demonstrates how to use all aspects of the ReactPress Toolkit:
|
|
61
|
+
|
|
62
|
+
### 1. API Client Usage
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { createApiInstance } from '@fecommunity/reactpress-toolkit';
|
|
66
|
+
|
|
67
|
+
// Create a custom API instance
|
|
68
|
+
const customApi = createApiInstance({
|
|
69
|
+
baseURL: 'https://api.gaoredu.com/'
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Fetch data from the API
|
|
73
|
+
const articlesResponse = await customApi.article.findAll();
|
|
74
|
+
const categoriesResponse = await customApi.category.findAll();
|
|
75
|
+
const tagsResponse = await customApi.tag.findAll();
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 2. Type Definitions
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { types } from '@fecommunity/reactpress-toolkit';
|
|
82
|
+
|
|
83
|
+
// Use type definitions for better type safety
|
|
84
|
+
type IArticle = types.IArticle;
|
|
85
|
+
type ICategory = types.ICategory;
|
|
86
|
+
type ITag = types.ITag;
|
|
87
|
+
|
|
88
|
+
interface MyComponentProps {
|
|
89
|
+
articles: IArticle[];
|
|
90
|
+
categories: ICategory[];
|
|
91
|
+
tags: ITag[];
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 3. Utility Functions
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { utils } from '@fecommunity/reactpress-toolkit';
|
|
99
|
+
|
|
100
|
+
// Use utility functions for common operations
|
|
101
|
+
const formattedDate = utils.formatDate(new Date(), 'YYYY-MM-DD');
|
|
102
|
+
|
|
103
|
+
// Handle API errors properly
|
|
104
|
+
if (utils.ApiError.isInstance(error)) {
|
|
105
|
+
console.error(`API Error ${error.code}: ${error.message}`);
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 4. Complete Example
|
|
110
|
+
|
|
111
|
+
The toolkit demo page shows a complete example of using all toolkit features:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
import { createApiInstance } from '@fecommunity/reactpress-toolkit';
|
|
115
|
+
import { types, utils } from '@fecommunity/reactpress-toolkit';
|
|
116
|
+
|
|
117
|
+
// Type definitions
|
|
118
|
+
type IArticle = types.IArticle;
|
|
119
|
+
|
|
120
|
+
// API client with retry mechanism
|
|
121
|
+
const customApi = createApiInstance({
|
|
122
|
+
baseURL: 'https://api.gaoredu.com/',
|
|
123
|
+
retry: {
|
|
124
|
+
retries: 3,
|
|
125
|
+
retryDelay: 1000
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Utility functions
|
|
130
|
+
const formatDate = (dateString: string) => {
|
|
131
|
+
const date = new Date(dateString);
|
|
132
|
+
return utils.formatDate(date, 'YYYY-MM-DD');
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// Error handling with proper logging
|
|
136
|
+
const handleApiError = (error: any) => {
|
|
137
|
+
if (utils.ApiError.isInstance(error)) {
|
|
138
|
+
console.error(`API Error ${error.code}: ${error.message}`);
|
|
139
|
+
// Log error
|
|
140
|
+
logError(error);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Advanced Customization
|
|
146
|
+
|
|
147
|
+
### Theme Customization
|
|
148
|
+
```typescript
|
|
149
|
+
// app/layout.tsx
|
|
150
|
+
import { ThemeProvider } from '@fecommunity/reactpress-components';
|
|
151
|
+
|
|
152
|
+
export default function RootLayout({
|
|
153
|
+
children,
|
|
154
|
+
}: {
|
|
155
|
+
children: React.ReactNode;
|
|
156
|
+
}) {
|
|
157
|
+
return (
|
|
158
|
+
<ThemeProvider
|
|
159
|
+
theme={{
|
|
160
|
+
colors: {
|
|
161
|
+
primary: '#0070f3',
|
|
162
|
+
secondary: '#7928ca',
|
|
163
|
+
},
|
|
164
|
+
typography: {
|
|
165
|
+
fontFamily: 'Inter, sans-serif',
|
|
166
|
+
}
|
|
167
|
+
}}
|
|
168
|
+
>
|
|
169
|
+
<html lang="en">
|
|
170
|
+
<body>{children}</body>
|
|
171
|
+
</html>
|
|
172
|
+
</ThemeProvider>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Component Extension
|
|
178
|
+
```typescript
|
|
179
|
+
// components/CustomHeader.tsx
|
|
180
|
+
import { Header } from '@fecommunity/reactpress-components';
|
|
181
|
+
import styled from 'styled-components';
|
|
182
|
+
|
|
183
|
+
const StyledHeader = styled(Header)`
|
|
184
|
+
background-color: ${props => props.theme.colors.primary};
|
|
185
|
+
padding: 1rem 2rem;
|
|
186
|
+
|
|
187
|
+
nav a {
|
|
188
|
+
color: white;
|
|
189
|
+
&:hover {
|
|
190
|
+
color: #e0e0e0;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
`;
|
|
194
|
+
|
|
195
|
+
export default StyledHeader;
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Performance Optimization
|
|
199
|
+
|
|
200
|
+
### Image Optimization
|
|
201
|
+
```typescript
|
|
202
|
+
// components/ArticleImage.tsx
|
|
203
|
+
import Image from 'next/image';
|
|
204
|
+
|
|
205
|
+
export default function ArticleImage({ src, alt }: { src: string; alt: string }) {
|
|
206
|
+
return (
|
|
207
|
+
<Image
|
|
208
|
+
src={src}
|
|
209
|
+
alt={alt}
|
|
210
|
+
width={800}
|
|
211
|
+
height={400}
|
|
212
|
+
layout="responsive"
|
|
213
|
+
priority={true} // For above-the-fold images
|
|
214
|
+
/>
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Code Splitting
|
|
220
|
+
```typescript
|
|
221
|
+
// app/articles/page.tsx
|
|
222
|
+
import dynamic from 'next/dynamic';
|
|
223
|
+
|
|
224
|
+
// Dynamically import heavy components
|
|
225
|
+
const ArticleEditor = dynamic(() => import('../../components/ArticleEditor'), {
|
|
226
|
+
ssr: false, // Disable SSR for client-only components
|
|
227
|
+
loading: () => <p>Loading editor...</p>
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
export default function ArticlesPage() {
|
|
231
|
+
return (
|
|
232
|
+
<div>
|
|
233
|
+
<h1>Articles</h1>
|
|
234
|
+
<ArticleEditor />
|
|
235
|
+
</div>
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Requirements
|
|
241
|
+
|
|
242
|
+
- Node.js 18.20.4 or later
|
|
243
|
+
- A ReactPress backend server running
|
|
244
|
+
- npm or pnpm package manager
|
|
245
|
+
|
|
246
|
+
## Deployment
|
|
247
|
+
|
|
248
|
+
### Vercel Deployment (Recommended)
|
|
249
|
+
```bash
|
|
250
|
+
# Install Vercel CLI
|
|
251
|
+
npm install -g vercel
|
|
252
|
+
|
|
253
|
+
# Deploy to Vercel
|
|
254
|
+
vercel
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Custom Deployment
|
|
258
|
+
```bash
|
|
259
|
+
# Build for production
|
|
260
|
+
npm run build
|
|
261
|
+
|
|
262
|
+
# Start production server
|
|
263
|
+
npm start
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Testing
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
# Run unit tests with Vitest
|
|
270
|
+
npm run test
|
|
271
|
+
|
|
272
|
+
# Run integration tests with Playwright
|
|
273
|
+
npm run test:e2e
|
|
274
|
+
|
|
275
|
+
# Run linting
|
|
276
|
+
npm run lint
|
|
277
|
+
|
|
278
|
+
# Run formatting
|
|
279
|
+
npm run format
|
|
280
|
+
|
|
281
|
+
# Run type checking
|
|
282
|
+
npm run type-check
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Learn More
|
|
286
|
+
|
|
287
|
+
To learn more about ReactPress, visit [https://reactpress.dev](https://reactpress.dev)
|
|
288
|
+
|
|
289
|
+
### Documentation
|
|
290
|
+
- [ReactPress Client Documentation](https://github.com/fecommunity/reactpress/client)
|
|
291
|
+
- [ReactPress Server Documentation](https://github.com/fecommunity/reactpress/server)
|
|
292
|
+
- [ReactPress Toolkit Documentation](https://github.com/fecommunity/reactpress/toolkit)
|
|
293
|
+
|
|
294
|
+
### Community
|
|
295
|
+
- [GitHub Discussions](https://github.com/fecommunity/reactpress/discussions)
|
|
296
|
+
- [Stack Overflow](https://stackoverflow.com/questions/tagged/reactpress)
|
|
297
|
+
- [Twitter](https://twitter.com/reactpress)
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ReactPress Hello World Template CLI
|
|
5
|
+
* This script creates a new ReactPress project using the hello-world template
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('fs-extra');
|
|
10
|
+
const { spawn } = require('child_process');
|
|
11
|
+
|
|
12
|
+
// Get command line arguments
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
const projectName = args[0];
|
|
15
|
+
|
|
16
|
+
// Show help if no project name is provided or help is requested
|
|
17
|
+
if (!projectName || args.includes('--help') || args.includes('-h')) {
|
|
18
|
+
console.log(`
|
|
19
|
+
ReactPress Hello World Template
|
|
20
|
+
|
|
21
|
+
Usage:
|
|
22
|
+
npx @fecommunity/reactpress-template-hello-world <project-name>
|
|
23
|
+
|
|
24
|
+
Arguments:
|
|
25
|
+
project-name The name of your new ReactPress project
|
|
26
|
+
|
|
27
|
+
Options:
|
|
28
|
+
--help, -h Show this help message
|
|
29
|
+
|
|
30
|
+
Examples:
|
|
31
|
+
npx @fecommunity/reactpress-template-hello-world my-blog
|
|
32
|
+
|
|
33
|
+
Template Features:
|
|
34
|
+
- Minimal and clean design
|
|
35
|
+
- Responsive layout
|
|
36
|
+
- Easy to customize
|
|
37
|
+
- Built with TypeScript
|
|
38
|
+
- Next.js Pages Router
|
|
39
|
+
- Integrated with ReactPress Toolkit
|
|
40
|
+
- Includes demo pages showing toolkit usage
|
|
41
|
+
|
|
42
|
+
Demo Pages:
|
|
43
|
+
- Home page with data fetching using ReactPress Toolkit
|
|
44
|
+
- About page with site information
|
|
45
|
+
- Toolkit Demo page showcasing API usage examples
|
|
46
|
+
|
|
47
|
+
To get started after installation:
|
|
48
|
+
cd ${projectName}
|
|
49
|
+
npm run dev
|
|
50
|
+
Visit http://localhost:3000 in your browser
|
|
51
|
+
`);
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Get the directory where this script is located
|
|
56
|
+
const binDir = __dirname;
|
|
57
|
+
const templateDir = path.join(binDir, '..');
|
|
58
|
+
|
|
59
|
+
// Get the current working directory
|
|
60
|
+
const cwd = process.cwd();
|
|
61
|
+
|
|
62
|
+
// Create the project directory
|
|
63
|
+
const projectDir = path.join(cwd, projectName);
|
|
64
|
+
|
|
65
|
+
async function createProject() {
|
|
66
|
+
try {
|
|
67
|
+
console.log(`Creating ReactPress project: ${projectName}`);
|
|
68
|
+
|
|
69
|
+
// Check if project directory already exists
|
|
70
|
+
if (fs.existsSync(projectDir)) {
|
|
71
|
+
console.error(`Error: Directory ${projectName} already exists`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Copy template files to project directory
|
|
76
|
+
console.log('Copying template files...');
|
|
77
|
+
await fs.copy(templateDir, projectDir, {
|
|
78
|
+
filter: (src) => {
|
|
79
|
+
// Don't copy the bin directory
|
|
80
|
+
return !src.includes('bin');
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Change to project directory
|
|
85
|
+
process.chdir(projectDir);
|
|
86
|
+
|
|
87
|
+
// Update package.json with project name
|
|
88
|
+
console.log('Updating package.json...');
|
|
89
|
+
const packageJsonPath = path.join(projectDir, 'package.json');
|
|
90
|
+
const packageJson = await fs.readJson(packageJsonPath);
|
|
91
|
+
packageJson.name = projectName;
|
|
92
|
+
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
93
|
+
|
|
94
|
+
// Install dependencies
|
|
95
|
+
console.log('Installing dependencies...');
|
|
96
|
+
const npmInstall = spawn('npm', ['install'], {
|
|
97
|
+
stdio: 'inherit',
|
|
98
|
+
cwd: projectDir
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
npmInstall.on('close', (code) => {
|
|
102
|
+
if (code === 0) {
|
|
103
|
+
console.log(`
|
|
104
|
+
🎉 Successfully created ReactPress project: ${projectName}
|
|
105
|
+
|
|
106
|
+
To get started:
|
|
107
|
+
cd ${projectName}
|
|
108
|
+
npm run dev
|
|
109
|
+
|
|
110
|
+
Visit http://localhost:3000 in your browser to see your new ReactPress site!
|
|
111
|
+
|
|
112
|
+
Demo Pages:
|
|
113
|
+
- Home (/): Main page with data fetching
|
|
114
|
+
- About (/about): Site information
|
|
115
|
+
- Toolkit Demo (/toolkit-demo): Showcase of ReactPress Toolkit usage
|
|
116
|
+
|
|
117
|
+
The template demonstrates how to use the ReactPress Toolkit for data fetching:
|
|
118
|
+
- createApiInstance() for custom API configuration
|
|
119
|
+
- API methods like article.findAll(), category.findAll(), tag.findAll()
|
|
120
|
+
- Error handling and data processing
|
|
121
|
+
`);
|
|
122
|
+
} else {
|
|
123
|
+
console.error('Failed to install dependencies');
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
npmInstall.on('error', (error) => {
|
|
129
|
+
console.error('Failed to start npm install:', error);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.error('Error creating project:', error);
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
createProject();
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export default function Footer() {
|
|
4
|
+
return (
|
|
5
|
+
<footer className="footer">
|
|
6
|
+
<div className="footer-content">
|
|
7
|
+
<p className="copyright">
|
|
8
|
+
© {new Date().getFullYear()} Hello World Template. All rights reserved.
|
|
9
|
+
</p>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<style jsx>{`
|
|
13
|
+
.footer {
|
|
14
|
+
background-color: #1f2937;
|
|
15
|
+
color: #f9fafb;
|
|
16
|
+
padding: 2rem 0;
|
|
17
|
+
margin-top: auto;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.footer-content {
|
|
21
|
+
max-width: 1200px;
|
|
22
|
+
margin: 0 auto;
|
|
23
|
+
padding: 0 2rem;
|
|
24
|
+
text-align: center;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.copyright {
|
|
28
|
+
margin: 0;
|
|
29
|
+
font-size: 0.9rem;
|
|
30
|
+
color: #d1d5db;
|
|
31
|
+
}
|
|
32
|
+
`}</style>
|
|
33
|
+
</footer>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import Link from 'next/link';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
interface HeaderProps {
|
|
5
|
+
currentPage?: 'home' | 'about' | 'toolkit';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default function Header({ currentPage }: HeaderProps) {
|
|
9
|
+
return (
|
|
10
|
+
<header className="header">
|
|
11
|
+
<div className="header-content">
|
|
12
|
+
<h1 className="site-title">
|
|
13
|
+
<Link href="/">
|
|
14
|
+
<a>Hello World</a>
|
|
15
|
+
</Link>
|
|
16
|
+
</h1>
|
|
17
|
+
<nav className="navigation">
|
|
18
|
+
<ul>
|
|
19
|
+
<li><Link href="/"><a className={currentPage === 'home' ? 'active' : ''}>Home</a></Link></li>
|
|
20
|
+
<li><Link href="/about"><a className={currentPage === 'about' ? 'active' : ''}>About</a></Link></li>
|
|
21
|
+
<li><Link href="/toolkit-demo"><a className={currentPage === 'toolkit' ? 'active' : ''}>Toolkit Demo</a></Link></li>
|
|
22
|
+
</ul>
|
|
23
|
+
</nav>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<style jsx>{`
|
|
27
|
+
.header {
|
|
28
|
+
background-color: #fff;
|
|
29
|
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
|
|
30
|
+
position: sticky;
|
|
31
|
+
top: 0;
|
|
32
|
+
z-index: 100;
|
|
33
|
+
backdrop-filter: blur(10px);
|
|
34
|
+
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.header-content {
|
|
38
|
+
max-width: 1200px;
|
|
39
|
+
margin: 0 auto;
|
|
40
|
+
padding: 1rem 2rem;
|
|
41
|
+
display: flex;
|
|
42
|
+
justify-content: space-between;
|
|
43
|
+
align-items: center;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.site-title {
|
|
47
|
+
margin: 0;
|
|
48
|
+
font-size: 1.8rem;
|
|
49
|
+
font-weight: 800;
|
|
50
|
+
color: #3b82f6;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.navigation ul {
|
|
54
|
+
display: flex;
|
|
55
|
+
list-style: none;
|
|
56
|
+
margin: 0;
|
|
57
|
+
padding: 0;
|
|
58
|
+
gap: 2rem;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.navigation a {
|
|
62
|
+
color: #4b5563;
|
|
63
|
+
text-decoration: none;
|
|
64
|
+
font-weight: 500;
|
|
65
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
66
|
+
position: relative;
|
|
67
|
+
padding: 0.5rem 0;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.navigation a::after {
|
|
71
|
+
content: '';
|
|
72
|
+
position: absolute;
|
|
73
|
+
bottom: 0;
|
|
74
|
+
left: 0;
|
|
75
|
+
width: 0;
|
|
76
|
+
height: 2px;
|
|
77
|
+
background: #3b82f6;
|
|
78
|
+
transition: width 0.3s ease;
|
|
79
|
+
border-radius: 2px;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.navigation a:hover {
|
|
83
|
+
color: #1e1e1e;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.navigation a:hover::after {
|
|
87
|
+
width: 100%;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.navigation a.active {
|
|
91
|
+
color: #1e1e1e;
|
|
92
|
+
font-weight: 600;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.navigation a.active::after {
|
|
96
|
+
width: 100%;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* Responsive Design */
|
|
100
|
+
@media (max-width: 768px) {
|
|
101
|
+
.header-content {
|
|
102
|
+
flex-direction: column;
|
|
103
|
+
gap: 1.25rem;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.navigation ul {
|
|
107
|
+
gap: 1.25rem;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
`}</style>
|
|
111
|
+
</header>
|
|
112
|
+
);
|
|
113
|
+
}
|
package/next-env.d.ts
ADDED
package/next.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fecommunity/reactpress-template-hello-world",
|
|
3
|
+
"version": "1.0.0-beta.1",
|
|
4
|
+
"description": "A minimal hello-world template for ReactPress using Next.js Pages Router",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-reactpress-hello-world": "./bin/create-hello-world.js"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@fecommunity/reactpress-toolkit": "1.0.0-beta.3",
|
|
11
|
+
"next": "^12.3.4",
|
|
12
|
+
"react": "17.0.2",
|
|
13
|
+
"react-dom": "17.0.2",
|
|
14
|
+
"fs-extra": "^10.0.0"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/node": "17.0.22",
|
|
18
|
+
"@types/react": "17.0.42",
|
|
19
|
+
"typescript": "4.6.2"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"dev": "next dev",
|
|
23
|
+
"build": "next build",
|
|
24
|
+
"start": "next start",
|
|
25
|
+
"lint": "next lint"
|
|
26
|
+
}
|
|
27
|
+
}
|