create-nxpress-app 1.0.6 → 1.0.8

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/dist/index.js CHANGED
@@ -12,6 +12,40 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
12
12
  const path_1 = __importDefault(require("path"));
13
13
  const util_1 = require("util");
14
14
  const execAsync = (0, util_1.promisify)(child_process_1.exec);
15
+ const deps = ["@nxpress/core"];
16
+ const devDeps = ["@types/express", "@types/node", "typescript"];
17
+ function getInstallCommands(pm, depsList, devDepsList) {
18
+ const depsStr = depsList.join(" ");
19
+ const devDepsStr = devDepsList.join(" ");
20
+ switch (pm) {
21
+ case "npm":
22
+ return {
23
+ depsCmd: `npm install ${depsStr}`,
24
+ devDepsCmd: `npm install -D ${devDepsStr}`,
25
+ };
26
+ case "yarn":
27
+ return {
28
+ depsCmd: `yarn add ${depsStr}`,
29
+ devDepsCmd: `yarn add -D ${devDepsStr}`,
30
+ };
31
+ case "bun":
32
+ return {
33
+ depsCmd: `bun add ${depsStr}`,
34
+ devDepsCmd: `bun add -d ${devDepsStr}`,
35
+ };
36
+ case "deno":
37
+ return {
38
+ depsCmd: `deno add ${depsStr}`,
39
+ devDepsCmd: `deno add -D ${devDepsStr}`,
40
+ };
41
+ case "pnpm":
42
+ default:
43
+ return {
44
+ depsCmd: `pnpm add ${depsStr}`,
45
+ devDepsCmd: `pnpm add -D ${devDepsStr}`,
46
+ };
47
+ }
48
+ }
15
49
  const program = new commander_1.Command();
16
50
  program
17
51
  .name("create-nxpress-app")
@@ -23,7 +57,7 @@ program
23
57
  .option("--app-dir <dir>", "Directory for application routes")
24
58
  .option("--components-dir <dir>", "Directory for components")
25
59
  .option("--public-dir <dir>", "Directory for static assets")
26
- .option("--skip-install", "Skip installing dependencies", false)
60
+ .option("--pkg-manager <pm>", "Package manager (pnpm, npm, yarn, bun, deno)")
27
61
  .action(async (projectDirArg, options) => {
28
62
  console.log();
29
63
  (0, prompts_1.intro)(chalk_1.default.bgCyan.black(" Create Nxpress App "));
@@ -135,17 +169,47 @@ program
135
169
  publicDirName = pubRes;
136
170
  }
137
171
  }
