@floegence/floe-webapp-init 0.1.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.
package/dist/index.mjs ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ import t from"node:fs";import a from"node:path";import{fileURLToPath as d}from"node:url";import y from"prompts";import{red as c,bold as g,cyan as f,green as x}from"kolorist";const h=[{name:"minimal",value:"minimal",description:"Basic setup with FloeApp"},{name:"full",value:"full",description:"Full setup with sample pages"}],v={"_package.json":"package.json",_gitignore:".gitignore","_env.example":".env.example"};async function S(){console.log(`
3
+ ${g(f("Floe Webapp"))}
4
+ `);const n=process.argv.slice(2);let o=n[0],l;(n.includes("--help")||n.includes("-h"))&&(console.log(`Usage: npx @floegence/floe-webapp-init [project-name] [options]
5
+
6
+ Options:
7
+ --template <name> Use a specific template (minimal, full)
8
+ --help, -h Show this help message
9
+
10
+ Examples:
11
+ npx @floegence/floe-webapp-init
12
+ npx @floegence/floe-webapp-init my-app
13
+ npx @floegence/floe-webapp-init my-app --template full
14
+ `),process.exit(0));const i=n.indexOf("--template");if(i!==-1&&n[i+1]){const e=n[i+1];e==="minimal"||e==="full"?l=e:(console.log(c(`Invalid template: ${e}`)),console.log("Available templates: minimal, full"),process.exit(1)),o==="--template"&&(o=n[i+2])}const p=await y([{type:o?null:"text",name:"projectName",message:"Project name:",initial:"floe-app",validate:e=>e?/^[a-z0-9-_]+$/i.test(e)?!0:"Project name can only contain letters, numbers, hyphens, and underscores":"Project name is required"},{type:l?null:"select",name:"template",message:"Select a template:",choices:h.map(e=>({title:e.name,value:e.value,description:e.description}))}],{onCancel:()=>{console.log(c(`
15
+ Operation cancelled`)),process.exit(1)}});o=o||p.projectName,l=l||p.template,(!o||!l)&&(console.log(c("Missing required information")),process.exit(1));const s=a.resolve(o);t.existsSync(s)&&t.readdirSync(s).length>0&&(console.log(c(`
16
+ Directory ${o} is not empty.`)),process.exit(1)),console.log(`
17
+ Scaffolding project in ${f(s)}...
18
+ `);const r=a.resolve(d(import.meta.url),"../../templates",l);t.existsSync(r)||(console.log(c(`Template directory not found: ${r}`)),process.exit(1)),u(r,s);const m=a.join(s,"package.json");if(t.existsSync(m)){const e=JSON.parse(t.readFileSync(m,"utf-8"));e.name=a.basename(o),t.writeFileSync(m,JSON.stringify(e,null,2)+`
19
+ `)}console.log(x(`Done!
20
+ `)),console.log(`Next steps:
21
+ `),console.log(` cd ${g(o)}`),console.log(" pnpm install"),console.log(` pnpm dev
22
+ `)}function u(n,o){t.mkdirSync(o,{recursive:!0});for(const l of t.readdirSync(n)){const i=a.join(n,l),p=v[l]||l,s=a.join(o,p);t.statSync(i).isDirectory()?u(i,s):t.copyFileSync(i,s)}}S().catch(n=>{console.error(c("Error:"),n),process.exit(1)});
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@floegence/floe-webapp-init",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Scaffolding tool for Floe Webapp applications",
6
+ "bin": {
7
+ "floe-webapp-init": "./dist/index.mjs"
8
+ },
9
+ "main": "./dist/index.mjs",
10
+ "files": [
11
+ "dist",
12
+ "templates"
13
+ ],
14
+ "scripts": {
15
+ "build": "unbuild",
16
+ "dev": "unbuild --stub",
17
+ "typecheck": "tsc --noEmit"
18
+ },
19
+ "dependencies": {
20
+ "prompts": "^2.4.2",
21
+ "kolorist": "^1.8.0"
22
+ },
23
+ "devDependencies": {
24
+ "@types/prompts": "^2.4.9",
25
+ "@types/node": "^22.10.0",
26
+ "typescript": "^5.7.2",
27
+ "unbuild": "^3.3.1"
28
+ },
29
+ "engines": {
30
+ "node": ">=20.0.0"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ }
35
+ }
@@ -0,0 +1,31 @@
1
+ # Dependencies
2
+ node_modules
3
+
4
+ # Build output
5
+ dist
6
+
7
+ # Local env files
8
+ .env
9
+ .env.local
10
+ .env.*.local
11
+
12
+ # Editor directories and files
13
+ .vscode/*
14
+ !.vscode/extensions.json
15
+ .idea
16
+ *.suo
17
+ *.ntvs*
18
+ *.njsproj
19
+ *.sln
20
+ *.sw?
21
+
22
+ # OS files
23
+ .DS_Store
24
+ Thumbs.db
25
+
26
+ # Logs
27
+ *.log
28
+ npm-debug.log*
29
+ pnpm-debug.log*
30
+ yarn-debug.log*
31
+ yarn-error.log*
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "floe-app",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "@floegence/floe-webapp-core": "^0.1.0",
13
+ "solid-js": "^1.9.3"
14
+ },
15
+ "devDependencies": {
16
+ "@tailwindcss/vite": "^4.0.0",
17
+ "tailwindcss": "^4.0.0",
18
+ "typescript": "^5.7.2",
19
+ "vite": "^6.0.7",
20
+ "vite-plugin-solid": "^2.11.0"
21
+ }
22
+ }
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Floe App</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
10
+ <script>
11
+ (function() {
12
+ const stored = localStorage.getItem('floe-theme');
13
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
14
+ const theme = stored ? JSON.parse(stored) : (prefersDark ? 'dark' : 'light');
15
+ const resolved = theme === 'system' ? (prefersDark ? 'dark' : 'light') : theme;
16
+ document.documentElement.classList.add(resolved);
17
+ document.documentElement.style.colorScheme = resolved;
18
+ })();
19
+ </script>
20
+ </head>
21
+ <body>
22
+ <div id="root"></div>
23
+ <script type="module" src="/src/index.tsx"></script>
24
+ </body>
25
+ </html>
@@ -0,0 +1,64 @@
1
+ import {
2
+ FloeApp,
3
+ Files,
4
+ Settings,
5
+ useLayout,
6
+ type FloeComponent,
7
+ } from '@floegence/floe-webapp-core';
8
+ import { HomePage } from './pages/HomePage';
9
+ import { SettingsPage } from './pages/SettingsPage';
10
+
11
+ // Component definitions for the sidebar and command palette
12
+ // Components are rendered in the sidebar; use fullScreen: true for main content
13
+ const components: FloeComponent[] = [
14
+ {
15
+ id: 'home',
16
+ name: 'Home',
17
+ icon: Files,
18
+ description: 'Home page',
19
+ component: HomePage,
20
+ sidebar: { order: 0, fullScreen: true },
21
+ commands: [
22
+ {
23
+ id: 'home.open',
24
+ title: 'Go to Home',
25
+ handler: ({ setActive }) => setActive('home'),
26
+ },
27
+ ],
28
+ },
29
+ {
30
+ id: 'settings',
31
+ name: 'Settings',
32
+ icon: Settings,
33
+ description: 'Application settings',
34
+ component: SettingsPage,
35
+ sidebar: { order: 100, fullScreen: true },
36
+ commands: [
37
+ {
38
+ id: 'settings.open',
39
+ title: 'Open Settings',
40
+ handler: ({ setActive }) => setActive('settings'),
41
+ },
42
+ ],
43
+ },
44
+ ];
45
+
46
+ // Content switcher based on active component
47
+ function AppContent() {
48
+ const layout = useLayout();
49
+
50
+ return (
51
+ <>
52
+ {layout.sidebarActiveTab() === 'home' && <HomePage />}
53
+ {layout.sidebarActiveTab() === 'settings' && <SettingsPage />}
54
+ </>
55
+ );
56
+ }
57
+
58
+ export default function App() {
59
+ return (
60
+ <FloeApp components={components}>
61
+ <AppContent />
62
+ </FloeApp>
63
+ );
64
+ }
@@ -0,0 +1,3 @@
1
+ @import 'tailwindcss';
2
+ @source './**/*.{ts,tsx}';
3
+ @import '@floegence/floe-webapp-core/styles';
@@ -0,0 +1,5 @@
1
+ import { render } from 'solid-js/web';
2
+ import App from './App';
3
+ import './index.css';
4
+
5
+ render(() => <App />, document.getElementById('root')!);
@@ -0,0 +1,32 @@
1
+ export function HomePage() {
2
+ return (
3
+ <div class="flex h-full items-center justify-center">
4
+ <div class="text-center">
5
+ <h1 class="text-3xl font-bold text-foreground">Welcome to Floe</h1>
6
+ <p class="mt-2 text-muted-foreground">
7
+ A feature-rich starter template
8
+ </p>
9
+ <div class="mt-6 flex justify-center gap-4">
10
+ <div class="rounded-lg border border-border bg-card p-4">
11
+ <h3 class="font-medium text-foreground">Components</h3>
12
+ <p class="mt-1 text-sm text-muted-foreground">
13
+ Pre-built UI components
14
+ </p>
15
+ </div>
16
+ <div class="rounded-lg border border-border bg-card p-4">
17
+ <h3 class="font-medium text-foreground">Commands</h3>
18
+ <p class="mt-1 text-sm text-muted-foreground">
19
+ Press Cmd+K to open
20
+ </p>
21
+ </div>
22
+ <div class="rounded-lg border border-border bg-card p-4">
23
+ <h3 class="font-medium text-foreground">Themes</h3>
24
+ <p class="mt-1 text-sm text-muted-foreground">
25
+ Light and dark mode
26
+ </p>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ </div>
31
+ );
32
+ }
@@ -0,0 +1,78 @@
1
+ import { useTheme, Sun, Moon } from '@floegence/floe-webapp-core';
2
+
3
+ export function SettingsPage() {
4
+ const { theme, setTheme } = useTheme();
5
+
6
+ return (
7
+ <div class="h-full overflow-auto p-6">
8
+ <h1 class="text-2xl font-bold text-foreground">Settings</h1>
9
+ <p class="mt-1 text-muted-foreground">
10
+ Manage your application preferences
11
+ </p>
12
+
13
+ <div class="mt-6 space-y-6">
14
+ {/* Theme Section */}
15
+ <section class="rounded-lg border border-border bg-card p-4">
16
+ <h2 class="font-medium text-foreground">Appearance</h2>
17
+ <p class="mt-1 text-sm text-muted-foreground">
18
+ Customize how the app looks
19
+ </p>
20
+
21
+ <div class="mt-4 flex gap-3">
22
+ <button
23
+ class={`flex items-center gap-2 rounded-lg border px-4 py-2 transition-colors ${
24
+ theme() === 'light'
25
+ ? 'border-primary bg-primary/10 text-primary'
26
+ : 'border-border text-muted-foreground hover:border-foreground/50'
27
+ }`}
28
+ onClick={() => setTheme('light')}
29
+ >
30
+ <Sun size={16} />
31
+ Light
32
+ </button>
33
+ <button
34
+ class={`flex items-center gap-2 rounded-lg border px-4 py-2 transition-colors ${
35
+ theme() === 'dark'
36
+ ? 'border-primary bg-primary/10 text-primary'
37
+ : 'border-border text-muted-foreground hover:border-foreground/50'
38
+ }`}
39
+ onClick={() => setTheme('dark')}
40
+ >
41
+ <Moon size={16} />
42
+ Dark
43
+ </button>
44
+ <button
45
+ class={`flex items-center gap-2 rounded-lg border px-4 py-2 transition-colors ${
46
+ theme() === 'system'
47
+ ? 'border-primary bg-primary/10 text-primary'
48
+ : 'border-border text-muted-foreground hover:border-foreground/50'
49
+ }`}
50
+ onClick={() => setTheme('system')}
51
+ >
52
+ System
53
+ </button>
54
+ </div>
55
+ </section>
56
+
57
+ {/* About Section */}
58
+ <section class="rounded-lg border border-border bg-card p-4">
59
+ <h2 class="font-medium text-foreground">About</h2>
60
+ <p class="mt-1 text-sm text-muted-foreground">
61
+ Application information
62
+ </p>
63
+
64
+ <div class="mt-4 space-y-2 text-sm">
65
+ <div class="flex justify-between">
66
+ <span class="text-muted-foreground">Version</span>
67
+ <span class="text-foreground">0.0.0</span>
68
+ </div>
69
+ <div class="flex justify-between">
70
+ <span class="text-muted-foreground">Framework</span>
71
+ <span class="text-foreground">Floe Webapp</span>
72
+ </div>
73
+ </div>
74
+ </section>
75
+ </div>
76
+ </div>
77
+ );
78
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "jsx": "preserve",
8
+ "jsxImportSource": "solid-js",
9
+ "strict": true,
10
+ "noEmit": true,
11
+ "isolatedModules": true,
12
+ "esModuleInterop": true,
13
+ "skipLibCheck": true,
14
+ "resolveJsonModule": true,
15
+ "allowImportingTsExtensions": true,
16
+ "verbatimModuleSyntax": true,
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "noFallthroughCasesInSwitch": true,
20
+ "forceConsistentCasingInFileNames": true
21
+ },
22
+ "include": ["src"],
23
+ "exclude": ["node_modules", "dist"]
24
+ }
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from 'vite';
2
+ import solid from 'vite-plugin-solid';
3
+ import tailwindcss from '@tailwindcss/vite';
4
+
5
+ export default defineConfig({
6
+ plugins: [solid(), tailwindcss()],
7
+ });
@@ -0,0 +1,31 @@
1
+ # Dependencies
2
+ node_modules
3
+
4
+ # Build output
5
+ dist
6
+
7
+ # Local env files
8
+ .env
9
+ .env.local
10
+ .env.*.local
11
+
12
+ # Editor directories and files
13
+ .vscode/*
14
+ !.vscode/extensions.json
15
+ .idea
16
+ *.suo
17
+ *.ntvs*
18
+ *.njsproj
19
+ *.sln
20
+ *.sw?
21
+
22
+ # OS files
23
+ .DS_Store
24
+ Thumbs.db
25
+
26
+ # Logs
27
+ *.log
28
+ npm-debug.log*
29
+ pnpm-debug.log*
30
+ yarn-debug.log*
31
+ yarn-error.log*
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "floe-app",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "@floegence/floe-webapp-core": "^0.1.0",
13
+ "solid-js": "^1.9.3"
14
+ },
15
+ "devDependencies": {
16
+ "@tailwindcss/vite": "^4.0.0",
17
+ "tailwindcss": "^4.0.0",
18
+ "typescript": "^5.7.2",
19
+ "vite": "^6.0.7",
20
+ "vite-plugin-solid": "^2.11.0"
21
+ }
22
+ }
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Floe App</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
10
+ <script>
11
+ (function() {
12
+ const stored = localStorage.getItem('floe-theme');
13
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
14
+ const theme = stored ? JSON.parse(stored) : (prefersDark ? 'dark' : 'light');
15
+ const resolved = theme === 'system' ? (prefersDark ? 'dark' : 'light') : theme;
16
+ document.documentElement.classList.add(resolved);
17
+ document.documentElement.style.colorScheme = resolved;
18
+ })();
19
+ </script>
20
+ </head>
21
+ <body>
22
+ <div id="root"></div>
23
+ <script type="module" src="/src/index.tsx"></script>
24
+ </body>
25
+ </html>
@@ -0,0 +1,29 @@
1
+ import { FloeApp, Files, type FloeComponent } from '@floegence/floe-webapp-core';
2
+
3
+ const HomePage = () => (
4
+ <div class="flex h-full items-center justify-center">
5
+ <div class="text-center">
6
+ <h1 class="text-2xl font-bold text-foreground">Welcome to Floe</h1>
7
+ <p class="mt-2 text-muted-foreground">Start building your app</p>
8
+ </div>
9
+ </div>
10
+ );
11
+
12
+ const components: FloeComponent[] = [
13
+ {
14
+ id: 'home',
15
+ name: 'Home',
16
+ icon: Files,
17
+ description: 'Home page',
18
+ component: HomePage,
19
+ sidebar: { order: 0 },
20
+ },
21
+ ];
22
+
23
+ export default function App() {
24
+ return (
25
+ <FloeApp components={components}>
26
+ <HomePage />
27
+ </FloeApp>
28
+ );
29
+ }
@@ -0,0 +1,3 @@
1
+ @import 'tailwindcss';
2
+ @source './**/*.{ts,tsx}';
3
+ @import '@floegence/floe-webapp-core/styles';
@@ -0,0 +1,5 @@
1
+ import { render } from 'solid-js/web';
2
+ import App from './App';
3
+ import './index.css';
4
+
5
+ render(() => <App />, document.getElementById('root')!);
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "jsx": "preserve",
8
+ "jsxImportSource": "solid-js",
9
+ "strict": true,
10
+ "noEmit": true,
11
+ "isolatedModules": true,
12
+ "esModuleInterop": true,
13
+ "skipLibCheck": true,
14
+ "resolveJsonModule": true,
15
+ "allowImportingTsExtensions": true,
16
+ "verbatimModuleSyntax": true,
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "noFallthroughCasesInSwitch": true,
20
+ "forceConsistentCasingInFileNames": true
21
+ },
22
+ "include": ["src"],
23
+ "exclude": ["node_modules", "dist"]
24
+ }
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from 'vite';
2
+ import solid from 'vite-plugin-solid';
3
+ import tailwindcss from '@tailwindcss/vite';
4
+
5
+ export default defineConfig({
6
+ plugins: [solid(), tailwindcss()],
7
+ });