create-jen-app 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.
Files changed (27) hide show
  1. package/README.md +89 -0
  2. package/dist/index.js +72 -0
  3. package/package.json +44 -0
  4. package/templates/static/.esbuild/jen.config.js +2 -0
  5. package/templates/static/.esbuild/jen.config.js.map +7 -0
  6. package/templates/static/build.js +86 -0
  7. package/templates/static/dist/index.html +1 -0
  8. package/templates/static/dist/styles.css +1 -0
  9. package/templates/static/jen.config.ts +35 -0
  10. package/templates/static/jenjs.d.ts +15 -0
  11. package/templates/static/node_modules/.bin/esbuild +21 -0
  12. package/templates/static/node_modules/.bin/esbuild.CMD +12 -0
  13. package/templates/static/node_modules/.bin/esbuild.ps1 +41 -0
  14. package/templates/static/node_modules/.bin/tsc +21 -0
  15. package/templates/static/node_modules/.bin/tsc.CMD +12 -0
  16. package/templates/static/node_modules/.bin/tsc.ps1 +41 -0
  17. package/templates/static/node_modules/.bin/tsserver +21 -0
  18. package/templates/static/node_modules/.bin/tsserver.CMD +12 -0
  19. package/templates/static/node_modules/.bin/tsserver.ps1 +41 -0
  20. package/templates/static/node_modules/.jen/cache/C__Users_rejes_Documents_GitHub_Jen.js_packages_create-jen-app_templates_new-sass-compiler_site_(home).tsx.mjs +8 -0
  21. package/templates/static/node_modules/.jen/cache/C__Users_rejes_Documents_GitHub_Jen.js_packages_create-jen-app_templates_static_site_(home).tsx.mjs +8 -0
  22. package/templates/static/package.json +20 -0
  23. package/templates/static/server.js +108 -0
  24. package/templates/static/site/(home).esbuild.mjs +15 -0
  25. package/templates/static/site/(home).tsx +11 -0
  26. package/templates/static/site/(index).esbuild.mjs +14 -0
  27. package/templates/static/site/styles/global.scss +43 -0