138
- let shouldInstall = !options.skipInstall;
139
- if (!options.skipInstall && process.stdin.isTTY) {
140
- const res = await (0, prompts_1.confirm)({
141
- message: "Install dependencies using pnpm?",
142
- initialValue: true,
172
+ let pkgManager = options.pkgManager;
173
+ if (process.stdin.isTTY && !options.pkgManager) {
174
+ const selectedPm = await (0, prompts_1.select)({
175
+ message: "Which package manager do you want to use?",
176
+ options: [
177
+ {
178
+ value: "pnpm",
179
+ label: "pnpm (Default)",
180
+ hint: "Fast & disk space efficient",
181
+ },
182
+ {
183
+ value: "npm",
184
+ label: "npm",
185
+ hint: "Default Node.js package manager",
186
+ },
187
+ {
188
+ value: "yarn",
189
+ label: "yarn",
190
+ hint: "Classic/Berry package manager",
191
+ },
192
+ {
193
+ value: "bun",
194
+ label: "bun",
195
+ hint: "Ultra-fast runtime & package manager",
196
+ },
197
+ {
198
+ value: "deno",
199
+ label: "deno",
200
+ hint: "Modern JavaScript/TypeScript runtime",
201
+ },
202
+ ],
203
+ initialValue: "pnpm",
143
204
  });
144
- if ((0, prompts_1.isCancel)(res)) {
205
+ if ((0, prompts_1.isCancel)(selectedPm)) {
145
206
  (0, prompts_1.cancel)("Operation cancelled.");
146
207
  process.exit(0);
147
208
  }
148
- shouldInstall = res;
209
+ pkgManager = selectedPm;
210
+ }
211
+ if (!pkgManager) {
212
+ pkgManager = "pnpm";
149
213
  }
150
214
  const s = (0, prompts_1.spinner)();
151
215
  s.start("Scaffolding project...");
@@ -157,102 +221,47 @@ program
157
221
  fs_extra_1.default.ensureDirSync(appDir);
158
222
  fs_extra_1.default.ensureDirSync(componentsDir);
159
223
  fs_extra_1.default.ensureDirSync(publicDir);
224
+ const templatesDir = path_1.default.resolve(__dirname, "..", "templates");
160
225
  const ext = engine === "handlebars" ? "hbs" : engine;
161
- // Root layout
162
- const layoutContent = engine === "handlebars"
163
- ? `<!DOCTYPE html>
164
- <html lang="en">
165
- <head>
166
- <meta charset="UTF-8">
167
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
168
- <title>{{title}}</title>
169
- </head>
170
- <body class="bg-slate-900 text-white min-h-screen">
171
- {{{body}}}
172
- </body>
173
- </html>`
174
- : engine === "ejs"
175
- ? `<!DOCTYPE html>
176
- <html lang="en">
177
- <head>
178
- <meta charset="UTF-8">
179
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
180
- <title><%= title %></title>
181
- </head>
182
- <body class="bg-slate-900 text-white min-h-screen">
183
- <%- body %>
184
- </body>
185
- </html>`
186
- : `<!DOCTYPE html>
187
- <html lang="en">
188
- <head>
189
- <meta charset="UTF-8">
190
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
191
- <title>Nxpress App</title>
192
- </head>
193
- <body class="bg-slate-900 text-white min-h-screen">
194
- <!-- Content -->
195
- </body>
196
- </html>`;
197
- fs_extra_1.default.writeFileSync(path_1.default.join(appDir, `layout.${ext}`), layoutContent);
198
- // Index page
199
- const indexPageContent = engine === "handlebars"
200
- ? `<div class="max-w-4xl mx-auto px-4 py-16 text-center">
201
- <h1 class="text-5xl font-bold mb-4 bg-linear-to-r from-blue-400 to-indigo-500 bg-clip-text text-transparent">
202
- Welcome to {{title}}
203
- </h1>
204
- <p class="text-xl text-slate-400 mb-8">{{description}}</p>
205
- <div class="inline-block bg-slate-800 border border-slate-700 rounded-lg p-6 text-left">
206
- <p class="text-sm font-mono text-cyan-400">Edit <span class="text-amber-300">${appDirName}/index.${ext}</span> to get started.</p>
207
- </div>
208
- </div>`
209
- : engine === "ejs"
210
- ? `<div class="max-w-4xl mx-auto px-4 py-16 text-center">
211
- <h1 class="text-5xl font-bold mb-4 bg-linear-to-r from-blue-400 to-indigo-500 bg-clip-text text-transparent">
212
- Welcome to <%= title %>
213
- </h1>
214
- <p class="text-xl text-slate-400 mb-8"><%= description %></p>
215
- <div class="inline-block bg-slate-800 border border-slate-700 rounded-lg p-6 text-left">
216
- <p class="text-sm font-mono text-cyan-400">Edit <span class="text-amber-300">${appDirName}/index.${ext}</span> to get started.</p>
217
- </div>
218
- </div>`
219
- : `<div class="max-w-4xl mx-auto px-4 py-16 text-center">
220
- <h1 class="text-5xl font-bold mb-4 bg-linear-to-r from-blue-400 to-indigo-500 bg-clip-text text-transparent">
221
- Welcome to Nxpress
222
- </h1>
223
- <p class="text-xl text-slate-400 mb-8">Express.js with Next.js developer experience</p>
224
- </div>`;
225
- fs_extra_1.default.writeFileSync(path_1.default.join(appDir, `index.${ext}`), indexPageContent);
226
+ // Copy public assets (e.g., logo.png)
227
+ const templatePublicDir = path_1.default.join(templatesDir, "public");
228
+ if (fs_extra_1.default.existsSync(templatePublicDir)) {
229
+ fs_extra_1.default.copySync(templatePublicDir, publicDir);
230
+ }
231
+ // Root layout from template
232
+ const layoutTemplatePath = path_1.default.join(templatesDir, "app", `layout.${ext}`);
233
+ if (fs_extra_1.default.existsSync(layoutTemplatePath)) {
234
+ fs_extra_1.default.copySync(layoutTemplatePath, path_1.default.join(appDir, `layout.${ext}`));
235
+ }
236
+ // Index page from template
237
+ const indexTemplatePath = path_1.default.join(templatesDir, "app", `index.${ext}`);
238
+ if (fs_extra_1.default.existsSync(indexTemplatePath)) {
239
+ let content = fs_extra_1.default.readFileSync(indexTemplatePath, "utf8");
240
+ content = content.replace(/app\/index\.(hbs|ejs|html)/g, `${appDirName}/index.${ext}`);
241
+ fs_extra_1.default.writeFileSync(path_1.default.join(appDir, `index.${ext}`), content);
242
+ }
226
243
  // Data loader for index page
227
- const indexTsContent = `import { Request, Response } from "express";
228
-
229
- export async function props(req: Request, res: Response) {
230
- return {
231
- title: 'Nxpress App',
232
- description: 'Express.js with Next.js developer experience',
233
- };
234
- }
235
- `;
236
- fs_extra_1.default.writeFileSync(path_1.default.join(appDir, "index.ts"), indexTsContent);
244
+ const indexTsTemplatePath = path_1.default.join(templatesDir, "app", "index.ts");
245
+ if (fs_extra_1.default.existsSync(indexTsTemplatePath)) {
246
+ fs_extra_1.default.copySync(indexTsTemplatePath, path_1.default.join(appDir, "index.ts"));
247
+ }
237
248
  // App CSS for Tailwind v4
238
- fs_extra_1.default.writeFileSync(path_1.default.join(targetPath, "app.css"), `@import "tailwindcss";\n@import "tailwindcss/preflight";\n@tailwind utilities;\n`);
249
+ const appCssTemplatePath = path_1.default.join(templatesDir, "app.css");
250
+ if (fs_extra_1.default.existsSync(appCssTemplatePath)) {
251
+ fs_extra_1.default.copySync(appCssTemplatePath, path_1.default.join(targetPath, "app.css"));
252
+ }
239
253
  // Server file
240
- const serverTsContent = `import { nxpress } from '@nxpress/core';
241
-
242
- const app = nxpress({
243
- engine: '${engine === "handlebars" ? "hbs" : engine}',
244
- });
245
-
246
- const PORT = process.env.PORT || ${port};
247
- app.listen(PORT, () => {
248
- console.log(\`Nxpress server running on http://localhost:\${PORT}\`);
249
- });
250
- `;
251
- fs_extra_1.default.writeFileSync(path_1.default.join(targetPath, "server.ts"), serverTsContent);
252
- const pkgVersion = "1.0.5";
254
+ const serverTsTemplatePath = path_1.default.join(templatesDir, "server.ts");
255
+ if (fs_extra_1.default.existsSync(serverTsTemplatePath)) {
256
+ let serverContent = fs_extra_1.default.readFileSync(serverTsTemplatePath, "utf8");
257
+ serverContent = serverContent
258
+ .replace("{{ENGINE}}", engine === "handlebars" ? "hbs" : engine)
259
+ .replace("{{PORT}}", port.toString());
260
+ fs_extra_1.default.writeFileSync(path_1.default.join(targetPath, "server.ts"), serverContent);
261
+ }
253
262
  // nxpress.config.json
254
263
  const nxConfig = {
255
- $schema: `https://unpkg.com/@nxpress/core@${pkgVersion}/schema.json`,
264
+ $schema: `https://unpkg.com/@nxpress/core@latest/schema.json`,
256
265
  port,
257
266
  engine: engine === "handlebars" ? "hbs" : engine,
258
267
  appDir: appDirName,
@@ -270,14 +279,6 @@ app.listen(PORT, () => {
270
279
  build: "tsc",
271
280
  start: "nxpress start",
272
281
  },
273
- dependencies: {
274
- "@nxpress/core": `^${pkgVersion}`,
275
- },
276
- devDependencies: {
277
- "@types/express": "^5.0.6",
278
- "@types/node": "^26.1.1",
279
- typescript: "^7.0.2",
280
- },
281
282
  };
282
283
  fs_extra_1.default.writeFileSync(path_1.default.join(targetPath, "package.json"), JSON.stringify(projectPkgJson, null, 2));
283
284
  // tsconfig.json for target project
@@ -303,20 +304,21 @@ dist
303
304
  `;
304
305
  fs_extra_1.default.writeFileSync(path_1.default.join(targetPath, ".gitignore"), gitignoreContent);
305
306
  s.stop("Project structure created successfully.");
306
- if (shouldInstall) {
307
- const instSpinner = (0, prompts_1.spinner)();
308
- instSpinner.start("Installing dependencies with pnpm...");
309
- try {
310
- await execAsync("pnpm install", { cwd: targetPath });
311
- instSpinner.stop("Dependencies installed successfully.");
312
- }
313
- catch (err) {
314
- instSpinner.stop("Failed to install dependencies automatically.");
315
- }
307
+ const instSpinner = (0, prompts_1.spinner)();
308
+ instSpinner.start(`Installing dependencies with ${pkgManager}...`);
309
+ try {
310
+ const { depsCmd, devDepsCmd } = getInstallCommands(pkgManager, deps, devDeps);
311
+ await execAsync(depsCmd, { cwd: targetPath });
312
+ await execAsync(devDepsCmd, { cwd: targetPath });
313
+ instSpinner.stop("Dependencies installed successfully.");
314
+ }
315
+ catch (err) {
316
+ instSpinner.stop("Failed to install dependencies automatically.");
316
317
  }
318
+ const devCmd = pkgManager === "npm" ? "npm run dev" : `${pkgManager} dev`;
317
319
  (0, prompts_1.outro)(`Project created in ${chalk_1.default.cyan(projectDir)}!\n\n` +
318
320
  `Next steps:\n` +
319
321
  ` ${chalk_1.default.cyan(`cd ${projectDir}`)}\n` +
320
- ` ${chalk_1.default.cyan("pnpm dev")}`);
322
+ ` ${chalk_1.default.cyan(devCmd)}`);
321
323
  });
322
324
  program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-nxpress-app",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "CLI tool to create Nxpress applications",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -28,6 +28,7 @@
28
28
  "fs-extra": "^11.4.0"
29
29
  },
30
30
  "devDependencies": {
31
+ "@types/express": "^5.0.6",
31
32
  "@types/fs-extra": "^11.0.4",
32
33
  "@types/node": "^26.1.1",
33
34
  "typescript": "^7.0.2"
@@ -0,0 +1,92 @@
1
+ <div class="min-h-screen flex flex-col justify-between max-w-6xl mx-auto px-6 py-8">
2
+ <header class="flex items-center justify-between py-4 border-b border-slate-800/80">
3
+ <div class="flex items-center gap-3">
4
+ <span class="font-bold text-lg text-slate-100 tracking-tight">Nxpress</span>
5
+ <span
6
+ class="text-xs font-mono px-2 py-0.5 rounded-full bg-indigo-500/10 text-indigo-400 border border-indigo-500/20 font-medium">
7
+ v<%= version %>
8
+ </span>
9
+ </div>
10
+ <% if (!E.NODE_ENV || E.NODE_ENV.toLowerCase() !=='prod' ) { %>
11
+ <div class="flex items-center gap-2">
12
+ <span
13
+ class="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium bg-emerald-500/10 text-emerald-400 border border-emerald-500/20">
14
+ <span class="w-1.5 h-1.5 rounded-full bg-emerald-400 animate-pulse"></span>
15
+ Dev Server Active
16
+ </span>
17
+ </div>
18
+ <% } %>
19
+ </header>
20
+
21
+ <main class="py-16 md:py-24 text-center my-auto">
22
+ <div class="flex justify-center mb-6">
23
+ <img src="/logo.png" alt="Nxpress"
24
+ class="w-16 h-16 sm:w-20 sm:h-20 object-contain drop-shadow-[0_0_25px_rgba(99,102,241,0.5)] transition-transform hover:scale-105 duration-300" />
25
+ </div>
26
+
27
+ <h1
28
+ class="text-4xl sm:text-6xl md:text-7xl font-extrabold tracking-tight text-white mb-6 max-w-4xl mx-auto leading-[1.1]">
29
+ Build fast Node apps with
30
+ <span class="bg-linear-to-r from-indigo-400 via-sky-400 to-cyan-300 bg-clip-text text-transparent">
31
+ <%= title %>
32
+ </span>
33
+ </h1>
34
+
35
+ <p class="text-lg sm:text-xl text-slate-400 max-w-2xl mx-auto mb-10 leading-relaxed">
36
+ <%= description %>
37
+ </p>
38
+
39
+ <div class="max-w-xl mx-auto mb-16">
40
+ <div
41
+ class="group relative rounded-2xl bg-linear-to-b from-slate-800/80 to-slate-900/90 border border-slate-700/80 p-5 shadow-2xl backdrop-blur-md transition-all hover:border-indigo-500/40">
42
+ <div
43
+ class="flex items-center justify-between mb-3 text-xs text-slate-400 font-mono border-b border-slate-800 pb-3">
44
+ <div class="flex items-center gap-2">
45
+ <span class="w-3 h-3 rounded-full bg-rose-500/80 inline-block"></span>
46
+ <span class="w-3 h-3 rounded-full bg-amber-500/80 inline-block"></span>
47
+ <span class="w-3 h-3 rounded-full bg-emerald-500/80 inline-block"></span>
48
+ <span class="ml-2 text-slate-500">app/index.ejs</span>
49
+ </div>
50
+ <span class="text-indigo-400 font-sans text-[11px] font-semibold tracking-wide uppercase">Quick Start</span>
51
+ </div>
52
+ <div class="text-left font-mono text-sm py-2">
53
+ <p class="text-slate-300">
54
+ <span class="text-purple-400">Edit</span>
55
+ <span
56
+ class="text-emerald-300 px-1.5 py-0.5 rounded bg-slate-800 border border-slate-700">app/index.ejs</span>
57
+ <span class="text-slate-400">to customize this page.</span>
58
+ </p>
59
+ </div>
60
+ </div>
61
+ </div>
62
+
63
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4 max-w-4xl mx-auto text-left">
64
+ <% features.forEach(function(feat) { %>
65
+ <div
66
+ class="p-6 rounded-2xl bg-slate-900/50 border border-slate-800/80 hover:border-slate-700 transition-all duration-200 group">
67
+ <div class="flex items-center justify-between mb-3">
68
+ <span
69
+ class="text-xs font-semibold px-2.5 py-1 rounded-md bg-slate-800 text-indigo-400 border border-slate-700/50">
70
+ <%= feat.tag %>
71
+ </span>
72
+ <span class="text-slate-600 group-hover:text-slate-400 transition-colors text-sm">→</span>
73
+ </div>
74
+ <h3 class="text-base font-bold text-slate-100 mb-1.5 group-hover:text-indigo-300 transition-colors">
75
+ <%= feat.title %>
76
+ </h3>
77
+ <p class="text-sm text-slate-400 leading-relaxed">
78
+ <%= feat.desc %>
79
+ </p>
80
+ </div>
81
+ <% }); %>
82
+ </div>
83
+ </main>
84
+
85
+ <footer
86
+ class="py-6 border-t border-slate-800/60 text-center text-xs text-slate-500 flex flex-col sm:flex-row items-center justify-between gap-3">
87
+ <p>Powered by <span class="text-slate-300 font-medium">Nxpress</span></p>
88
+ <p class="font-mono text-slate-600">
89
+ <%= R.base %>
90
+ </p>
91
+ </footer>
92
+ </div>
@@ -0,0 +1,113 @@
1
+ <div class="min-h-screen flex flex-col justify-between max-w-6xl mx-auto px-6 py-8">
2
+ <!-- Top Navigation -->
3
+ <header class="flex items-center justify-between py-4 border-b border-slate-800/80">
4
+ <div class="flex items-center gap-3">
5
+ <span class="font-bold text-lg text-slate-100 tracking-tight">
6
+ Nxpress
7
+ </span>
8
+ <span
9
+ class="text-xs font-mono px-2 py-0.5 rounded-full bg-indigo-500/10 text-indigo-400 border border-indigo-500/20 font-medium">
10
+ v{{version}}
11
+ </span>
12
+ </div>
13
+ {{#if (ne (lower E.NODE_ENV) 'prod')}}
14
+ <div class="flex items-center gap-2">
15
+ <span
16
+ class="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium bg-emerald-500/10 text-emerald-400 border border-emerald-500/20">
17
+ <span class="w-1.5 h-1.5 rounded-full bg-emerald-400 animate-pulse"></span>
18
+ Dev Server Active
19
+ </span>
20
+ </div>
21
+ {{/if}}
22
+ </header>
23
+
24
+ <!-- Hero Section -->
25
+ <main class="py-16 md:py-24 text-center my-auto">
26
+ <div class="flex justify-center mb-6">
27
+ <img src="/logo.png" alt="Nxpress"
28
+ class="w-16 h-16 sm:w-20 sm:h-20 object-contain drop-shadow-[0_0_25px_rgba(99,102,241,0.5)] transition-transform hover:scale-105 duration-300" />
29
+ </div>
30
+ <h1
31
+ class="text-4xl sm:text-6xl md:text-7xl font-extrabold tracking-tight text-white mb-6 max-w-4xl mx-auto leading-[1.1]">
32
+ Build fast Node apps with
33
+ <span class="bg-linear-to-r from-indigo-400 via-sky-400 to-cyan-300 bg-clip-text text-transparent">
34
+ {{title}}
35
+ </span>
36
+ </h1>
37
+ <p class="text-lg sm:text-xl text-slate-400 max-w-2xl mx-auto mb-10 leading-relaxed">
38
+ {{description}}
39
+ </p>
40
+
41
+ <!-- Code Snippet Card -->
42
+ <div class="max-w-xl mx-auto mb-16">
43
+ <div
44
+ class="group relative rounded-2xl bg-linear-to-b from-slate-800/80 to-slate-900/90 border border-slate-700/80 p-5 shadow-2xl backdrop-blur-md transition-all hover:border-indigo-500/40">
45
+ <div
46
+ class="flex items-center justify-between mb-3 text-xs text-slate-400 font-mono border-b border-slate-800 pb-3">
47
+ <div class="flex items-center gap-2">
48
+ <span class="w-3 h-3 rounded-full bg-rose-500/80 inline-block"></span>
49
+ <span class="w-3 h-3 rounded-full bg-amber-500/80 inline-block"></span>
50
+ <span class="w-3 h-3 rounded-full bg-emerald-500/80 inline-block"></span>
51
+ <span class="ml-2 text-slate-500">
52
+ app/index.hbs
53
+ </span>
54
+ </div>
55
+ <span class="text-indigo-400 font-sans text-[11px] font-semibold tracking-wide uppercase">
56
+ Quick Start
57
+ </span>
58
+ </div>
59
+ <div class="text-left font-mono text-sm py-2">
60
+ <p class="text-slate-300">
61
+ <span class="text-purple-400">
62
+ Edit
63
+ </span>
64
+ <span class="text-emerald-300 px-1.5 py-0.5 rounded bg-slate-800 border border-slate-700">
65
+ app/index.hbs
66
+ </span>
67
+ <span class="text-slate-400">
68
+ to customize this page.
69
+ </span>
70
+ </p>
71
+ </div>
72
+ </div>
73
+ </div>
74
+
75
+ <!-- Feature Grid -->
76
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4 max-w-4xl mx-auto text-left">
77
+ {{#each features}}
78
+ <div
79
+ class="p-6 rounded-2xl bg-slate-900/50 border border-slate-800/80 hover:border-slate-700 transition-all duration-200 group">
80
+ <div class="flex items-center justify-between mb-3">
81
+ <span
82
+ class="text-xs font-semibold px-2.5 py-1 rounded-md bg-slate-800 text-indigo-400 border border-slate-700/50">
83
+ {{this.tag}}
84
+ </span>
85
+ <span class="text-slate-600 group-hover:text-slate-400 transition-colors text-sm">
86
+
87
+ </span>
88
+ </div>
89
+ <h3 class="text-base font-bold text-slate-100 mb-1.5 group-hover:text-indigo-300 transition-colors">
90
+ {{this.title}}
91
+ </h3>
92
+ <p class="text-sm text-slate-400 leading-relaxed">
93
+ {{this.desc}}
94
+ </p>
95
+ </div>
96
+ {{/each}}
97
+ </div>
98
+ </main>
99
+
100
+ <!-- Footer -->
101
+ <footer
102
+ class="py-6 border-t border-slate-800/60 text-center text-xs text-slate-500 flex flex-col sm:flex-row items-center justify-between gap-3">
103
+ <p>
104
+ Powered by
105
+ <span class="text-slate-300 font-medium">
106
+ Nxpress
107
+ </span>
108
+ </p>
109
+ <p class="font-mono text-slate-600">
110
+ {{R.base}}
111
+ </p>
112
+ </footer>
113
+ </div>
@@ -0,0 +1,76 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" class="dark h-full">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <meta name="description" content="Express.js speed with Next.js developer experience.">
8
+ <title>Nxpress App</title>
9
+ <link rel="preconnect" href="https://fonts.googleapis.com">
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
+ <link
12
+ href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap"
13
+ rel="stylesheet">
14
+ <link rel="stylesheet" href="/tailwind.css">
15
+ <style>
16
+ body {
17
+ font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
18
+ }
19
+
20
+ code,
21
+ pre {
22
+ font-family: 'JetBrains Mono', monospace;
23
+ }
24
+ </style>
25
+ </head>
26
+
27
+ <body
28
+ class="bg-[#0b0f19] text-slate-100 min-h-full antialiased selection:bg-indigo-500 selection:text-white relative overflow-x-hidden">
29
+ <div
30
+ class="pointer-events-none absolute top-0 left-1/2 -translate-x-1/2 w-full max-w-7xl h-125 bg-radial from-indigo-500/15 via-purple-500/5 to-transparent blur-3xl -z-10">
31
+ </div>
32
+ <div class="pointer-events-none absolute top-1/3 right-10 w-96 h-96 bg-blue-500/10 rounded-full blur-3xl -z-10"></div>
33
+
34
+ <!-- Content -->
35
+ <div class="min-h-screen flex flex-col justify-between max-w-6xl mx-auto px-6 py-8">
36
+ <header class="flex items-center justify-between py-4 border-b border-slate-800/80">
37
+ <div class="flex items-center gap-3">
38
+ <span class="font-bold text-lg text-slate-100 tracking-tight">Nxpress</span>
39
+ </div>
40
+ <div class="flex items-center gap-2">
41
+ <span
42
+ class="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium bg-emerald-500/10 text-emerald-400 border border-emerald-500/20">
43
+ <span class="w-1.5 h-1.5 rounded-full bg-emerald-400 animate-pulse"></span>
44
+ Dev Server Active
45
+ </span>
46
+ </div>
47
+ </header>
48
+
49
+ <main class="py-16 md:py-24 text-center my-auto">
50
+ <div class="flex justify-center mb-6">
51
+ <img src="/logo.png" alt="Nxpress"
52
+ class="w-16 h-16 sm:w-20 sm:h-20 object-contain drop-shadow-[0_0_25px_rgba(99,102,241,0.5)] transition-transform hover:scale-105 duration-300" />
53
+ </div>
54
+
55
+ <h1
56
+ class="text-4xl sm:text-6xl md:text-7xl font-extrabold tracking-tight text-white mb-6 max-w-4xl mx-auto leading-[1.1]">
57
+ Welcome to
58
+ <span class="bg-linear-to-r from-indigo-400 via-sky-400 to-cyan-300 bg-clip-text text-transparent">
59
+ Nxpress
60
+ </span>
61
+ </h1>
62
+
63
+ <p class="text-lg sm:text-xl text-slate-400 max-w-2xl mx-auto mb-10 leading-relaxed">
64
+ Express.js speed with Next.js developer experience.
65
+ </p>
66
+ </main>
67
+
68
+ <footer
69
+ class="py-6 border-t border-slate-800/60 text-center text-xs text-slate-500 flex flex-col sm:flex-row items-center justify-between gap-3">
70
+ <p>Powered by <span class="text-slate-300 font-medium">Nxpress</span></p>
71
+ </footer>
72
+ </div>
73
+
74
+ </body>
75
+
76
+ </html>
@@ -0,0 +1,38 @@
1
+ import type { Request, Response } from "express";
2
+
3
+ export async function props(req: Request, res: Response) {
4
+ let version = "1.0.8";
5
+ try {
6
+ const f = await fetch("https://registry.npmjs.org/@nxpress/core/latest");
7
+ version = (await f.json()).version;
8
+ } catch (err) {
9
+ console.error("Getting Nxpress version failed.", err);
10
+ }
11
+ return {
12
+ title: "Nxpress Framework",
13
+ version: version,
14
+ description: "Express.js speed with Next.js developer experience.",
15
+ features: [
16
+ {
17
+ title: "File-Based Routing",
18
+ desc: "Automatic route handling mapped to the app directory structure.",
19
+ tag: "Zero Config",
20
+ },
21
+ {
22
+ title: "Server Data Props",
23
+ desc: "Export props functions in route files for SSR data loading.",
24
+ tag: "SSR Ready",
25
+ },
26
+ {
27
+ title: "Tailwind CSS Integration",
28
+ desc: "Modern styling out of the box with zero boilerplate.",
29
+ tag: "Styling",
30
+ },
31
+ {
32
+ title: "Fast Handlebars Engine",
33
+ desc: "Dynamic server rendering with seamless layout templates.",
34
+ tag: "Templating",
35
+ },
36
+ ],
37
+ };
38
+ }
@@ -0,0 +1,39 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" class="dark h-full">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <meta name="description" content="<%= description %>">
8
+ <title>
9
+ <%= title %>
10
+ </title>
11
+ <link rel="preconnect" href="https://fonts.googleapis.com">
12
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
13
+ <link
14
+ href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap"
15
+ rel="stylesheet">
16
+ <link rel="stylesheet" href="/tailwind.css">
17
+ <style>
18
+ body {
19
+ font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
20
+ }
21
+
22
+ code,
23
+ pre {
24
+ font-family: 'JetBrains Mono', monospace;
25
+ }
26
+ </style>
27
+ </head>
28
+
29
+ <body
30
+ class="bg-[#0b0f19] text-slate-100 min-h-full antialiased selection:bg-indigo-500 selection:text-white relative overflow-x-hidden">
31
+ <div
32
+ class="pointer-events-none absolute top-0 left-1/2 -translate-x-1/2 w-full max-w-7xl h-125 bg-radial from-indigo-500/15 via-purple-500/5 to-transparent blur-3xl -z-10">
33
+ </div>
34
+ <div class="pointer-events-none absolute top-1/3 right-10 w-96 h-96 bg-blue-500/10 rounded-full blur-3xl -z-10"></div>
35
+
36
+ <%- body %>
37
+ </body>
38
+
39
+ </html>
@@ -0,0 +1,37 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" class="dark h-full">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <meta name="description" content="{{description}}">
8
+ <title>{{title}}</title>
9
+ <link rel="preconnect" href="https://fonts.googleapis.com">
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
+ <link
12
+ href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap"
13
+ rel="stylesheet">
14
+ <link rel="stylesheet" href="/tailwind.css">
15
+ <style>
16
+ body {
17
+ font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
18
+ }
19
+
20
+ code,
21
+ pre {
22
+ font-family: 'JetBrains Mono', monospace;
23
+ }
24
+ </style>
25
+ </head>
26
+
27
+ <body
28
+ class="bg-[#0b0f19] text-slate-100 min-h-full antialiased selection:bg-indigo-500 selection:text-white relative overflow-x-hidden">
29
+ <div
30
+ class="pointer-events-none absolute top-0 left-1/2 -translate-x-1/2 w-full max-w-7xl h-125 bg-radial from-indigo-500/15 via-purple-500/5 to-transparent blur-3xl -z-10">
31
+ </div>
32
+ <div class="pointer-events-none absolute top-1/3 right-10 w-96 h-96 bg-blue-500/10 rounded-full blur-3xl -z-10"></div>
33
+
34
+ {{{body}}}
35
+ </body>
36
+
37
+ </html>
@@ -0,0 +1,2 @@
1
+ @import "tailwindcss";
2
+ @tailwind utilities;
Binary file
@@ -0,0 +1,10 @@
1
+ import { nxpress } from '@nxpress/core';
2
+
3
+ const app = nxpress({
4
+ engine: '{{ENGINE}}',
5
+ });
6
+
7
+ const PORT = process.env.PORT || {{PORT}};
8
+ app.listen(PORT, () => {
9
+ console.log(`Nxpress server running on http://localhost:${PORT}`);
10
+ });