mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-10-07 02:58:11 +00:00
initial commit
This commit is contained in:
parent
cf47d73126
commit
6a4d59ccf5
17 changed files with 367 additions and 0 deletions
13
apps/desktop/.gitignore
vendored
Normal file
13
apps/desktop/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# typescript
|
||||
next-env.d.ts
|
||||
*.tsbuildinfo
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
28
apps/desktop/README.md
Normal file
28
apps/desktop/README.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# @repo/desktop
|
||||
|
||||
Supermemory desktop app — a [Tauri v2](https://v2.tauri.app) shell around the
|
||||
Supermemory web UI (Next.js static export), talking to `api.supermemory.ai`.
|
||||
|
||||
Design docs live in `/.context/desktop-app-*.md` (spec, roadmap, architecture).
|
||||
|
||||
## Develop
|
||||
|
||||
```sh
|
||||
# from this directory — launches the native window and spawns `next dev` on :3001
|
||||
bun run tauri dev
|
||||
```
|
||||
|
||||
`bun run dev` on its own just starts the Next dev server on :3001 (no native window).
|
||||
|
||||
## Build
|
||||
|
||||
```sh
|
||||
bun run build # Next static export -> ./out (no Rust needed)
|
||||
bun run tauri build # native .app / .dmg (requires the Rust toolchain)
|
||||
```
|
||||
|
||||
## Prerequisites for the native build
|
||||
|
||||
- Rust toolchain (`rustup`) + Xcode Command Line Tools.
|
||||
- App icons in `src-tauri/icons/` — generate once with
|
||||
`bun run tauri icon <path-to-1024px.png>`.
|
||||
71
apps/desktop/app/globals.css
Normal file
71
apps/desktop/app/globals.css
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
:root {
|
||||
color-scheme: light dark;
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
|
||||
sans-serif;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.screen {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 100vh;
|
||||
background: radial-gradient(125% 125% at 50% 0%, #1b1b2f 0%, #0c0c12 60%);
|
||||
color: #ececf1;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: 360px;
|
||||
padding: 2rem;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 1rem;
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.muted {
|
||||
margin: 0.25rem 0 1.5rem;
|
||||
color: #9a9ab0;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.info {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.row dt {
|
||||
color: #9a9ab0;
|
||||
}
|
||||
|
||||
.row dd {
|
||||
margin: 0;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #ff6b6b;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
15
apps/desktop/app/layout.tsx
Normal file
15
apps/desktop/app/layout.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import type { ReactNode } from "react"
|
||||
import "./globals.css"
|
||||
|
||||
export const metadata = {
|
||||
title: "Supermemory",
|
||||
description: "Supermemory Desktop",
|
||||
}
|
||||
|
||||
export default function RootLayout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
53
apps/desktop/app/page.tsx
Normal file
53
apps/desktop/app/page.tsx
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
"use client"
|
||||
|
||||
import { invoke } from "@tauri-apps/api/core"
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
type AppInfo = {
|
||||
name: string
|
||||
version: string
|
||||
platform: string
|
||||
}
|
||||
|
||||
export default function Home() {
|
||||
const [info, setInfo] = useState<AppInfo | null>(null)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
// Call into the Rust core over Tauri's IPC bridge. If this resolves, the
|
||||
// native layer is alive and wired to the webview — the Phase 0 goal.
|
||||
invoke<AppInfo>("app_info")
|
||||
.then(setInfo)
|
||||
.catch((err) => setError(String(err)))
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<main className="screen">
|
||||
<section className="card">
|
||||
<h1 className="title">Supermemory</h1>
|
||||
<p className="muted">Desktop · Phase 0</p>
|
||||
|
||||
{info ? (
|
||||
<dl className="info">
|
||||
<div className="row">
|
||||
<dt>App</dt>
|
||||
<dd>{info.name}</dd>
|
||||
</div>
|
||||
<div className="row">
|
||||
<dt>Version</dt>
|
||||
<dd>{info.version}</dd>
|
||||
</div>
|
||||
<div className="row">
|
||||
<dt>Platform</dt>
|
||||
<dd>{info.platform}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
) : error ? (
|
||||
<p className="error">Native bridge error: {error}</p>
|
||||
) : (
|
||||
<p className="muted">Connecting to the native core…</p>
|
||||
)}
|
||||
</section>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
5
apps/desktop/biome.json
Normal file
5
apps/desktop/biome.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"root": false,
|
||||
"extends": "//",
|
||||
"$schema": "https://biomejs.dev/schemas/2.4.6/schema.json"
|
||||
}
|
||||
14
apps/desktop/next.config.ts
Normal file
14
apps/desktop/next.config.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import type { NextConfig } from "next"
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
// Tauri serves a static bundle from disk — there is no Node server at runtime,
|
||||
// so the app is exported to plain HTML/JS/CSS in ./out.
|
||||
output: "export",
|
||||
// The static export has no server-side image optimizer.
|
||||
images: { unoptimized: true },
|
||||
// Emit `route/index.html` files so the webview can resolve nested routes
|
||||
// (e.g. /spotlight) directly from the bundled filesystem.
|
||||
trailingSlash: true,
|
||||
}
|
||||
|
||||
export default nextConfig
|
||||
24
apps/desktop/package.json
Normal file
24
apps/desktop/package.json
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "@repo/desktop",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --port 3001",
|
||||
"build": "next build",
|
||||
"check-types": "tsc --noEmit",
|
||||
"tauri": "tauri"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2",
|
||||
"next": "^16.0.11",
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^2",
|
||||
"@types/node": "^24.0.4",
|
||||
"@types/react": "^19.2.9",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"typescript": "^5.8.3"
|
||||
}
|
||||
}
|
||||
5
apps/desktop/src-tauri/.gitignore
vendored
Normal file
5
apps/desktop/src-tauri/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Rust build output
|
||||
/target
|
||||
|
||||
# Tauri-generated schemas / artifacts
|
||||
/gen/schemas
|
||||
19
apps/desktop/src-tauri/Cargo.toml
Normal file
19
apps/desktop/src-tauri/Cargo.toml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "supermemory-desktop"
|
||||
version = "0.1.0"
|
||||
description = "Supermemory Desktop"
|
||||
edition = "2021"
|
||||
rust-version = "1.77.2"
|
||||
|
||||
[lib]
|
||||
# The app logic lives in a library crate so it can be shared with a future
|
||||
# mobile target; `main.rs` is a thin binary that calls into it.
|
||||
name = "supermemory_desktop_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "2", features = [] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
3
apps/desktop/src-tauri/build.rs
Normal file
3
apps/desktop/src-tauri/build.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fn main() {
|
||||
tauri_build::build()
|
||||
}
|
||||
7
apps/desktop/src-tauri/capabilities/default.json
Normal file
7
apps/desktop/src-tauri/capabilities/default.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "Core capabilities granted to the main window.",
|
||||
"windows": ["main"],
|
||||
"permissions": ["core:default"]
|
||||
}
|
||||
32
apps/desktop/src-tauri/src/lib.rs
Normal file
32
apps/desktop/src-tauri/src/lib.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
use serde::Serialize;
|
||||
|
||||
/// Identity of the native app, surfaced to the webview over IPC.
|
||||
/// `rename_all = "camelCase"` makes the JSON keys match the TypeScript `AppInfo`.
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct AppInfo {
|
||||
name: String,
|
||||
version: String,
|
||||
platform: String,
|
||||
}
|
||||
|
||||
/// First proof that the webview <-> Rust IPC bridge is wired: the placeholder
|
||||
/// page calls `invoke("app_info")` on mount and renders the result.
|
||||
#[tauri::command]
|
||||
fn app_info() -> AppInfo {
|
||||
AppInfo {
|
||||
name: "Supermemory".to_string(),
|
||||
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
platform: std::env::consts::OS.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
tauri::Builder::default()
|
||||
.invoke_handler(tauri::generate_handler![app_info])
|
||||
// Bootstrap failure is unrecoverable (no window, no app), so we abort
|
||||
// loudly here. This is the one sanctioned `expect` — see roadmap quality bar.
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
7
apps/desktop/src-tauri/src/main.rs
Normal file
7
apps/desktop/src-tauri/src/main.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// On Windows release builds, prevent a console window from opening alongside
|
||||
// the app. No-op on macOS/Linux. Kept now so the entry point is cross-platform.
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
fn main() {
|
||||
supermemory_desktop_lib::run()
|
||||
}
|
||||
40
apps/desktop/src-tauri/tauri.conf.json
Normal file
40
apps/desktop/src-tauri/tauri.conf.json
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Supermemory",
|
||||
"version": "0.1.0",
|
||||
"identifier": "ai.supermemory.desktop",
|
||||
"build": {
|
||||
"beforeDevCommand": "bun run dev",
|
||||
"devUrl": "http://localhost:3001",
|
||||
"beforeBuildCommand": "bun run build",
|
||||
"frontendDist": "../out"
|
||||
},
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"label": "main",
|
||||
"title": "Supermemory",
|
||||
"width": 1100,
|
||||
"height": 720,
|
||||
"minWidth": 720,
|
||||
"minHeight": 480,
|
||||
"titleBarStyle": "Overlay",
|
||||
"hiddenTitle": true
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": null
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": ["app", "dmg"],
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
]
|
||||
}
|
||||
}
|
||||
17
apps/desktop/tsconfig.json
Normal file
17
apps/desktop/tsconfig.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"incremental": true,
|
||||
"jsx": "preserve",
|
||||
"paths": {
|
||||
"@/*": ["./*"],
|
||||
"@ui/*": ["../../packages/ui/*"],
|
||||
"@repo/ui/*": ["../../packages/ui/*"],
|
||||
"@lib/*": ["../../packages/lib/*"],
|
||||
"@hooks/*": ["../../packages/hooks/*"]
|
||||
},
|
||||
"plugins": [{ "name": "next" }]
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"extends": "@total-typescript/tsconfig/bundler/dom/app",
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"]
|
||||
}
|
||||
14
apps/desktop/turbo.json
Normal file
14
apps/desktop/turbo.json
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"$schema": "https://turborepo.com/schema.json",
|
||||
"extends": ["//"],
|
||||
"tasks": {
|
||||
"build": {
|
||||
"dependsOn": ["^build"],
|
||||
"outputs": ["out/**"]
|
||||
},
|
||||
"dev": {
|
||||
"cache": false,
|
||||
"persistent": true
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue