easy-starter 1.2.1 → 2.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.
Files changed (36) hide show
  1. package/README.md +32 -80
  2. package/bin/index.js +219 -44
  3. package/package.json +20 -11
  4. package/template/.cursorrules +16 -9
  5. package/template/README.md +81 -24
  6. package/template/env +0 -1
  7. package/template/gitignore +1 -1
  8. package/template/index.html +15 -0
  9. package/template/package.json +8 -9
  10. package/template/public/images/icon-16.png +0 -0
  11. package/template/public/images/icon-180.png +0 -0
  12. package/template/public/images/icon-192.png +0 -0
  13. package/template/public/images/icon-32.png +0 -0
  14. package/template/public/images/icon-512.png +0 -0
  15. package/template/{src → public}/site.webmanifest +6 -12
  16. package/template/server/index.tsx +249 -53
  17. package/template/server/mail.tsx +120 -0
  18. package/template/src/App.tsx +33 -7
  19. package/template/src/Router.tsx +11 -2
  20. package/template/src/index.tsx +28 -1
  21. package/template/src/pages/Index.tsx +45 -6
  22. package/template/src/pages/ResetPassword.tsx +126 -0
  23. package/template/src/pages/admin/Admin.tsx +360 -85
  24. package/template/src/pages/admin/AnalyticsTab.tsx +71 -0
  25. package/template/src/pages/admin/ErrorsTab.tsx +46 -0
  26. package/template/src/pages/admin/UsersTab.tsx +61 -0
  27. package/template/src/services/api.ts +5 -7
  28. package/template/src/services/common.ts +23 -0
  29. package/template/src/styles.css +460 -0
  30. package/template/tsconfig.json +2 -1
  31. package/template/types.ts +44 -3
  32. package/template/vite.config.ts +24 -0
  33. package/template/.parcelrc +0 -6
  34. package/template/src/images/icon.png +0 -0
  35. package/template/src/index.html +0 -16
  36. package/template/src/styles.scss +0 -292
@@ -4,23 +4,54 @@ This project was bootstrapped with `easy-starter`, giving you maximum freedom wi
4
4
 
5
5
  ## Features Included
6
6
 
7
- * **React 19 & TypeScript**: For a robust frontend experience.
7
+ * **React 19 & TypeScript 7.0**: A modern, state-of-the-art type-safe frontend experience.
8
8
  * **Express Backend**: A simple Node.js server.
