create-ereo 0.2.6 → 0.2.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.
Files changed (3) hide show
  1. package/README.md +4 -0
  2. package/dist/index.js +88 -57
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -81,6 +81,7 @@ bunx create-ereo@latest my-app --template minimal
81
81
  | `--no-typescript` | | Use JavaScript instead of TypeScript |
82
82
  | `--no-git` | | Skip git initialization |
83
83
  | `--no-install` | | Skip package installation |
84
+ | `--trace` | | Include @ereo/trace for full-stack observability |
84
85
  | `--help` | `-h` | Show help message |
85
86
 
86
87
  ## Examples
@@ -97,6 +98,9 @@ bunx create-ereo@latest my-app --no-install
97
98
 
98
99
  # Create without git initialization
99
100
  bunx create-ereo@latest my-app --no-git
101
+
102
+ # Create with tracing enabled
103
+ bunx create-ereo@latest my-app --trace
100
104
  ```
101
105
 
102
106
  ## Project Structure
package/dist/index.js CHANGED
@@ -420,11 +420,28 @@ export default function HomePage() {
420
420
  esModuleInterop: true,
421
421
  skipLibCheck: true,
422
422
  forceConsistentCasingInFileNames: true,
423
- types: ["bun-types"]
423
+ types: ["bun-types"],
424
+ baseUrl: ".",
425
+ paths: {
426
+ "~/*": ["./app/*"],
427
+ "@/*": ["./app/*"]
428
+ }
424
429
  },
425
430
  include: ["app/**/*", "*.config.ts"]
426
431
  };
427
432
  await Bun.write(join(projectDir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2));
433
+ } else {
434
+ const jsconfig = {
435
+ compilerOptions: {
436
+ baseUrl: ".",
437
+ paths: {
438
+ "~/*": ["./app/*"],
439
+ "@/*": ["./app/*"]
440
+ }
441
+ },
442
+ include: ["app/**/*"]
443
+ };
444
+ await Bun.write(join(projectDir, "jsconfig.json"), JSON.stringify(jsconfig, null, 2));
428
445
  }
429
446
  await Bun.write(join(projectDir, ".gitignore"), `node_modules
430
447
  .ereo
@@ -516,13 +533,27 @@ export default defineConfig({
516
533
  skipLibCheck: true,
517
534
  forceConsistentCasingInFileNames: true,
518
535
  types: ["bun-types"],
536
+ baseUrl: ".",
519
537
  paths: {
520
- "~/*": ["./app/*"]
538
+ "~/*": ["./app/*"],
539
+ "@/*": ["./app/*"]
521
540
  }
522
541
  },
523
542
  include: ["app/**/*", "*.config.ts"]
524
543
  };
525
544
  await Bun.write(join(projectDir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2));
545
+ } else {
546
+ const jsconfig = {
547
+ compilerOptions: {
548
+ baseUrl: ".",
549
+ paths: {
550
+ "~/*": ["./app/*"],
551
+ "@/*": ["./app/*"]
552
+ }
553
+ },
554
+ include: ["app/**/*"]
555
+ };
556
+ await Bun.write(join(projectDir, "jsconfig.json"), JSON.stringify(jsconfig, null, 2));
526
557
  }
527
558
  const tailwindConfig = `
528
559
  /** @type {import('tailwindcss').Config} */
@@ -713,7 +744,7 @@ For production, alias \\\`@ereo/trace\\\` to \\\`@ereo/trace/noop\\\` \u2014 a 5
713
744
  tags: ['ereo', 'tracing', 'devtools'],
714
745
  },` : "";
715
746
  const mockData = `
716
- ${ts ? `import type { Post } from './types';
747
+ ${ts ? `import type { Post } from '~/lib/types';
717
748
  ` : ""}
