create-ereo 0.2.7 → 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 +38 -52
  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
@@ -890,10 +890,6 @@ export async function simulateDelay(ms${ts ? ": number" : ""} = 100)${ts ? ": Pr
890
890
  `.trim();
891
891
  await Bun.write(join(projectDir, `app/lib/data.${ts ? "ts" : "js"}`), mockData);
892
892
  const navigation = `
893
- 'use client';
894
-
895
- import { useState } from 'react';
896
-
897
893
  const navLinks = [
898
894
  { href: '/', label: 'Home' },
899
895
  { href: '/blog', label: 'Blog' },
@@ -902,8 +898,6 @@ const navLinks = [
902
898
  ];
903
899
 
904
900
  export function Navigation() {
905
- const [isOpen, setIsOpen] = useState(false);
906
-
907
901
  return (
908
902
  <nav className="bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800">
909
903
  <div className="max-w-6xl mx-auto px-4">
@@ -936,37 +930,26 @@ export function Navigation() {
936
930
  ))}
937
931
  </div>
938
932
 
939
- {/* Mobile menu button */}
940
- <button
941
- onClick={() => setIsOpen(!isOpen)}
942
- className="md:hidden p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800"
943
- aria-label="Toggle menu"
944
- >
945
- <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
946
- {isOpen ? (
947
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
948
- ) : (
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">
949
937
  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
950
- )}
951
- </svg>
952
- </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>
953
952
  </div>
954
-
955
- {/* Mobile Navigation */}
956
- {isOpen && (
957
- <div className="md:hidden py-4 border-t border-gray-200 dark:border-gray-800">
958
- {navLinks.map((link) => (
959
- <a
960
- key={link.href}
961
- href={link.href}
962
- className="block py-2 text-gray-600 dark:text-gray-300 hover:text-primary-600"
963
- onClick={() => setIsOpen(false)}
964
- >
965
- {link.label}
966
- </a>
967
- ))}
968
- </div>
969
- )}
970
953
  </div>
971
954
  </nav>
972
955
  );
@@ -1108,6 +1091,21 @@ export default function RootLayout({ children }${ts ? ": RootLayoutProps" : ""})
1108
1091
  }
1109
1092
  `.trim();
1110
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);
1111
1109
  const homePage = `
1112
1110
  import { Counter } from '~/components/Counter';
1113
1111
  import { getAllPosts, simulateDelay } from '~/lib/data';
@@ -1321,7 +1319,7 @@ export async function action({ request }) {
1321
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.
1322
1320
  </p>
1323
1321
  <div className="flex justify-center">
1324
- <Counter initialCount={0} />
1322
+ <Counter client:load initialCount={0} />
1325
1323
  </div>
1326
1324
  </div>
1327
1325
  </div>
@@ -1545,13 +1543,9 @@ export function ErrorBoundary({ error }${ts ? ": { error: Error }" : ""}) {
1545
1543
  `.trim();
1546
1544
  await Bun.write(join(projectDir, `app/routes/blog/[slug].${ext}`), blogPost);
1547
1545
  const contactPage = `
1548
- 'use client';
1549
-
1550
- import { useState } from 'react';
1551
-
1552
1546
  /**
1553
1547
  * Action handler for the contact form.
1554
- * Runs on the server when the form is submitted.
1548
+ * Runs on the server when the form is submitted via POST.
1555
1549
  */
1556
1550
  export async function action({ request }${ts ? ": { request: Request }" : ""}) {
1557
1551
  const formData = await request.formData();
@@ -1599,13 +1593,6 @@ ${ts ? `interface ContactPageProps {
1599
1593
  }
1600
1594
  ` : ""}
1601
1595
  export default function ContactPage({ actionData }${ts ? ": ContactPageProps" : ""}) {
1602
- const [isSubmitting, setIsSubmitting] = useState(false);
1603
-
1604
- const handleSubmit = async (e${ts ? ": React.FormEvent<HTMLFormElement>" : ""}) => {
1605
- setIsSubmitting(true);
1606
- // Form will be handled by the action
1607
- };
1608
-
1609
1596
  return (
1610
1597
  <div className="min-h-screen py-12 px-4">
1611
1598
  <div className="max-w-2xl mx-auto">
@@ -1624,7 +1611,7 @@ export default function ContactPage({ actionData }${ts ? ": ContactPageProps" :
1624
1611
  </div>
1625
1612
  </div>
1626
1613
  ) : (
1627
- <form method="POST" onSubmit={handleSubmit} className="space-y-6">
1614
+ <form method="POST" className="space-y-6">
1628
1615
  <div>
1629
1616
  <label htmlFor="name" className="block text-sm font-medium mb-2">
1630
1617
  Name
@@ -1678,10 +1665,9 @@ export default function ContactPage({ actionData }${ts ? ": ContactPageProps" :
1678
1665
 
1679
1666
  <button
1680
1667
  type="submit"
1681
- disabled={isSubmitting}
1682
- className="btn btn-primary w-full disabled:opacity-50"
1668
+ className="btn btn-primary w-full"
1683
1669
  >
1684
- {isSubmitting ? 'Sending...' : 'Send Message'}
1670
+ Send Message
1685
1671
  </button>
1686
1672
  </form>
1687
1673
  )}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ereo",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "license": "MIT",
5
5
  "author": "Ereo Team",
6
6
  "homepage": "https://ereojs.github.io/ereoJS",