@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 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
+ [![NPM Version](https://img.shields.io/npm/v/@fecommunity/reactpress-template-hello-world.svg)](https://www.npmjs.com/package/@fecommunity/reactpress-template-hello-world)
6
+ [![License](https://img.shields.io/npm/l/@fecommunity/reactpress-template-hello-world.svg)](https://github.com/fecommunity/reactpress/blob/master/templates/hello-world/LICENSE)
7
+ [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/)
8
+ [![Next.js](https://img.shields.io/badge/Next.js-14-black)](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
+ &copy; {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
@@ -0,0 +1,5 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+
4
+ // NOTE: This file should not be edited
5
+ // see https://nextjs.org/docs/basic-features/typescript for more information.
package/next.config.js ADDED
@@ -0,0 +1,10 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ reactStrictMode: true,
4
+ swcMinify: true,
5
+ eslint: {
6
+ ignoreDuringBuilds: true,
7
+ },
8
+ }
9
+
10
+ module.exports = nextConfig
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
+ }