718
749
  /**
719
750
  * Mock blog posts data.
@@ -859,10 +890,6 @@ export async function simulateDelay(ms${ts ? ": number" : ""} = 100)${ts ? ": Pr
859
890
  `.trim();
860
891
  await Bun.write(join(projectDir, `app/lib/data.${ts ? "ts" : "js"}`), mockData);
861
892
  const navigation = `
862
- 'use client';
863
-
864
- import { useState } from 'react';
865
-
866
893
  const navLinks = [
867
894
  { href: '/', label: 'Home' },
868
895
  { href: '/blog', label: 'Blog' },
@@ -871,8 +898,6 @@ const navLinks = [
871
898
  ];
872
899
 
873
900
  export function Navigation() {
874
- const [isOpen, setIsOpen] = useState(false);
875
-
876
901
  return (
877
902
  <nav className="bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800">
878
903
  <div className="max-w-6xl mx-auto px-4">
@@ -905,37 +930,26 @@ export function Navigation() {
905
930
  ))}
906
931
  </div>
907
932
 
908
- {/* Mobile menu button */}
909
- <button
910
- onClick={() => setIsOpen(!isOpen)}
911
- className="md:hidden p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800"
912
- aria-label="Toggle menu"
913
- >
914
- <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
915
- {isOpen ? (
916
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
917
- ) : (
933
+ {/* Mobile Navigation - uses native <details> for JS-free toggle */}
934
+ <details className="md:hidden relative">
935
+ <summary className="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer list-none [&::-webkit-details-marker]:hidden">
936
+ <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
918
937
  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
919
- )}
920
- </svg>
921
- </button>
938
+ </svg>
939
+ </summary>
940
+ <div className="absolute right-0 top-full mt-2 w-48 py-2 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg z-50">
941
+ {navLinks.map((link) => (
942
+ <a
943
+ key={link.href}
944
+ href={link.href}
945
+ className="block px-4 py-2 text-gray-600 dark:text-gray-300 hover:text-primary-600 hover:bg-gray-50 dark:hover:bg-gray-700"
946
+ >
947
+ {link.label}
948
+ </a>
949
+ ))}
950
+ </div>
951
+ </details>
922
952
  </div>
923
-
924
- {/* Mobile Navigation */}
925
- {isOpen && (
926
- <div className="md:hidden py-4 border-t border-gray-200 dark:border-gray-800">
927
- {navLinks.map((link) => (
928
- <a
929
- key={link.href}
930
- href={link.href}
931
- className="block py-2 text-gray-600 dark:text-gray-300 hover:text-primary-600"
932
- onClick={() => setIsOpen(false)}
933
- >
934
- {link.label}
935
- </a>
936
- ))}
937
- </div>
938
- )}
939
953
  </div>
940
954
  </nav>
941
955
  );
@@ -1077,6 +1091,21 @@ export default function RootLayout({ children }${ts ? ": RootLayoutProps" : ""})
1077
1091
  }
1078
1092
  `.trim();
1079
1093
  await Bun.write(join(projectDir, `app/routes/_layout.${ext}`), rootLayout);
1094
+ const clientEntry = `
1095
+ /**
1096
+ * Client Entry Point
1097
+ *
1098
+ * This file initializes the client-side runtime:
1099
+ * - Hydrates island components marked with 'use client'
1100
+ * - Sets up client-side navigation
1101
+ * - Enables link prefetching
1102
+ */
1103
+ import { initClient } from '@ereo/client';
1104
+
1105
+ // Initialize the EreoJS client runtime
1106
+ initClient();
1107
+ `.trim();
1108
+ await Bun.write(join(projectDir, `app/entry.client.${ext}`), clientEntry);
1080
1109
  const homePage = `
1081
1110
  import { Counter } from '~/components/Counter';
1082
1111
  import { getAllPosts, simulateDelay } from '~/lib/data';
