@korajs/cli 0.3.1 → 0.3.4

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 (48) hide show
  1. package/dist/bin.cjs +120 -67
  2. package/dist/bin.cjs.map +1 -1
  3. package/dist/bin.js +3 -3
  4. package/dist/{chunk-KTSRAPSE.js → chunk-HNVCNPER.js} +105 -65
  5. package/dist/chunk-HNVCNPER.js.map +1 -0
  6. package/dist/{chunk-E7OCVRYL.js → chunk-MIMLCXSX.js} +2 -2
  7. package/dist/{chunk-ZGYRDYXS.js → chunk-ULTO5NFA.js} +22 -4
  8. package/dist/chunk-ULTO5NFA.js.map +1 -0
  9. package/dist/create.cjs +119 -66
  10. package/dist/create.cjs.map +1 -1
  11. package/dist/create.js +2 -2
  12. package/dist/index.cjs +105 -65
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.cts +6 -1
  15. package/dist/index.d.ts +6 -1
  16. package/dist/index.js +2 -2
  17. package/package.json +2 -2
  18. package/templates/tauri-react/.env.example +7 -0
  19. package/templates/tauri-react/.github/workflows/release-desktop.yml +107 -0
  20. package/templates/tauri-react/README.md.hbs +148 -0
  21. package/templates/tauri-react/dev.ts +37 -0
  22. package/templates/tauri-react/index.html.hbs +16 -0
  23. package/templates/tauri-react/kora.config.ts +17 -0
  24. package/templates/tauri-react/package.json.hbs +44 -0
  25. package/templates/tauri-react/server.ts +23 -0
  26. package/templates/tauri-react/src/App.tsx +578 -0
  27. package/templates/tauri-react/src/AppShell.tsx +116 -0
  28. package/templates/tauri-react/src/SetupScreen.tsx +239 -0
  29. package/templates/tauri-react/src/main.tsx +9 -0
  30. package/templates/tauri-react/src/schema.ts +15 -0
  31. package/templates/tauri-react/src/sync-config.ts +103 -0
  32. package/templates/tauri-react/src/updater.ts +38 -0
  33. package/templates/tauri-react/src-tauri/Cargo.toml +19 -0
  34. package/templates/tauri-react/src-tauri/build.rs +3 -0
  35. package/templates/tauri-react/src-tauri/capabilities/default.json +12 -0
  36. package/templates/tauri-react/src-tauri/icons/128x128.png +0 -0
  37. package/templates/tauri-react/src-tauri/icons/128x128@2x.png +0 -0
  38. package/templates/tauri-react/src-tauri/icons/32x32.png +0 -0
  39. package/templates/tauri-react/src-tauri/icons/icon.icns +0 -0
  40. package/templates/tauri-react/src-tauri/icons/icon.ico +0 -0
  41. package/templates/tauri-react/src-tauri/src/lib.rs +8 -0
  42. package/templates/tauri-react/src-tauri/src/main.rs +6 -0
  43. package/templates/tauri-react/src-tauri/tauri.conf.json +44 -0
  44. package/templates/tauri-react/tsconfig.json +15 -0
  45. package/templates/tauri-react/vite.config.ts +15 -0
  46. package/dist/chunk-KTSRAPSE.js.map +0 -1
  47. package/dist/chunk-ZGYRDYXS.js.map +0 -1
  48. /package/dist/{chunk-E7OCVRYL.js.map → chunk-MIMLCXSX.js.map} +0 -0
package/dist/index.d.cts CHANGED
@@ -5,7 +5,7 @@ import * as citty from 'citty';
5
5
  declare const PACKAGE_MANAGERS: readonly ["pnpm", "npm", "yarn", "bun"];
6
6
  type PackageManager = (typeof PACKAGE_MANAGERS)[number];
7
7
  /** Available project templates */
8
- declare const TEMPLATES: readonly ["react-tailwind-sync", "react-tailwind", "react-sync", "react-basic"];
8
+ declare const TEMPLATES: readonly ["react-tailwind-sync", "react-tailwind", "react-sync", "react-basic", "tauri-react"];
9
9
  type TemplateName = (typeof TEMPLATES)[number];
10
10
  /** Metadata for a project template */
