create-ereo 0.2.7 → 0.2.9
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/README.md +4 -0
- package/dist/index.js +38 -52
- 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
|
|
940
|
-
<
|
|
941
|
-
|
|
942
|
-
|
|
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
|
-
</
|
|
952
|
-
|
|
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"
|
|
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
|
-
|
|
1682
|
-
className="btn btn-primary w-full disabled:opacity-50"
|
|
1668
|
+
className="btn btn-primary w-full"
|
|
1683
1669
|
>
|
|
1684
|
-
|
|
1670
|
+
Send Message
|
|
1685
1671
|
</button>
|
|
1686
1672
|
</form>
|
|
1687
1673
|
)}
|