@@ -1290,7 +1319,7 @@ export async function action({ request }) {
1290
1319
  This counter is an island \u2014 it's the only part of this page that ships JavaScript. The rest is pure HTML from the server.
1291
1320
  </p>
1292
1321
  <div className="flex justify-center">
1293
- <Counter initialCount={0} />
1322
+ <Counter client:load initialCount={0} />
1294
1323
  </div>
1295
1324
  </div>
1296
1325
  </div>
@@ -1514,13 +1543,9 @@ export function ErrorBoundary({ error }${ts ? ": { error: Error }" : ""}) {
1514
1543
  `.trim();
1515
1544
  await Bun.write(join(projectDir, `app/routes/blog/[slug].${ext}`), blogPost);
1516
1545
  const contactPage = `
1517
- 'use client';
1518
-
1519
- import { useState } from 'react';
1520
-
1521
1546
  /**
1522
1547
  * Action handler for the contact form.
1523
- * Runs on the server when the form is submitted.
1548
+ * Runs on the server when the form is submitted via POST.
1524
1549
  */
1525
1550
  export async function action({ request }${ts ? ": { request: Request }" : ""}) {
1526
1551
  const formData = await request.formData();
@@ -1568,13 +1593,6 @@ ${ts ? `interface ContactPageProps {
1568
1593
  }
1569
1594
  ` : ""}
1570
1595
  export default function ContactPage({ actionData }${ts ? ": ContactPageProps" : ""}) {
1571
- const [isSubmitting, setIsSubmitting] = useState(false);
1572
-
1573
- const handleSubmit = async (e${ts ? ": React.FormEvent<HTMLFormElement>" : ""}) => {
1574
- setIsSubmitting(true);
1575
- // Form will be handled by the action
1576
- };
1577
-
1578
1596
  return (
1579
1597
  <div className="min-h-screen py-12 px-4">
1580
1598
  <div className="max-w-2xl mx-auto">
@@ -1593,7 +1611,7 @@ export default function ContactPage({ actionData }${ts ? ": ContactPageProps" :
1593
1611
  </div>
1594
1612
  </div>
1595
1613
  ) : (
1596
- <form method="POST" onSubmit={handleSubmit} className="space-y-6">
1614
+ <form method="POST" className="space-y-6">
1597
1615
  <div>
1598
1616
  <label htmlFor="name" className="block text-sm font-medium mb-2">
1599
1617
  Name
@@ -1647,10 +1665,9 @@ export default function ContactPage({ actionData }${ts ? ": ContactPageProps" :
1647
1665
 
1648
1666
  <button
1649
1667
  type="submit"
1650
- disabled={isSubmitting}
1651
- className="btn btn-primary w-full disabled:opacity-50"
1668
+ className="btn btn-primary w-full"
1652
1669
  >
1653
- {isSubmitting ? 'Sending...' : 'Send Message'}
1670
+ Send Message
1654
1671
  </button>
1655
1672
  </form>
1656
1673
  )}
@@ -2051,13 +2068,27 @@ export default defineConfig({
2051
2068
  skipLibCheck: true,
2052
2069
  forceConsistentCasingInFileNames: true,
2053
2070
  types: ["bun-types"],
2071
+ baseUrl: ".",
2054
2072
  paths: {
2055
- "~/*": ["./app/*"]
2073
+ "~/*": ["./app/*"],
2074
+ "@/*": ["./app/*"]
2056
2075
  }
2057
2076
  },
2058
2077
  include: ["app/**/*", "*.config.ts"]
2059
2078
  };
2060
2079
  await Bun.write(join(projectDir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2));
2080
+ } else {
2081
+ const jsconfig = {
2082
+ compilerOptions: {
2083
+ baseUrl: ".",
2084
+ paths: {
2085
+ "~/*": ["./app/*"],
2086
+ "@/*": ["./app/*"]
2087
+ }
2088
+ },
2089
+ include: ["app/**/*"]
2090
+ };
2091
+ await Bun.write(join(projectDir, "jsconfig.json"), JSON.stringify(jsconfig, null, 2));
2061
2092
  }
2062
2093
  const tailwindConfig = `
2063
2094
  /** @type {import('tailwindcss').Config} */
@@ -2341,7 +2372,7 @@ export default db;
2341
2372
  * Shared types for the application.
2342
2373
  */
2343
2374
 
2344
- export type { User, Task, TaskStats } from './db';
2375
+ export type { User, Task, TaskStats } from '~/lib/db';
2345
2376
 
2346
2377
  export interface ActionResult<T = unknown> {
2347
2378
  success: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ereo",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "license": "MIT",
5
5
  "author": "Ereo Team",
6
6
  "homepage": "https://ereojs.github.io/ereoJS",