package/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # create-jen-app
2
+
3
+ The fastest way to create a beautiful Jen.js application.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npm create jen-app my-app
9
+ cd my-app
10
+ npm run dev
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ npm create jen-app [project-name]
17
+ ```
18
+
19
+ ### Interactive Prompts
20
+
21
+ When you run the command, you'll be guided through:
22
+
23
+ 1. **Project Name** - What to call your project
24
+ 2. **Template Selection** - The CLI currently offers:
25
+ - **Static** - Pure SSG with components
26
+ 3. **TypeScript** - Enable TypeScript support (recommended)
27
+ 4. **Dependencies** - Install npm packages automatically
28
+ 5. **Git** - Initialize a git repository
29
+
30
+ ## Templates
31
+
32
+ ### Static Template
33
+ Perfect for marketing sites, blogs, and documentation.
34
+
35
+ - ⚡ Pure static site generation
36
+ - 📝 Component-based with Preact
37
+ - 🎨 Beautiful dark theme styles
38
+ - 🚀 Zero JavaScript overhead
39
+
40
+ ## Available Commands
41
+
42
+ All templates come with these npm scripts:
43
+
44
+ ```bash
45
+ npm run dev # Start development server (port 3000)
46
+ npm run build # Build for production
47
+ npm run start # Start production server
48
+ npm run typecheck # TypeScript type checking (if enabled)
49
+ ```
50
+
51
+ ## Features
52
+
53
+ - 🎨 **Beautiful Dark Theme** - Modern, colorful CLI with no white backgrounds
54
+ - 🚀 **Fast Setup** - Get started in seconds with template selection
55
+ - 📦 **Modern Stack** - Pre-configured and ready to use
56
+ - 🔧 **TypeScript Ready** - Full TypeScript support included
57
+ - 🌈 **Colorful Prompts** - Interactive, beautiful terminal experience
58
+
59
+ ## Project Structure
60
+
61
+ ### Static Template
62
+ ```
63
+ my-app/
64
+ ├── site/
65
+ │ ├── styles/ # SCSS styles
66
+ │ ├── components/ # Preact components
67
+ │ ├── routes/ # Page routes (file-based)
68
+ │ └── assets/ # Static assets
69
+ ├── dist/ # Build output
70
+ ├── jen.config.ts # Jen.js config
71
+ └── package.json
72
+ ```
73
+
74
+ ## Technologies
75
+
76
+ - [Jen.js](https://github.com/kessud2021/Jen.js) - Web framework
77
+ - [Preact](https://preactjs.com) - Lightweight React alternative
78
+ - [TypeScript](https://www.typescriptlang.org) - Type safety
79
+ - [SCSS](https://sass-lang.com) - Advanced styling
80
+
81
+ ## Documentation
82
+
83
+ - [Jen.js Docs](https://github.com/kessud2021/Jen.js)
84
+ - [Preact Guide](https://preactjs.com)
85
+ - [TypeScript Handbook](https://www.typescriptlang.org/docs)
86
+
87
+ ## License
88
+
89
+ MIT - See LICENSE in the Jen.js repository
package/dist/index.js ADDED
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env node
2
+ import d from"fs";import b from"path";import{fileURLToPath as D}from"url";import m from"prompts";var t={primary:e=>`\x1B[38;2;99;102;241m${e}\x1B[0m`,accent:e=>`\x1B[38;2;139;92;246m${e}\x1B[0m`,success:e=>`\x1B[38;2;34;197;94m${e}\x1B[0m`,warning:e=>`\x1B[38;2;251;146;60m${e}\x1B[0m`,error:e=>`\x1B[38;2;239;68;68m${e}\x1B[0m`,cyan:e=>`\x1B[38;2;34;211;238m${e}\x1B[0m`,magenta:e=>`\x1B[38;2;219;39;119m${e}\x1B[0m`,yellow:e=>`\x1B[38;2;250;204;21m${e}\x1B[0m`,bold:e=>`\x1B[1m${e}\x1B[0m`,dim:e=>`\x1B[2m${e}\x1B[0m`,italic:e=>`\x1B[3m${e}\x1B[0m`,underline:e=>`\x1B[4m${e}\x1B[0m`,bgDark:e=>`\x1B[48;2;23;23;23m${e}\x1B[0m`,bgPrimary:e=>`\x1B[48;2;99;102;241m${e}\x1B[0m`,reset:"\x1B[0m"},f={arrow:"\u2192",check:"\u2713",cross:"\u2715",dot:"\u2022",star:"\u2605",sparkles:"\u2728",rocket:"\u{1F680}",folder:"\u{1F4C1}",package:"\u{1F4E6}",code:"\u{1F4BB}"};function v(){let e=`
3
+ ${t.accent(t.bold(`
4
+ \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557
5
+ \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
6
+ \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D
7
+ \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u255D
8
+ \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551
9
+ \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D
10
+ `))}
11
+
12
+ ${t.primary(t.bold("Create a beautiful Jen.js application"))}
13
+ ${t.dim("v1.0.0")}
14
+ `;console.log(e)}function j(e){console.log(`
15
+ ${t.primary(t.bold(e))}`)}function g(e){console.log(`${t.success(f.check)} ${e}`)}function h(e){console.log(`${t.cyan("\u2139")} ${e}`)}function u(e,n,i){console.log(`${t.primary(`[${e}/${n}]`)} ${t.bold(i)}`)}function w(e){console.log(`
16
+ ${t.accent(t.bold("Next steps:"))}`),e.forEach((n,i)=>{console.log(` ${t.primary(i+1+".")} ${n}`)})}import r from"fs";import s from"path";function S(e,n){if(!r.existsSync(e))return;let i=r.readdirSync(e);for(let o of i){let c=s.join(e,o),a=s.join(n,o);r.statSync(c).isDirectory()?(r.mkdirSync(a,{recursive:!0}),S(c,a)):r.copyFileSync(c,a)}}function k(e,n){let i={},o=s.join(e,"package.json");if(r.existsSync(o)){let p=r.readFileSync(o,"utf-8");i=JSON.parse(p)}let c={...i,name:n.projectName.toLowerCase().replace(/\s+/g,"-"),version:"0.1.0",type:"module",scripts:{...i.scripts,dev:"jen dev",build:"jen build",start:"jen start",...n.typescript&&{typecheck:"tsc --noEmit"}},dependencies:{...i.dependencies,"@jenjs/master":"^1.2.5"},devDependencies:{...i.devDependencies,...n.typescript&&{"@types/node":"^22.10.0",typescript:"^5.7.2"}}};if(r.writeFileSync(s.join(e,"package.json"),JSON.stringify(c,null,2)),n.typescript){let p={compilerOptions:{target:"ES2022",module:"ESNext",moduleResolution:"node",strict:!0,jsx:"react-jsx",jsxImportSource:"preact",lib:["ES2022","DOM","DOM.Iterable"],skipLibCheck:!0,forceConsistentCasingInFileNames:!0,resolveJsonModule:!0,allowImportingTsExtensions:!0},include:["site/**/*"],exclude:["node_modules","dist"]};r.writeFileSync(s.join(e,"tsconfig.json"),JSON.stringify(p,null,2))}let a=`# ${n.projectName}
17
+
18
+ A beautiful Jen.js application.
19
+
20
+ ## Getting Started
21
+
22
+ \`\`\`bash
23
+ npm install
24
+ npm run dev
25
+ \`\`\`
26
+
27
+ ## Available Commands
28
+
29
+ - \`npm run dev\` - Start development server (http://localhost:3000)
30
+ - \`npm run build\` - Build for production
31
+ - \`npm run start\` - Start production server
32
+ ${n.typescript?"- `npm run typecheck` - Check TypeScript types\n":""}
33
+
34
+ ## Project Structure
35
+
36
+ \`\`\`
37
+ src/
38
+ \u251C\u2500\u2500 styles/ # Global styles
39
+ \u251C\u2500\u2500 components/ # Preact components
40
+ \u2514\u2500\u2500 routes/ # Page routes
41
+ dist/ # Build output
42
+ jen.config.ts # Jen.js configuration
43
+ \`\`\`
44
+
45
+ ## Learn More
46
+
47
+ - [Jen.js Documentation](https://github.com/kessud2021/Jen.js)
48
+ - [Preact Documentation](https://preactjs.com)
49
+
50
+ ## License
51
+
52
+ MIT
53
+ `;r.writeFileSync(s.join(e,"README.md"),a),r.writeFileSync(s.join(e,".env.example"),`# Database
54
+ DATABASE_URL=
55
+
56
+ # API
57
+ API_SECRET=
58
+
59
+ # Environment
60
+ NODE_ENV=development
61
+ `);let y=["site/styles","site/components","site/routes","site/assets"];for(let p of y)r.mkdirSync(s.join(e,p),{recursive:!0})}var I=b.dirname(D(import.meta.url));async function P(){v();let e=process.argv[2];e||(e=(await m({type:"text",name:"projectName",message:"Project name",initial:"my-jen-app",validate:$=>$?/^[a-zA-Z0-9._-]+$/.test($)?!0:"Project name can only contain alphanumeric characters, dots, dashes and underscores":"Project name is required"})).projectName);let n=b.resolve(process.cwd(),e);d.existsSync(n)&&((await m({type:"confirm",name:"overwrite",message:`${t.warning(e)} already exists. Overwrite?`,initial:!1})).overwrite||(console.log(`${t.dim("Cancelled")}`),process.exit(0)),d.rmSync(n,{recursive:!0})),j(`${f.sparkles} Configuring your project`);let i=await m({type:"select",name:"template",message:"Select a template",choices:[{title:`${t.accent("Static")} - Pure SSG with components`,value:"static",description:"Fast, lightweight static sites"}]}),o=await m({type:"confirm",name:"typescript",message:"Use TypeScript?",initial:!0}),c=await m({type:"confirm",name:"installDeps",message:"Install dependencies?",initial:!0}),a=await m({type:"confirm",name:"gitInit",message:"Initialize git repository?",initial:!0}),l={projectName:e,template:i.template,typescript:o.typescript,installDeps:c.installDeps,gitInit:a.gitInit};j(`${f.rocket} Creating project`),u(1,4,"Setting up directories"),d.mkdirSync(n,{recursive:!0}),g("Directories created"),u(2,4,"Copying template files");let y=b.join(I,"..","templates",l.template);if(d.existsSync(y)&&S(y,n),g("Template files copied"),u(3,4,"Generating configuration files"),k(n,l),g("Configuration files generated"),l.gitInit){u(4,4,"Initializing git repository");try{let{execSync:x}=await import("child_process");x("git init",{cwd:n,stdio:"pipe"}),d.writeFileSync(b.join(n,".gitignore"),`node_modules/
62
+ dist/
63
+ .jen/
64
+ .env
65
+ .env.local
66
+ .DS_Store
67
+ *.log
68
+ `),g("Git repository initialized")}catch{h("Git initialization skipped")}}console.log(`
69
+ ${t.accent(t.bold("\u2728 Your Jen.js app is ready!"))}`);let p=[`${t.cyan(`cd ${e}`)}`,l.installDeps?`${t.cyan("npm run dev")} ${t.dim("to start development server")}`:`${t.cyan("npm install")} then ${t.cyan("npm run dev")}`];w(p),console.log(`
70
+ ${t.dim("Happy coding! \u{1F389}")}
71
+ `)}P().catch(e=>{console.error(`
72
+ \u274C Error:`,e.message),process.exit(1)});
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "create-jen-app",
3
+ "version": "1.0.0",
4
+ "description": "Create a beautiful Jen.js application with a single command",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-jen-app": "./dist/index.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "files": [
11
+ "dist",
12
+ "templates"
13
+ ],
14
+ "scripts": {
15
+ "build": "esbuild src/index.ts --minify --bundle --platform=node --target=es2022 --format=esm --external:prompts --external:child_process --outfile=dist/index.js && chmod +x dist/index.js",
16
+ "dev": "tsx src/index.ts"
17
+ },
18
+ "keywords": [
19
+ "jen",
20
+ "jenjs",
21
+ "create",
22
+ "cli",
23
+ "scaffold",
24
+ "boilerplate"
25
+ ],
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/kessud2021/Jen.js.git"
29
+ },
30
+ "bugs": {
31
+ "url": "https://github.com/kessud2021/Jen.js/issues"
32
+ },
33
+ "homepage": "https://github.com/kessud2021/Jen.js#readme",
34
+ "license": "GPL-3.0-only",
35
+ "dependencies": {
36
+ "prompts": "^2.4.2"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^22.10.0",
40
+ "esbuild": "^0.25.0",
41
+ "tsx": "^4.7.0",
42
+ "typescript": "^5.7.2"
43
+ }
44
+ }
@@ -0,0 +1,2 @@
1
+ var e={siteDir:"site",distDir:"dist",routes:{fileExtensions:[".tsx",".jsx",".ts",".js"],routeFilePattern:/^\(([^)]+)\)\.(tsx|jsx|ts|js)$/,enableIndexFallback:!0},rendering:{defaultMode:"ssg",defaultRevalidateSeconds:0},inject:{head:[],bodyEnd:[]},css:{globalScss:"site/styles/global.scss"},assets:{publicDir:"site/assets",cacheControl:"public, max-age=3600"},server:{port:3001,hostname:"localhost"},dev:{liveReload:!0}},s=e;export{s as default};
2
+ //# sourceMappingURL=jen.config.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../jen.config.ts"],
4
+ "sourcesContent": ["import type { FrameworkConfig } from \"@jenjs/master\";\n\nconst config: FrameworkConfig = {\n siteDir: \"site\",\n distDir: \"dist\",\n routes: {\n fileExtensions: [\".tsx\", \".jsx\", \".ts\", \".js\"],\n routeFilePattern: /^\\(([^)]+)\\)\\.(tsx|jsx|ts|js)$/,\n enableIndexFallback: true\n },\n rendering: {\n defaultMode: \"ssg\",\n defaultRevalidateSeconds: 0\n },\n inject: {\n head: [],\n bodyEnd: []\n },\n css: {\n globalScss: \"site/styles/global.scss\"\n },\n assets: {\n publicDir: \"site/assets\",\n cacheControl: \"public, max-age=3600\"\n },\n server: {\n port: 3001,\n hostname: \"localhost\"\n },\n dev: {\n liveReload: true\n }\n};\n\nexport default config;\n"],
5
+ "mappings": "AAEA,IAAMA,EAA0B,CAC9B,QAAS,OACT,QAAS,OACT,OAAQ,CACN,eAAgB,CAAC,OAAQ,OAAQ,MAAO,KAAK,EAC7C,iBAAkB,iCAClB,oBAAqB,EACvB,EACA,UAAW,CACT,YAAa,MACb,yBAA0B,CAC5B,EACA,OAAQ,CACN,KAAM,CAAC,EACP,QAAS,CAAC,CACZ,EACA,IAAK,CACH,WAAY,yBACd,EACA,OAAQ,CACN,UAAW,cACX,aAAc,sBAChB,EACA,OAAQ,CACN,KAAM,KACN,SAAU,WACZ,EACA,IAAK,CACH,WAAY,EACd,CACF,EAEOC,EAAQD",
6
+ "names": ["config", "jen_config_default"]
7
+ }
@@ -0,0 +1,86 @@
1
+ import { dirname, join } from "node:path";
2
+ import { fileURLToPath, pathToFileURL } from "node:url";
3
+ import { readdir, stat, readFile, writeFile } from "node:fs/promises";
4
+ import esbuild from "esbuild";
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const currentDir = dirname(__filename);
8
+ const rootDir = join(currentDir, "../../../..");
9
+
10
+ // Embedded Minifier Logic
11
+ const Minifier = {
12
+ html(input) {
13
+ return input
14
+ .replace(/<!--[\s\S]*?-->/g, "")
15
+ .replace(/>\s+</g, "><")
16
+ .replace(/\s+/g, " ")
17
+ .replace(/\s*([{};:,=])\s*/g, "$1")
18
+ .trim();
19
+ },
20
+ css(input) {
21
+ return input
22
+ .replace(/\/\*[\s\S]*?\*\//g, "")
23
+ .replace(/\/\/.*/g, "")
24
+ .replace(/\s*([{}:;,])\s*/g, "$1")
25
+ .replace(/\s+/g, " ")
26
+ .replace(/;\s*}/g, "}")
27
+ .trim();
28
+ }
29
+ };
30
+
31
+ async function main() {
32
+ console.log("[BUILD] Starting build...");
33
+
34
+ const configPath = join(currentDir, "jen.config.ts");
35
+ const outdir = join(currentDir, ".esbuild");
36
+
37
+ await esbuild.build({
38
+ entryPoints: [configPath],
39
+ outdir,
40
+ format: "esm",
41
+ platform: "node",
42
+ target: "es2022",
43
+ bundle: true,
44
+ minify: true,
45
+ sourcemap: true,
46
+ loader: { ".ts": "ts" },
47
+ logLevel: "silent"
48
+ });
49
+
50
+ const configFile = join(outdir, "jen.config.js");
51
+ const config = (await import(pathToFileURL(configFile).href)).default;
52
+
53
+ const buildPath = pathToFileURL(join(rootDir, "build/src/build/build.js")).href;
54
+ const { buildSite } = await import(buildPath);
55
+
56
+ await buildSite({ config });
57
+
58
+ console.log("[BUILD] Minifying output...");
59
+
60
+ async function minifyDir(dir) {
61
+ try {
62
+ const files = await readdir(dir);
63
+ for (const file of files) {
64
+ const path = join(dir, file);
65
+ const s = await stat(path);
66
+ if (s.isDirectory()) {
67
+ await minifyDir(path);
68
+ } else if (file.endsWith(".html")) {
69
+ const content = await readFile(path, "utf-8");
70
+ await writeFile(path, Minifier.html(content));
71
+ } else if (file.endsWith(".css")) {
72
+ const content = await readFile(path, "utf-8");
73
+ await writeFile(path, Minifier.css(content));
74
+ }
75
+ }
76
+ } catch (e) {
77
+ if (e.code !== 'ENOENT') console.warn("Minification warning:", e.message);
78
+ }
79
+ }
80
+
81
+ await minifyDir(join(currentDir, config.distDir || "dist"));
82
+
83
+ console.log("✅ Site built successfully!");
84
+ }
85
+
86
+ main().catch(console.error);
@@ -0,0 +1 @@
1
+ <!doctype html><html><head><link rel="stylesheet" href="/styles.css"></head><body><div id="app"><div class="container"><h1>Jen.js</h1><p>Edit site/(home).tsx to change this page.</p></div></div><script id="__FRAMEWORK_DATA__" type="application/json">{"data":null,"params":{},"query":{}}</script><script type="module"> import{hydrateClient}from "/__runtime/hydrate.js";hydrateClient("/__hydrate?id=route_index");</script></body></html>
@@ -0,0 +1 @@
1
+ body{background-color:#f8fafc;color:#1e293b;font-family:system-ui,sans-serif;margin:0;display:flex;justify-content:center;align-items:center;min-height:100vh}.container{max-width:600px;padding:2rem;text-align:center}.container h1{color:#2563eb;font-size:3rem;margin-bottom:1rem}.container .card{background:#fff;border-radius:.5rem;padding:1.5rem;box-shadow:0 4px 6px -1px rgba(0,0,0,.1);margin-top:2rem}.container .card h2{margin-top:0;color:rgb(18.5714285714,76.1428571429,202.4285714286)}.container .card p{color:rgb(64.3820224719,87.9887640449,126.6179775281)}
@@ -0,0 +1,35 @@
1
+ import type { FrameworkConfig } from "@jenjs/master";
2
+
3
+ const config: FrameworkConfig = {
4
+ siteDir: "site",
5
+ distDir: "dist",
6
+ routes: {
7
+ fileExtensions: [".tsx", ".jsx", ".ts", ".js"],
8
+ routeFilePattern: /^\(([^)]+)\)\.(tsx|jsx|ts|js)$/,
9
+ enableIndexFallback: true
10
+ },
11
+ rendering: {
12
+ defaultMode: "ssg",
13
+ defaultRevalidateSeconds: 0
14
+ },
15
+ inject: {
16
+ head: [],
17
+ bodyEnd: []
18
+ },
19
+ css: {
20
+ globalScss: "site/styles/global.scss"
21
+ },
22
+ assets: {
23
+ publicDir: "site/assets",
24
+ cacheControl: "public, max-age=3600"
25
+ },
26
+ server: {
27
+ port: 3001,
28
+ hostname: "localhost"
29
+ },
30
+ dev: {
31
+ liveReload: true
32
+ }
33
+ };
34
+
35
+ export default config;
@@ -0,0 +1,15 @@
1
+ declare module "@jenjs/master" {
2
+ export * from "@jenjs/master";
3
+ }
4
+
5
+ declare module "@jenjs/master/config" {
6
+ export * from "@jenjs/master/config";
7
+ }
8
+
9
+ declare module "@jenjs/master/compile" {
10
+ export * from "@jenjs/master/compile";
11
+ }
12
+
13
+ declare module "@jenjs/master/render" {
14
+ export * from "@jenjs/master/render";
15
+ }
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/esbuild@0.25.12/node_modules/esbuild/bin/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/esbuild@0.25.12/node_modules/esbuild/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/esbuild@0.25.12/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/esbuild@0.25.12/node_modules/esbuild/bin/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/esbuild@0.25.12/node_modules/esbuild/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/esbuild@0.25.12/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../../../../../../node_modules/.pnpm/esbuild@0.25.12/node_modules/esbuild/bin/esbuild" "$@"
19
+ else
20
+ exec node "$basedir/../../../../../../node_modules/.pnpm/esbuild@0.25.12/node_modules/esbuild/bin/esbuild" "$@"
21
+ fi
@@ -0,0 +1,12 @@
1
+ @SETLOCAL
2
+ @IF NOT DEFINED NODE_PATH (
3
+ @SET "NODE_PATH=C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\esbuild@0.25.12\node_modules\esbuild\bin\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\esbuild@0.25.12\node_modules\esbuild\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\esbuild@0.25.12\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\node_modules"
4
+ ) ELSE (
5
+ @SET "NODE_PATH=C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\esbuild@0.25.12\node_modules\esbuild\bin\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\esbuild@0.25.12\node_modules\esbuild\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\esbuild@0.25.12\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\node_modules;%NODE_PATH%"
6
+ )
7
+ @IF EXIST "%~dp0\node.exe" (
8
+ "%~dp0\node.exe" "%~dp0\..\..\..\..\..\..\node_modules\.pnpm\esbuild@0.25.12\node_modules\esbuild\bin\esbuild" %*
9
+ ) ELSE (
10
+ @SET PATHEXT=%PATHEXT:;.JS;=;%
11
+ node "%~dp0\..\..\..\..\..\..\node_modules\.pnpm\esbuild@0.25.12\node_modules\esbuild\bin\esbuild" %*
12
+ )
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env pwsh
2
+ $basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
3
+
4
+ $exe=""
5
+ $pathsep=":"
6
+ $env_node_path=$env:NODE_PATH
7
+ $new_node_path="C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\esbuild@0.25.12\node_modules\esbuild\bin\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\esbuild@0.25.12\node_modules\esbuild\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\esbuild@0.25.12\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\node_modules"
8
+ if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
9
+ # Fix case when both the Windows and Linux builds of Node
10
+ # are installed in the same directory
11
+ $exe=".exe"
12
+ $pathsep=";"
13
+ } else {
14
+ $new_node_path="/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/esbuild@0.25.12/node_modules/esbuild/bin/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/esbuild@0.25.12/node_modules/esbuild/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/esbuild@0.25.12/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/node_modules"
15
+ }
16
+ if ([string]::IsNullOrEmpty($env_node_path)) {
17
+ $env:NODE_PATH=$new_node_path
18
+ } else {
19
+ $env:NODE_PATH="$new_node_path$pathsep$env_node_path"
20
+ }
21
+
22
+ $ret=0
23
+ if (Test-Path "$basedir/node$exe") {
24
+ # Support pipeline input
25
+ if ($MyInvocation.ExpectingInput) {
26
+ $input | & "$basedir/node$exe" "$basedir/../../../../../../node_modules/.pnpm/esbuild@0.25.12/node_modules/esbuild/bin/esbuild" $args
27
+ } else {
28
+ & "$basedir/node$exe" "$basedir/../../../../../../node_modules/.pnpm/esbuild@0.25.12/node_modules/esbuild/bin/esbuild" $args
29
+ }
30
+ $ret=$LASTEXITCODE
31
+ } else {
32
+ # Support pipeline input
33
+ if ($MyInvocation.ExpectingInput) {
34
+ $input | & "node$exe" "$basedir/../../../../../../node_modules/.pnpm/esbuild@0.25.12/node_modules/esbuild/bin/esbuild" $args
35
+ } else {
36
+ & "node$exe" "$basedir/../../../../../../node_modules/.pnpm/esbuild@0.25.12/node_modules/esbuild/bin/esbuild" $args
37
+ }
38
+ $ret=$LASTEXITCODE
39
+ }
40
+ $env:NODE_PATH=$env_node_path
41
+ exit $ret
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsc" "$@"
19
+ else
20
+ exec node "$basedir/../../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsc" "$@"
21
+ fi
@@ -0,0 +1,12 @@
1
+ @SETLOCAL
2
+ @IF NOT DEFINED NODE_PATH (
3
+ @SET "NODE_PATH=C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\bin\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\node_modules"
4
+ ) ELSE (
5
+ @SET "NODE_PATH=C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\bin\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\node_modules;%NODE_PATH%"
6
+ )
7
+ @IF EXIST "%~dp0\node.exe" (
8
+ "%~dp0\node.exe" "%~dp0\..\..\..\..\..\..\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\bin\tsc" %*
9
+ ) ELSE (
10
+ @SET PATHEXT=%PATHEXT:;.JS;=;%
11
+ node "%~dp0\..\..\..\..\..\..\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\bin\tsc" %*
12
+ )
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env pwsh
2
+ $basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
3
+
4
+ $exe=""
5
+ $pathsep=":"
6
+ $env_node_path=$env:NODE_PATH
7
+ $new_node_path="C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\bin\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\node_modules"
8
+ if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
9
+ # Fix case when both the Windows and Linux builds of Node
10
+ # are installed in the same directory
11
+ $exe=".exe"
12
+ $pathsep=";"
13
+ } else {
14
+ $new_node_path="/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/node_modules"
15
+ }
16
+ if ([string]::IsNullOrEmpty($env_node_path)) {
17
+ $env:NODE_PATH=$new_node_path
18
+ } else {
19
+ $env:NODE_PATH="$new_node_path$pathsep$env_node_path"
20
+ }
21
+
22
+ $ret=0
23
+ if (Test-Path "$basedir/node$exe") {
24
+ # Support pipeline input
25
+ if ($MyInvocation.ExpectingInput) {
26
+ $input | & "$basedir/node$exe" "$basedir/../../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsc" $args
27
+ } else {
28
+ & "$basedir/node$exe" "$basedir/../../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsc" $args
29
+ }
30
+ $ret=$LASTEXITCODE
31
+ } else {
32
+ # Support pipeline input
33
+ if ($MyInvocation.ExpectingInput) {
34
+ $input | & "node$exe" "$basedir/../../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsc" $args
35
+ } else {
36
+ & "node$exe" "$basedir/../../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsc" $args
37
+ }
38
+ $ret=$LASTEXITCODE
39
+ }
40
+ $env:NODE_PATH=$env_node_path
41
+ exit $ret
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsserver" "$@"
19
+ else
20
+ exec node "$basedir/../../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsserver" "$@"
21
+ fi
@@ -0,0 +1,12 @@
1
+ @SETLOCAL
2
+ @IF NOT DEFINED NODE_PATH (
3
+ @SET "NODE_PATH=C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\bin\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\node_modules"
4
+ ) ELSE (
5
+ @SET "NODE_PATH=C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\bin\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\node_modules;%NODE_PATH%"
6
+ )
7
+ @IF EXIST "%~dp0\node.exe" (
8
+ "%~dp0\node.exe" "%~dp0\..\..\..\..\..\..\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\bin\tsserver" %*
9
+ ) ELSE (
10
+ @SET PATHEXT=%PATHEXT:;.JS;=;%
11
+ node "%~dp0\..\..\..\..\..\..\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\bin\tsserver" %*
12
+ )
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env pwsh
2
+ $basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
3
+
4
+ $exe=""
5
+ $pathsep=":"
6
+ $env_node_path=$env:NODE_PATH
7
+ $new_node_path="C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\bin\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\typescript@5.9.3\node_modules;C:\Users\rejes\Documents\GitHub\Jen.js\node_modules\.pnpm\node_modules"
8
+ if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
9
+ # Fix case when both the Windows and Linux builds of Node
10
+ # are installed in the same directory
11
+ $exe=".exe"
12
+ $pathsep=";"
13
+ } else {
14
+ $new_node_path="/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/typescript@5.9.3/node_modules:/mnt/c/Users/rejes/Documents/GitHub/Jen.js/node_modules/.pnpm/node_modules"
15
+ }
16
+ if ([string]::IsNullOrEmpty($env_node_path)) {
17
+ $env:NODE_PATH=$new_node_path
18
+ } else {
19
+ $env:NODE_PATH="$new_node_path$pathsep$env_node_path"
20
+ }
21
+
22
+ $ret=0
23
+ if (Test-Path "$basedir/node$exe") {
24
+ # Support pipeline input
25
+ if ($MyInvocation.ExpectingInput) {
26
+ $input | & "$basedir/node$exe" "$basedir/../../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsserver" $args
27
+ } else {
28
+ & "$basedir/node$exe" "$basedir/../../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsserver" $args
29
+ }
30
+ $ret=$LASTEXITCODE
31
+ } else {
32
+ # Support pipeline input
33
+ if ($MyInvocation.ExpectingInput) {
34
+ $input | & "node$exe" "$basedir/../../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsserver" $args
35
+ } else {
36
+ & "node$exe" "$basedir/../../../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsserver" $args
37
+ }
38
+ $ret=$LASTEXITCODE
39
+ }
40
+ $env:NODE_PATH=$env_node_path
41
+ exit $ret
@@ -0,0 +1,8 @@
1
+ // site/(home).tsx
2
+ import { h } from "preact";
3
+ function Index() {
4
+ return /* @__PURE__ */ h("div", { className: "container" }, /* @__PURE__ */ h("h1", null, "Jen.js"), /* @__PURE__ */ h("p", null, "Edit site/(home).tsx to change this page."));
5
+ }
6
+ export {
7
+ Index as default
8
+ };
@@ -0,0 +1,8 @@
1
+ // site/(home).tsx
2
+ import { h } from "preact";
3
+ function Index() {
4
+ return /* @__PURE__ */ h("div", { className: "container" }, /* @__PURE__ */ h("h1", null, "Jen.js"), /* @__PURE__ */ h("p", null, "Edit site/(home).tsx to change this page."));
5
+ }
6
+ export {
7
+ Index as default
8
+ };
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "new-sass-compiler-example",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "node server.js dev",
7
+ "build": "node build.js"
8
+ },
9
+ "dependencies": {
10
+ "@jenjs/master": "^1.2.5",
11
+ "esbuild": "^0.25.0",
12
+ "preact": "^10.25.4",
13
+ "preact-render-to-string": "^6.5.13",
14
+ "sirv": "^3.0.1"
15
+ },
16
+ "devDependencies": {
17
+ "@types/node": "^22.10.0",
18
+ "typescript": "^5.7.2"
19
+ }
20
+ }
@@ -0,0 +1,108 @@
1
+ import { createServer } from "node:http";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath, pathToFileURL } from "node:url";
4
+ import esbuild from "esbuild";
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const currentDir = dirname(__filename);
8
+ const rootDir = join(currentDir, "../../../..");
9
+
10
+ const mode = process.argv[2] ?? "dev";
11
+ const isDev = mode === "dev";
12
+
13
+ // Embedded Minifier Logic
14
+ const Minifier = {
15
+ html(input) {
16
+ return input
17
+ .replace(/<!--[\s\S]*?-->/g, "")
18
+ .replace(/>\s+</g, "><")
19
+ .replace(/\s+/g, " ")
20
+ .replace(/\s*([{};:,=])\s*/g, "$1")
21
+ .trim();
22
+ },
23
+ css(input) {
24
+ return input
25
+ .replace(/\/\*[\s\S]*?\*\//g, "")
26
+ .replace(/\/\/.*/g, "")
27
+ .replace(/\s*([{}:;,])\s*/g, "$1")
28
+ .replace(/\s+/g, " ")
29
+ .replace(/;\s*}/g, "}")
30
+ .trim();
31
+ }
32
+ };
33
+
34
+ async function main() {
35
+ console.log(`[SERVER] Starting in ${isDev ? "DEV" : "PROD"} mode...`);
36
+
37
+ const configPath = join(currentDir, "jen.config.ts");
38
+ const outdir = join(currentDir, ".esbuild");
39
+
40
+ await esbuild.build({
41
+ entryPoints: [configPath],
42
+ outdir,
43
+ format: "esm",
44
+ platform: "node",
45
+ target: "es2022",
46
+ minify: true,
47
+ bundle: true,
48
+ loader: { ".ts": "ts" },
49
+ logLevel: "silent"
50
+ });
51
+
52
+ const configFile = join(outdir, "jen.config.js");
53
+ const config = (await import(pathToFileURL(configFile).href)).default;
54
+
55
+ const appPath = pathToFileURL(join(rootDir, "build/src/server/app.js")).href;
56
+ const { createApp } = await import(appPath);
57
+
58
+ // Load banner
59
+ const bannerPath = pathToFileURL(join(rootDir, "build/src/cli/banner.js")).href;
60
+ const { printBanner } = await import(bannerPath);
61
+
62
+ const app = await createApp({
63
+ config,
64
+ mode: isDev ? "dev" : "prod"
65
+ });
66
+
67
+ const server = createServer(async (req, res) => {
68
+ // Intercept response to minify
69
+ const originalEnd = res.end;
70
+ res.end = function(chunk, encoding, callback) {
71
+ if (chunk) {
72
+ const type = res.getHeader("content-type");
73
+ if (typeof type === "string") {
74
+ if (type.includes("text/html")) {
75
+ try {
76
+ chunk = Minifier.html(chunk.toString());
77
+ res.removeHeader("content-length");
78
+ } catch (e) {
79
+ console.error("HTML Minification failed:", e);
80
+ }
81
+ } else if (type.includes("text/css")) {
82
+ try {
83
+ chunk = Minifier.css(chunk.toString());
84
+ res.removeHeader("content-length");
85
+ } catch (e) {
86
+ console.error("CSS Minification failed:", e);
87
+ }
88
+ }
89
+ }
90
+ }
91
+ return originalEnd.call(this, chunk, encoding, callback);
92
+ };
93
+
94
+ try {
95
+ await app.handle(req, res);
96
+ } catch (err) {
97
+ res.statusCode = 500;
98
+ res.setHeader("content-type", "text/plain; charset=utf-8");
99
+ res.end("Internal Server Error\n\n" + (err?.stack ?? String(err)));
100
+ }
101
+ });
102
+
103
+ server.listen(config.server.port, config.server.hostname, () => {
104
+ printBanner(config.server.port, isDev ? "development" : "production");
105
+ });
106
+ }
107
+
108
+ main().catch(console.error);
@@ -0,0 +1,15 @@
1
+ import { jsx, jsxs } from "preact/jsx-runtime";
2
+ function Index() {
3
+ return /* @__PURE__ */ jsxs("div", { className: "container", children: [
4
+ /* @__PURE__ */ jsx("h1", { children: "Jen.js + SCSS" }),
5
+ /* @__PURE__ */ jsx("p", { children: "bruh" }),
6
+ /* @__PURE__ */ jsx("p", { children: "This page is styled using a real SCSS compiler!" }),
7
+ /* @__PURE__ */ jsxs("div", { className: "card", children: [
8
+ /* @__PURE__ */ jsx("h2", { children: "Nested Rules" }),
9
+ /* @__PURE__ */ jsx("p", { children: "I am inside a card with a border and padding." })
10
+ ] })
11
+ ] });
12
+ }
13
+ export {
14
+ Index as default
15
+ };
@@ -0,0 +1,11 @@
1
+ /** @jsx h */
2
+ import { h } from "preact";
3
+
4
+ export default function Index() {
5
+ return (
6
+ <div className="container">
7
+ <h1>Jen.js</h1>
8
+ <p>Edit site/(home).tsx to change this page.</p>
9
+ </div>
10
+ );
11
+ }
@@ -0,0 +1,14 @@
1
+ import { jsx, jsxs } from "preact/jsx-runtime";
2
+ function Index() {
3
+ return /* @__PURE__ */ jsxs("div", { className: "container", children: [
4
+ /* @__PURE__ */ jsx("h1", { children: "Jen.js + SCSS" }),
5
+ /* @__PURE__ */ jsx("p", { children: "This page is styled using a real SCSS compiler!" }),
6
+ /* @__PURE__ */ jsxs("div", { className: "card", children: [
7
+ /* @__PURE__ */ jsx("h2", { children: "Nested Rules" }),
8
+ /* @__PURE__ */ jsx("p", { children: "I am inside a card with a border and padding." })
9
+ ] })
10
+ ] });
11
+ }
12
+ export {
13
+ Index as default
14
+ };
@@ -0,0 +1,43 @@
1
+ $primary: #2563eb;
2
+ $bg: #f8fafc;
3
+ $text: #1e293b;
4
+
5
+ body {
6
+ background-color: $bg;
7
+ color: $text;
8
+ font-family: system-ui, sans-serif;
9
+ margin: 0;
10
+ display: flex;
11
+ justify-content: center;
12
+ align-items: center;
13
+ min-height: 100vh;
14
+ }
15
+
16
+ .container {
17
+ max-width: 600px;
18
+ padding: 2rem;
19
+ text-align: center;
20
+
21
+ h1 {
22
+ color: $primary;
23
+ font-size: 3rem;
24
+ margin-bottom: 1rem;
25
+ }
26
+
27
+ .card {
28
+ background: white;
29
+ border-radius: 0.5rem;
30
+ padding: 1.5rem;
31
+ box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
32
+ margin-top: 2rem;
33
+
34
+ h2 {
35
+ margin-top: 0;
36
+ color: darken($primary, 10%);
37
+ }
38
+
39
+ p {
40
+ color: lighten($text, 20%);
41
+ }
42
+ }
43
+ }