9
- * **Parcel Bundler**: Lightning-fast builds with zero configuration.
10
- * **SSR Ready**: Powered by [`ssr-hook`](https://www.npmjs.com/package/ssr-hook).
11
- * **Type-Safe API**: Connected via [`typed-client-server-api`](https://www.npmjs.com/package/typed-client-server-api).
12
- * **Local Database**: Ready to use with [`easy-db-node`](https://www.npmjs.com/package/easy-db-node).
9
+ * **Vite v8 Bundler**: Zero-config client compilation with lightning-fast HMR and proxying.
10
+ * **Type-Safe API**: RPC communication via [`typed-client-server-api`](https://www.npmjs.com/package/typed-client-server-api).
11
+ * **Local Database**: local JSON-based document storage with [`easy-db-node`](https://www.npmjs.com/package/easy-db-node).
13
12
  * **Routing**: Managed by [`easy-page-router`](https://www.npmjs.com/package/easy-page-router).
13
+ <!-- --- AUTH START --- -->
14
+ * **User Authentication**: Pre-configured user registration, login dialogs, cookie rotation, and password reset flows via [`easy-user-auth`](https://www.npmjs.com/package/easy-user-auth).
15
+ <!-- --- AUTH END --- -->
16
+ <!-- --- SSR START --- -->
17
+ * **SSR Ready**: Server-side rendering and hydration powered by [`ssr-hook`](https://www.npmjs.com/package/ssr-hook).
18
+ <!-- --- SSR END --- -->
19
+ <!-- --- ANALYTICS START --- -->
20
+ * **Analytics**: Privacy-friendly local analytics tracked via [`easy-analytics`](https://www.npmjs.com/package/easy-analytics).
21
+ <!-- --- ANALYTICS END --- -->
22
+ <!-- --- OGIMAGE START --- -->
23
+ * **og:image Generation**: Dynamic page screenshotting for social previews using headless `puppeteer`.
24
+ <!-- --- OGIMAGE END --- -->
25
+
26
+ ---
14
27
 
15
28
  ## Getting Started
16
29
 
17
- To start developing, run:
30
+ To start developing:
18
31
 
19
- ```bash
20
- npm run dev
21
- ```
32
+ 1. Install dependencies (already completed by easy-starter):
33
+ ```bash
34
+ npm install
35
+ ```
36
+ <!-- --- AUTH START --- -->
37
+ 2. **Configure SMTP settings:**
38
+ Open the generated `.env` file and fill in your SMTP credentials. This is required for sending password recovery links to users:
39
+ ```env
40
+ MAIL_SMTP=smtp.example.com
41
+ MAIL_PORT=587
42
+ MAIL_USER=your-email@example.com
43
+ MAIL_PASSWORD=your-email-password
44
+ ```
45
+ <!-- --- AUTH END --- -->
46
+
47
+ 3. Run the development environment:
48
+ ```bash
49
+ npm run dev
50
+ ```
51
+
52
+ This concurrently starts your Express server (port `1111`) and the Vite bundler (port `5173`). Open [http://localhost:5173](http://localhost:5173) in your browser. The page will automatically reload when you make changes.
22
53
 
23
- This will concurrently start your Express server and the Parcel bundler. Open [http://localhost:1234](http://localhost:1234) in your browser. The page will automatically reload when you make changes.
54
+ ---
24
55
 
25
56
  ## Core Concepts & Examples
26
57
 
@@ -28,10 +59,10 @@ This will concurrently start your Express server and the Parcel bundler. Open [h
28
59
 
29
60
  ### 1. Defining your API
30
61
 
31
- Your API contract is defined in a single file (`types.d.ts`). This ensures your frontend and backend are always perfectly in sync.
62
+ Your API contract is defined in `types.ts`. This ensures your frontend and backend are always perfectly in sync.
32
63
 
33
64
  ```typescript
34
- // types.d.ts
65
+ // types.ts
35
66
  import { APIDefinition, Endpoint } from "typed-client-server-api";
36
67
 
37
68
  export type API = APIDefinition<{
@@ -45,21 +76,21 @@ On the server, you implement these endpoints:
45
76
 
46
77
  ```typescript
47
78
  // server/index.tsx
48
- import { initApi } from "typed-client-server-api";
79
+ import { setAPIBackend } from "typed-client-server-api";
49
80
  import { API } from "../types";
50
81
 
51
- initApi<API>(app, {
82
+ setAPIBackend<API>(app, {
52
83
  getItems: async () => {
53
- return db.select("item");
84
+ return selectArray("item");
54
85
  },
55
86
  addItem: async ({ name, value }) => {
56
- return db.insert("item", { name, value });
87
+ return insert("item", { name, value });
57
88
  }
58
89
  });
59
90
  ```
60
91
 
61
- ### 2. Fetching Data with SSR (`useSSRApi`)
62
-
92
+ ### 2. Fetching Data
93
+ <!-- --- SSR START --- -->
63
94
  To fetch data on the server during SSR and seamlessly hydrate it on the client without loading spinners, use `useSSRApi` in your React components.
64
95
 
65
96
  ```tsx
@@ -68,8 +99,6 @@ import React from "react";
68
99
  import { useSSRApi } from "../services/api";
69
100
 
70
101
  export default function Index() {
71
- // This will run on the server, fetch the data, embed it in the HTML,
72
- // and hydrate perfectly on the client. Fully type-safe!
73
102
  const [items, error, isLoading, reload] = useSSRApi.getItems({});
74
103
 
75
104
  if (isLoading) return <p>Loading...</p>;
@@ -82,25 +111,53 @@ export default function Index() {
82
111
  );
83
112
  }
84
113
  ```
114
+ <!-- --- SSR END --- -->
115
+ <!-- --- NO_SSR START --- -->
116
+ To fetch data on the client reactively, use `useApi` in your React components.
117
+
118
+ ```tsx
119
+ // src/pages/Index.tsx
120
+ import React from "react";
121
+ import { useApi } from "../services/api";
122
+
123
+ export default function Index() {
124
+ const [items, error, isLoading, reload] = useApi.getItems({});
125
+
126
+ if (isLoading) return <p>Loading...</p>;
127
+ if (error) return <p>Error: {error.message}</p>;
128
+
129
+ return (
130
+ <ul>
131
+ {items?.map(item => <li key={item._id}>{item.name}</li>)}
132
+ </ul>
133
+ );
134
+ }
135
+ ```
136
+ <!-- --- NO_SSR END --- -->
85
137
 
86
138
  ### 3. AI Integration (`.cursorrules`)
87
139
 
88
- This template includes a pre-configured `.cursorrules` file in the root. If you develop using AI assistants such as Cursor, Windsurf, or GitHub Copilot, they will automatically read this file to understand the specific conventions of `easy-starter`:
140
+ This template includes a pre-configured `.cursorrules` file in the root. If you develop using AI assistants such as Cursor, Windsurf, or GitHub Copilot, they will automatically read this file to understand the specific conventions of `easy-starter`.
141
+
142
+ ---
89
143
 
90
144
  ## Scripts
91
145
 
92
- * `npm run dev` - Starts the development server.
146
+ * `npm run dev` - Starts backend and Vite dev server.
93
147
  * `npm run build` - Builds the application for production.
94
148
  * `npm start` - Starts the production server (run build first).
95
149
  * `npm run deploy` - (If included) Deploys your app to a remote server via SSH.
96
150
 
151
+ ---
152
+
97
153
  ## Project Structure
98
154
 
99
155
  * `/src` - Your React frontend code.
100
156
  * `/server` - Your Express backend code.
101
157
  * `/types.ts` - Shared TypeScript definitions for your API and Database.
102
158
  * `/.cursorrules` - Rules instructing AI coding assistants how to interact with the project stack.
103
- * `/public` - Static assets (images, fonts, etc.).
104
- * `/easy-db` - Where your local database JSON files are stored.
159
+ * `/public` - Static assets served at the root (images, favicon, site.webmanifest).
160
+ * `/easy-db-files` - Where uploaded database files are served.
161
+ * `/easy-db-backup` - Automated backup folder for your JSON collections.
105
162
 
106
163
  Enjoy building with freedom!
package/template/env CHANGED
@@ -1,6 +1,5 @@
1
1
  NODE_ENV=development # development/production
2
2
  SERVER_PORT=1111
3
- ADMIN_PASSWORD=admin
4
3
 
5
4
  SERVER_URL=https://your-production-url.com/
6
5
 
@@ -1,4 +1,4 @@
1
- .parcel-cache/
1
+ .vite/
2
2
  node_modules/
3
3
  dist/
4
4
  easy-db/
@@ -0,0 +1,15 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <link rel="apple-touch-icon" sizes="180x180" href="/images/icon-180.png" />
7
+ <link rel="icon" type="image/png" sizes="32x32" href="/images/icon-32.png" />
8
+ <link rel="icon" type="image/png" sizes="16x16" href="/images/icon-16.png" />
9
+ <link rel="manifest" href="/site.webmanifest" />
10
+ </head>
11
+ <body>
12
+ <div id="root"></div>
13
+ <script type="module" src="/src/index.tsx"></script>
14
+ </body>
15
+ </html>
@@ -6,30 +6,29 @@
6
6
  "start": "tsx --env-file=.env server/index.tsx",
7
7
  "dev": "concurrently --kill-others \"npm run server:dev\" \"npm run fe:dev\"",
8
8
  "server:dev": "tsx --env-file=.env --watch server/index.tsx",
9
- "fe:dev": "parcel src/index.html --no-cache",
10
- "build": "parcel build src/index.html",
11
- "deploy": "tsx scripts/deploy.ts"
9
+ "fe:dev": "vite",
10
+ "build": "vite build"
12
11
  },
13
12
  "dependencies": {
14
13
  "cors": "^2.8.6",
15
- "easy-analytics": "^1.0.1",
16
14
  "easy-db-node": "^3.0.1",
17
15
  "easy-page-router": "^0.2.1",
18
16
  "express": "^5.2.1",
19
17
  "react": "^19.2.6",
20
18
  "react-dom": "^19.2.6",
21
- "ssr-hook": "^0.2.0",
22
19
  "typed-client-server-api": "^1.1.0"
23
20
  },
24
21
  "devDependencies": {
25
22
  "@types/cors": "^2.8.19",
26
23
  "@types/express": "^5.0.6",
27
24
  "@types/node": "^24.0.0",
28
- "@types/react": "^19.2.14",
29
- "@types/react-dom": "^19.2.3",
25
+ "@types/react": "^19.0.0",
26
+ "@types/react-dom": "^19.0.0",
30
27
  "concurrently": "^9.2.1",
31
- "parcel": "^2.16.4",
32
28
  "tsx": "^4.21.0",
33
- "typescript": "^6.0.3"
29
+ "typescript": "^7.0.0",
30
+ "vite": "^8.1.5",
31
+ "@vitejs/plugin-react": "^6.0.3",
32
+ "vite-imagetools": "^10.0.1"
34
33
  }
35
34
  }
@@ -8,39 +8,33 @@
8
8
  "background_color": "#09090b",
9
9
  "icons": [
10
10
  {
11
- "src": "./images/icon.png?width=16&height=16",
11
+ "src": "/images/icon-16.png",
12
12
  "sizes": "16x16",
13
13
  "type": "image/png",
14
14
  "purpose": "maskable"
15
15
  },
16
16
  {
17
- "src": "./images/icon.png?width=32&height=32",
17
+ "src": "/images/icon-32.png",
18
18
  "sizes": "32x32",
19
19
  "type": "image/png",
20
20
  "purpose": "maskable"
21
21
  },
22
22
  {
23
- "src": "./images/icon.png?width=180&height=180",
23
+ "src": "/images/icon-180.png",
24
24
  "sizes": "180x180",
25
25
  "type": "image/png",
26
26
  "purpose": "maskable"
27
27
  },
28
28
  {
29
- "src": "./images/icon.png?as=webp&width=192&height=192",
30
- "sizes": "192x192",
31
- "type": "image/webp",
32
- "purpose": "maskable"
33
- },
34
- {
35
- "src": "./images/icon.png?width=192&height=192",
29
+ "src": "/images/icon-192.png",
36
30
  "sizes": "192x192",
37
31
  "type": "image/png",
38
32
  "purpose": "maskable"
39
33
  },
40
34
  {
41
- "src": "./images/icon.png?as=webp&width=512&height=512",
35
+ "src": "/images/icon-512.png",
42
36
  "sizes": "512x512",
43
- "type": "image/webp",
37
+ "type": "image/png",
44
38
  "purpose": "maskable"
45
39
  }
46
40
  ]