11
11
  interface TemplateInfo {
@@ -548,11 +548,13 @@ interface ProjectNameValidationResult {
548
548
  */
549
549
  declare function validateProjectName(name: string): ProjectNameValidationResult;
550
550
 
551
+ type PlatformOption = 'web' | 'desktop-tauri';
551
552
  type FrameworkOption = 'react' | 'vue' | 'svelte' | 'solid';
552
553
  type AuthOption = 'none' | 'email-password' | 'oauth';
553
554
  type DatabaseOption = 'none' | 'sqlite' | 'postgres';
554
555
  type DatabaseProviderOption = 'none' | 'local' | 'supabase' | 'neon' | 'railway' | 'vercel-postgres' | 'custom';
555
556
  interface TemplateSelectionInput {
557
+ platform: PlatformOption;
556
558
  tailwind: boolean;
557
559
  sync: boolean;
558
560
  db: DatabaseOption;
@@ -614,6 +616,7 @@ declare class ClackPromptClient implements PromptClient {
614
616
  }
615
617
 
616
618
  interface CreatePreferences {
619
+ platform: PlatformOption;
617
620
  framework: FrameworkOption;
618
621
  tailwind: boolean;
619
622
  sync: boolean;
@@ -639,6 +642,7 @@ declare function getCreatePreferencesOrDefault(store: PreferenceStore): CreatePr
639
642
  declare function getDefaultCreatePreferences(): CreatePreferences;
640
643
 
641
644
  interface CreateFlags {
645
+ platform?: string;
642
646
  framework?: string;
643
647
  auth?: string;
644
648
  db?: string;
@@ -648,6 +652,7 @@ interface CreateFlags {
648
652
  useDefaults: boolean;
649
653
  }
650
654
  interface PreferenceResolutionResult {
655
+ platform: PlatformOption;
651
656
  framework: FrameworkOption;
652
657
  auth: AuthOption;
653
658
  db: DatabaseOption;
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@ import * as citty from 'citty';
5
5
  declare const PACKAGE_MANAGERS: readonly ["pnpm", "npm", "yarn", "bun"];
6
6
  type PackageManager = (typeof PACKAGE_MANAGERS)[number];
7
7
  /** Available project templates */
8
- declare const TEMPLATES: readonly ["react-tailwind-sync", "react-tailwind", "react-sync", "react-basic"];
8
+ declare const TEMPLATES: readonly ["react-tailwind-sync", "react-tailwind", "react-sync", "react-basic", "tauri-react"];
9
9
  type TemplateName = (typeof TEMPLATES)[number];
10
10
  /** Metadata for a project template */
11
11
  interface TemplateInfo {
@@ -548,11 +548,13 @@ interface ProjectNameValidationResult {
548
548
  */
549
549
  declare function validateProjectName(name: string): ProjectNameValidationResult;
550
550
 
551
+ type PlatformOption = 'web' | 'desktop-tauri';
551
552
  type FrameworkOption = 'react' | 'vue' | 'svelte' | 'solid';
552
553
  type AuthOption = 'none' | 'email-password' | 'oauth';
553
554
  type DatabaseOption = 'none' | 'sqlite' | 'postgres';
554
555
  type DatabaseProviderOption = 'none' | 'local' | 'supabase' | 'neon' | 'railway' | 'vercel-postgres' | 'custom';
555
556
  interface TemplateSelectionInput {
557
+ platform: PlatformOption;
556
558
  tailwind: boolean;
557
559
  sync: boolean;
558
560
  db: DatabaseOption;
@@ -614,6 +616,7 @@ declare class ClackPromptClient implements PromptClient {
614
616
  }
615
617
 
616
618
  interface CreatePreferences {
619
+ platform: PlatformOption;
617
620
  framework: FrameworkOption;
618
621
  tailwind: boolean;
619
622
  sync: boolean;
@@ -639,6 +642,7 @@ declare function getCreatePreferencesOrDefault(store: PreferenceStore): CreatePr
639
642
  declare function getDefaultCreatePreferences(): CreatePreferences;
640
643
 
641
644
  interface CreateFlags {
645
+ platform?: string;
642
646
  framework?: string;
643
647
  auth?: string;
644
648
  db?: string;
@@ -648,6 +652,7 @@ interface CreateFlags {
648
652
  useDefaults: boolean;
649
653
  }
650
654
  interface PreferenceResolutionResult {
655
+ platform: PlatformOption;
651
656
  framework: FrameworkOption;
652
657
  auth: AuthOption;
653
658
  db: DatabaseOption;
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  writeDockerfileArtifact,
28
28
  writeFlyTomlArtifact,
29
29
  writeRailwayJsonArtifact
30
- } from "./chunk-E7OCVRYL.js";
30
+ } from "./chunk-MIMLCXSX.js";
31
31
  import {
32
32
  ClackPromptClient,
33
33
  CliError,
@@ -54,7 +54,7 @@ import {
54
54
  saveResolvedPreferences,
55
55
  shouldSavePreferences,
56
56
  validateProjectName
57
- } from "./chunk-KTSRAPSE.js";
57
+ } from "./chunk-HNVCNPER.js";
58
58
  export {
59
59
  ClackPromptClient,
60
60
  CliError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@korajs/cli",
3
- "version": "0.3.1",
3
+ "version": "0.3.4",
4
4
  "description": "Kora.js CLI tooling and project scaffolding",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -36,7 +36,7 @@
36
36
  "conf": "^15.1.0",
37
37
  "esbuild": "^0.28.0",
38
38
  "validate-npm-package-name": "^7.0.2",
39
- "@korajs/core": "0.3.1"
39
+ "@korajs/core": "0.3.2"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^25.5.2",
@@ -0,0 +1,7 @@
1
+ # Sync server URL (used by the Tauri app to connect to the sync server)
2
+ # In development, defaults to ws://localhost:3001/kora-sync
3
+ # For production builds, set this to your deployed server URL:
4
+ # VITE_SYNC_URL=wss://your-server.example.com/kora-sync
5
+
6
+ # Sync server port
7
+ PORT=3001
@@ -0,0 +1,107 @@
1
+ # Build and release desktop binaries for macOS, Windows, and Linux.
2
+ #
3
+ # Trigger: Push a version tag (e.g., v1.0.0) or run manually.
4
+ #
5
+ # Prerequisites:
6
+ # 1. Generate Tauri signing keys:
7
+ # pnpm tauri signer generate -w ~/.tauri/myapp.key
8
+ # 2. Add secrets to your GitHub repo:
9
+ # - TAURI_SIGNING_PRIVATE_KEY: Contents of ~/.tauri/myapp.key
10
+ # - TAURI_SIGNING_PRIVATE_KEY_PASSWORD: Password used during generation
11
+ # 3. (Optional) For macOS notarization:
12
+ # - APPLE_CERTIFICATE: Base64-encoded .p12 certificate
13
+ # - APPLE_CERTIFICATE_PASSWORD: Certificate password
14
+ # - APPLE_SIGNING_IDENTITY: e.g., "Developer ID Application: Your Name (TEAM_ID)"
15
+ # - APPLE_ID: Apple ID email
16
+ # - APPLE_PASSWORD: App-specific password
17
+ # - APPLE_TEAM_ID: Your Apple Developer Team ID
18
+ #
19
+ # After the workflow runs, a GitHub Release is created with installers
20
+ # for all platforms plus an update manifest (latest.json) for auto-updates.
21
+
22
+ name: Release Desktop
23
+
24
+ on:
25
+ push:
26
+ tags:
27
+ - 'v*'
28
+ workflow_dispatch:
29
+ inputs:
30
+ tag:
31
+ description: 'Version tag (e.g., v1.0.0)'
32
+ required: true
33
+
34
+ permissions:
35
+ contents: write
36
+
37
+ jobs:
38
+ build:
39
+ strategy:
40
+ fail-fast: false
41
+ matrix:
42
+ include:
43
+ - platform: macos-latest
44
+ args: '--target aarch64-apple-darwin'
45
+ rust_target: aarch64-apple-darwin
46
+ - platform: macos-latest
47
+ args: '--target x86_64-apple-darwin'
48
+ rust_target: x86_64-apple-darwin
49
+ - platform: ubuntu-22.04
50
+ args: ''
51
+ rust_target: ''
52
+ - platform: windows-latest
53
+ args: ''
54
+ rust_target: ''
55
+
56
+ runs-on: ${{ matrix.platform }}
57
+
58
+ steps:
59
+ - uses: actions/checkout@v4
60
+
61
+ - name: Install system dependencies (Linux)
62
+ if: matrix.platform == 'ubuntu-22.04'
63
+ run: |
64
+ sudo apt-get update
65
+ sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
66
+
67
+ - uses: actions/setup-node@v4
68
+ with:
69
+ node-version: 20
70
+
71
+ - uses: pnpm/action-setup@v4
72
+ with:
73
+ version: 9
74
+
75
+ - name: Install Rust stable
76
+ uses: dtolnay/rust-toolchain@stable
77
+ with:
78
+ targets: ${{ matrix.rust_target }}
79
+
80
+ - name: Rust cache
81
+ uses: swatinem/rust-cache@v2
82
+ with:
83
+ workspaces: './src-tauri -> target'
84
+
85
+ - name: Install dependencies
86
+ run: pnpm install
87
+
88
+ - name: Build and release
89
+ uses: tauri-apps/tauri-action@v0
90
+ env:
91
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
92
+ TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
93
+ TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
94
+ # macOS code signing (optional)
95
+ APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
96
+ APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
97
+ APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
98
+ APPLE_ID: ${{ secrets.APPLE_ID }}
99
+ APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
100
+ APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
101
+ with:
102
+ tagName: ${{ github.ref_name || github.event.inputs.tag }}
103
+ releaseName: '${{ github.ref_name || github.event.inputs.tag }}'
104
+ releaseBody: 'See the assets below to download and install.'
105
+ releaseDraft: true
106
+ prerelease: false
107
+ args: ${{ matrix.args }}
@@ -0,0 +1,148 @@
1
+ # {{projectName}}
2
+
3
+ A native desktop application built with [Kora.js](https://ehoneahobed.github.io/kora/) and [Tauri](https://tauri.app). Uses native SQLite for fast local storage and syncs data across devices via a lightweight sync server.
4
+
5
+ ## Getting Started
6
+
7
+ ```bash
8
+ pnpm dev
9
+ ```
10
+
11
+ This starts both the sync server and the Tauri desktop app. The first launch compiles the Rust backend (2-5 minutes). Subsequent launches are fast.
12
+
13
+ On first launch, you'll see a setup screen to enter your sync server URL. For local development, use `ws://localhost:3001/kora-sync` (the local sync server started by `pnpm dev`). You can also skip setup to use the app in local-only mode.
14
+
15
+ ## Project Structure
16
+
17
+ ```
18
+ src/
19
+ schema.ts # Data schema definition
20
+ main.tsx # Entry point
21
+ AppShell.tsx # Setup flow + Kora initialization
22
+ App.tsx # Main application UI
23
+ SetupScreen.tsx # First-launch server configuration
24
+ sync-config.ts # Runtime sync URL storage
25
+ updater.ts # Auto-update checker
26
+ src-tauri/
27
+ Cargo.toml # Rust dependencies (Kora SQLite + updater plugins)
28
+ tauri.conf.json # Window, bundle, and updater config
29
+ capabilities/ # Tauri security permissions
30
+ src/
31
+ main.rs # Rust entry point
32
+ lib.rs # Plugin registration
33
+ server.ts # Kora sync server
34
+ dev.ts # Dev orchestrator (starts sync + Tauri together)
35
+ kora.config.ts # Kora configuration
36
+ .github/workflows/
37
+ release-desktop.yml # CI/CD for cross-platform builds
38
+ ```
39
+
40
+ ## Scripts
41
+
42
+ | Script | Description |
43
+ |--------|-------------|
44
+ | `pnpm dev` | Start sync server + Tauri app together |
45
+ | `pnpm dev:app` | Start Tauri app only (no sync server) |
46
+ | `pnpm dev:server` | Start sync server only |
47
+ | `pnpm build` | Build desktop app for distribution |
48
+ | `pnpm deploy:server` | Deploy sync server to the cloud |
49
+
50
+ ## Distributing to Organizations
51
+
52
+ This app is designed to be distributed to multiple organizations. Each organization gets the **same binary** and connects to their own sync server.
53
+
54
+ ### 1. Deploy a sync server for each organization
55
+
56
+ ```bash
57
+ pnpm deploy:server
58
+ ```
59
+
60
+ Or deploy manually to any Node.js host. Each org gets their own server (or share one with multi-tenant scoping).
61
+
62
+ ### 2. Build the desktop binary
63
+
64
+ ```bash
65
+ pnpm build
66
+ ```
67
+
68
+ No need to bake in a sync URL — users configure it on first launch.
69
+
70
+ If you want to pre-configure the URL (e.g., for a specific org):
71
+
72
+ ```bash
73
+ VITE_SYNC_URL=wss://acme-corp.example.com/kora-sync pnpm build
74
+ ```
75
+
76
+ ### 3. Set up auto-updates
77
+
78
+ 1. Generate signing keys:
79
+ ```bash
80
+ pnpm tauri signer generate -w ~/.tauri/myapp.key
81
+ ```
82
+
83
+ 2. Add the public key to `src-tauri/tauri.conf.json` under `plugins.updater.pubkey`.
84
+
85
+ 3. Set the update endpoint:
86
+ ```json
87
+ "endpoints": ["https://github.com/YOUR_ORG/YOUR_REPO/releases/latest/download/latest.json"]
88
+ ```
89
+
90
+ 4. Add `TAURI_SIGNING_PRIVATE_KEY` and `TAURI_SIGNING_PRIVATE_KEY_PASSWORD` to your GitHub repo secrets.
91
+
92
+ 5. Push a version tag to trigger a release:
93
+ ```bash
94
+ git tag v1.0.0 && git push origin v1.0.0
95
+ ```
96
+
97
+ The GitHub Actions workflow builds for macOS, Windows, and Linux, creating a draft release with all installers.
98
+
99
+ ### 4. Distribute installers
100
+
101
+ Built installers are in `src-tauri/target/release/bundle/`:
102
+
103
+ | Platform | Output |
104
+ |----------|--------|
105
+ | macOS | `.dmg` and `.app` bundle |
106
+ | Windows | `.msi` and `.exe` installer |
107
+ | Linux | `.deb`, `.rpm`, `.AppImage` |
108
+
109
+ Share these with your users. Installed apps auto-update when you push new releases.
110
+
111
+ ## First-Launch Experience
112
+
113
+ When users install and open the app:
114
+
115
+ 1. **Setup screen** asks for the sync server URL
116
+ 2. User enters the URL provided by their organization admin
117
+ 3. App connects, verifies the server, and saves the URL locally
118
+ 4. On subsequent launches, the app connects automatically
119
+
120
+ Users can also skip setup and use the app offline — they can connect later from the settings gear icon.
121
+
122
+ ## Environment Variables
123
+
124
+ | Variable | Default | Description |
125
+ |----------|---------|-------------|
126
+ | `VITE_SYNC_URL` | (none) | Pre-configure sync URL at build time |
127
+ | `PORT` | `3001` | Sync server port |
128
+
129
+ ## Code Signing
130
+
131
+ ### macOS
132
+
133
+ For distribution outside the Mac App Store, you need a Developer ID certificate from Apple:
134
+
135
+ 1. Enroll in the [Apple Developer Program](https://developer.apple.com/programs/)
136
+ 2. Create a "Developer ID Application" certificate
137
+ 3. Add the certificate and credentials to your GitHub secrets (see `.github/workflows/release-desktop.yml`)
138
+
139
+ ### Windows
140
+
141
+ For SmartScreen trust, get an EV code signing certificate from a provider like DigiCert or Sectigo. Set the certificate in your CI environment.
142
+
143
+ ## Learn More
144
+
145
+ - [Tauri Desktop Guide](https://ehoneahobed.github.io/kora/guide/tauri-desktop)
146
+ - [Deployment Guide](https://ehoneahobed.github.io/kora/guide/deployment)
147
+ - [Sync Configuration](https://ehoneahobed.github.io/kora/guide/sync-configuration)
148
+ - [Schema Design](https://ehoneahobed.github.io/kora/guide/schema-design)
@@ -0,0 +1,37 @@
1
+ import { spawn, type ChildProcess } from 'node:child_process'
2
+
3
+ // Starts both the sync server and the Tauri app with a single command.
4
+ // The sync server runs in the background so the desktop app can sync
5
+ // data across devices during development.
6
+
7
+ const children: ChildProcess[] = []
8
+
9
+ function cleanup() {
10
+ for (const child of children) {
11
+ child.kill()
12
+ }
13
+ process.exit()
14
+ }
15
+
16
+ process.on('SIGINT', cleanup)
17
+ process.on('SIGTERM', cleanup)
18
+
19
+ // Start the sync server
20
+ const syncServer = spawn('tsx', ['server.ts'], {
21
+ stdio: 'inherit',
22
+ shell: true,
23
+ })
24
+ children.push(syncServer)
25
+
26
+ // Start the Tauri app (manages Vite dev server + Rust build)
27
+ const tauriApp = spawn('tauri', ['dev'], {
28
+ stdio: 'inherit',
29
+ shell: true,
30
+ })
31
+ children.push(tauriApp)
32
+
33
+ // If the Tauri app exits, stop everything
34
+ tauriApp.on('close', (code) => {
35
+ syncServer.kill()
36
+ process.exit(code ?? 0)
37
+ })
@@ -0,0 +1,16 @@
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>{{projectName}}</title>
7
+ <style>
8
+ * { margin: 0; padding: 0; box-sizing: border-box; }
9
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
10
+ </style>
11
+ </head>
12
+ <body>
13
+ <div id="root"></div>
14
+ <script type="module" src="/src/main.tsx"></script>
15
+ </body>
16
+ </html>
@@ -0,0 +1,17 @@
1
+ import { defineConfig } from 'korajs/config'
2
+
3
+ export default defineConfig({
4
+ schema: './src/schema.ts',
5
+ dev: {
6
+ port: 5173,
7
+ sync: {
8
+ enabled: true,
9
+ port: 3001,
10
+ store: 'sqlite',
11
+ },
12
+ watch: {
13
+ enabled: true,
14
+ debounceMs: 300,
15
+ },
16
+ },
17
+ })
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "tsx dev.ts",
8
+ "dev:app": "tauri dev",
9
+ "dev:server": "tsx server.ts",
10
+ "build": "tauri build",
11
+ "start:server": "node --import tsx server.ts",
12
+ "deploy:server": "kora deploy"
13
+ },
14
+ "dependencies": {
15
+ "korajs": "{{koraVersion}}",
16
+ "@korajs/core": "{{koraVersion}}",
17
+ "@korajs/react": "{{koraVersion}}",
18
+ "@korajs/tauri": "{{koraVersion}}",
19
+ "@tauri-apps/api": "^2.0.0",
20
+ "@tauri-apps/plugin-updater": "^2.0.0",
21
+ "lucide-react": "^0.468.0",
22
+ "react": "^19.0.0",
23
+ "react-dom": "^19.0.0"
24
+ },
25
+ "devDependencies": {
26
+ "@korajs/cli": "{{koraVersion}}",
27
+ "@korajs/server": "{{koraVersion}}",
28
+ "@tauri-apps/cli": "^2.0.0",
29
+ "@types/react": "^19.0.0",
30
+ "@types/react-dom": "^19.0.0",
31
+ "@vitejs/plugin-react": "^4.3.0",
32
+ "better-sqlite3": "^12.9.0",
33
+ "tsx": "^4.19.0",
34
+ "typescript": "^5.7.0",
35
+ "vite": "^6.0.0",
36
+ "ws": "^8.18.0"
37
+ },
38
+ "pnpm": {
39
+ "onlyBuiltDependencies": [
40
+ "better-sqlite3",
41
+ "esbuild"
42
+ ]
43
+ }
44
+ }
@@ -0,0 +1,23 @@
1
+ import { createProductionServer, createSqliteServerStore } from '@korajs/server'
2
+
3
+ // Sync server for your Kora desktop app.
4
+ // Started automatically by `pnpm dev`, or run standalone with `pnpm dev:server`.
5
+ // Deploy with `pnpm deploy:server` (uses kora deploy).
6
+ //
7
+ // All desktop clients connect to this server to sync data across devices.
8
+ // For production, deploy this server and set VITE_SYNC_URL when building
9
+ // the desktop app: VITE_SYNC_URL=wss://your-server.com/kora-sync pnpm build
10
+
11
+ const store = createSqliteServerStore({ filename: './kora-server.db' })
12
+
13
+ const server = createProductionServer({
14
+ store,
15
+ port: Number(process.env.PORT) || 3001,
16
+ staticDir: './dist',
17
+ syncPath: '/kora-sync',
18
+ })
19
+
20
+ server.start().then((url) => {
21
+ console.log(`Kora sync server running at ${url}`)
22
+ console.log(` Sync endpoint: ${url.replace('http', 'ws')}/kora-sync`)
23
+ })