img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
+ className
+ )}
+ {...props}
+ />
+ )
+}
+
+function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardAction({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardContent({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+export {
+ Card,
+ CardHeader,
+ CardFooter,
+ CardTitle,
+ CardAction,
+ CardDescription,
+ CardContent,
+}
diff --git a/maxc-landing-page/components/ui/separator.tsx b/maxc-landing-page/components/ui/separator.tsx
new file mode 100644
index 0000000..d457090
--- /dev/null
+++ b/maxc-landing-page/components/ui/separator.tsx
@@ -0,0 +1,28 @@
+"use client"
+
+import * as React from "react"
+import { Separator as SeparatorPrimitive } from "radix-ui"
+
+import { cn } from "@/lib/utils"
+
+function Separator({
+ className,
+ orientation = "horizontal",
+ decorative = true,
+ ...props
+}: React.ComponentProps
) {
+ return (
+
+ )
+}
+
+export { Separator }
diff --git a/maxc-landing-page/eslint.config.mjs b/maxc-landing-page/eslint.config.mjs
new file mode 100644
index 0000000..05e726d
--- /dev/null
+++ b/maxc-landing-page/eslint.config.mjs
@@ -0,0 +1,18 @@
+import { defineConfig, globalIgnores } from "eslint/config";
+import nextVitals from "eslint-config-next/core-web-vitals";
+import nextTs from "eslint-config-next/typescript";
+
+const eslintConfig = defineConfig([
+ ...nextVitals,
+ ...nextTs,
+ // Override default ignores of eslint-config-next.
+ globalIgnores([
+ // Default ignores of eslint-config-next:
+ ".next/**",
+ "out/**",
+ "build/**",
+ "next-env.d.ts",
+ ]),
+]);
+
+export default eslintConfig;
diff --git a/maxc-landing-page/lib/utils.ts b/maxc-landing-page/lib/utils.ts
new file mode 100644
index 0000000..bd0c391
--- /dev/null
+++ b/maxc-landing-page/lib/utils.ts
@@ -0,0 +1,6 @@
+import { clsx, type ClassValue } from "clsx"
+import { twMerge } from "tailwind-merge"
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs))
+}
diff --git a/maxc-landing-page/next.config.ts b/maxc-landing-page/next.config.ts
new file mode 100644
index 0000000..e9ffa30
--- /dev/null
+++ b/maxc-landing-page/next.config.ts
@@ -0,0 +1,7 @@
+import type { NextConfig } from "next";
+
+const nextConfig: NextConfig = {
+ /* config options here */
+};
+
+export default nextConfig;
diff --git a/maxc-landing-page/package.json b/maxc-landing-page/package.json
new file mode 100644
index 0000000..1b53571
--- /dev/null
+++ b/maxc-landing-page/package.json
@@ -0,0 +1,35 @@
+{
+ "name": "maxc-landing-page",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "eslint"
+ },
+ "dependencies": {
+ "@vercel/analytics": "^2.0.1",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "framer-motion": "^12.36.0",
+ "lucide-react": "^0.577.0",
+ "next": "16.1.6",
+ "radix-ui": "^1.4.3",
+ "react": "19.2.3",
+ "react-dom": "19.2.3",
+ "shadcn": "^4.0.8",
+ "tailwind-merge": "^3.5.0",
+ "tw-animate-css": "^1.4.0"
+ },
+ "devDependencies": {
+ "@tailwindcss/postcss": "^4",
+ "@types/node": "^20",
+ "@types/react": "^19",
+ "@types/react-dom": "^19",
+ "eslint": "^9",
+ "eslint-config-next": "16.1.6",
+ "tailwindcss": "^4",
+ "typescript": "^5"
+ }
+}
diff --git a/maxc-landing-page/postcss.config.mjs b/maxc-landing-page/postcss.config.mjs
new file mode 100644
index 0000000..61e3684
--- /dev/null
+++ b/maxc-landing-page/postcss.config.mjs
@@ -0,0 +1,7 @@
+const config = {
+ plugins: {
+ "@tailwindcss/postcss": {},
+ },
+};
+
+export default config;
diff --git a/maxc-landing-page/public/apple-logo-svgrepo-com.svg b/maxc-landing-page/public/apple-logo-svgrepo-com.svg
new file mode 100644
index 0000000..51ded04
--- /dev/null
+++ b/maxc-landing-page/public/apple-logo-svgrepo-com.svg
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/maxc-landing-page/public/file.svg b/maxc-landing-page/public/file.svg
new file mode 100644
index 0000000..004145c
--- /dev/null
+++ b/maxc-landing-page/public/file.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/maxc-landing-page/public/globe.svg b/maxc-landing-page/public/globe.svg
new file mode 100644
index 0000000..567f17b
--- /dev/null
+++ b/maxc-landing-page/public/globe.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/maxc-landing-page/public/linux-svgrepo-com.svg b/maxc-landing-page/public/linux-svgrepo-com.svg
new file mode 100644
index 0000000..bd05879
--- /dev/null
+++ b/maxc-landing-page/public/linux-svgrepo-com.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/maxc-landing-page/public/maxc_logo_dark.svg b/maxc-landing-page/public/maxc_logo_dark.svg
new file mode 100644
index 0000000..cd53269
--- /dev/null
+++ b/maxc-landing-page/public/maxc_logo_dark.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/maxc-landing-page/public/maxc_logo_full_dark_single.svg b/maxc-landing-page/public/maxc_logo_full_dark_single.svg
new file mode 100644
index 0000000..4a0823c
--- /dev/null
+++ b/maxc-landing-page/public/maxc_logo_full_dark_single.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/maxc-landing-page/public/maxc_logo_full_white_single.svg b/maxc-landing-page/public/maxc_logo_full_white_single.svg
new file mode 100644
index 0000000..b9a75ec
--- /dev/null
+++ b/maxc-landing-page/public/maxc_logo_full_white_single.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/maxc-landing-page/public/maxc_logo_white.svg b/maxc-landing-page/public/maxc_logo_white.svg
new file mode 100644
index 0000000..45a0bc3
--- /dev/null
+++ b/maxc-landing-page/public/maxc_logo_white.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/maxc-landing-page/public/next.svg b/maxc-landing-page/public/next.svg
new file mode 100644
index 0000000..5174b28
--- /dev/null
+++ b/maxc-landing-page/public/next.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/maxc-landing-page/public/robots.txt b/maxc-landing-page/public/robots.txt
new file mode 100644
index 0000000..4d48990
--- /dev/null
+++ b/maxc-landing-page/public/robots.txt
@@ -0,0 +1,4 @@
+User-agent: *
+Allow: /
+
+Sitemap: https://maxc.polluxstudio.in/sitemap.xml
diff --git a/maxc-landing-page/public/vercel.svg b/maxc-landing-page/public/vercel.svg
new file mode 100644
index 0000000..7705396
--- /dev/null
+++ b/maxc-landing-page/public/vercel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/maxc-landing-page/public/window.svg b/maxc-landing-page/public/window.svg
new file mode 100644
index 0000000..b2b2a44
--- /dev/null
+++ b/maxc-landing-page/public/window.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/maxc-landing-page/tsconfig.json b/maxc-landing-page/tsconfig.json
new file mode 100644
index 0000000..3a13f90
--- /dev/null
+++ b/maxc-landing-page/tsconfig.json
@@ -0,0 +1,34 @@
+{
+ "compilerOptions": {
+ "target": "ES2017",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "react-jsx",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@/*": ["./*"]
+ }
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts",
+ ".next/dev/types/**/*.ts",
+ "**/*.mts"
+ ],
+ "exclude": ["node_modules"]
+}
diff --git a/maxc_desktop/src-tauri/icons/128x128.png b/maxc_desktop/src-tauri/icons/128x128.png
index 6061a3e..e572a48 100644
Binary files a/maxc_desktop/src-tauri/icons/128x128.png and b/maxc_desktop/src-tauri/icons/128x128.png differ
diff --git a/maxc_desktop/src-tauri/icons/128x128@2x.png b/maxc_desktop/src-tauri/icons/128x128@2x.png
index 02522f2..affd62c 100644
Binary files a/maxc_desktop/src-tauri/icons/128x128@2x.png and b/maxc_desktop/src-tauri/icons/128x128@2x.png differ
diff --git a/maxc_desktop/src-tauri/icons/32x32.png b/maxc_desktop/src-tauri/icons/32x32.png
index dbe6064..6a77b34 100644
Binary files a/maxc_desktop/src-tauri/icons/32x32.png and b/maxc_desktop/src-tauri/icons/32x32.png differ
diff --git a/maxc_desktop/src-tauri/icons/64x64.png b/maxc_desktop/src-tauri/icons/64x64.png
index ee8ca56..06ac15c 100644
Binary files a/maxc_desktop/src-tauri/icons/64x64.png and b/maxc_desktop/src-tauri/icons/64x64.png differ
diff --git a/maxc_desktop/src-tauri/icons/Square107x107Logo.png b/maxc_desktop/src-tauri/icons/Square107x107Logo.png
index 04b896b..f49c977 100644
Binary files a/maxc_desktop/src-tauri/icons/Square107x107Logo.png and b/maxc_desktop/src-tauri/icons/Square107x107Logo.png differ
diff --git a/maxc_desktop/src-tauri/icons/Square142x142Logo.png b/maxc_desktop/src-tauri/icons/Square142x142Logo.png
index 5218115..f4ca777 100644
Binary files a/maxc_desktop/src-tauri/icons/Square142x142Logo.png and b/maxc_desktop/src-tauri/icons/Square142x142Logo.png differ
diff --git a/maxc_desktop/src-tauri/icons/Square150x150Logo.png b/maxc_desktop/src-tauri/icons/Square150x150Logo.png
index 7fe268b..a9be390 100644
Binary files a/maxc_desktop/src-tauri/icons/Square150x150Logo.png and b/maxc_desktop/src-tauri/icons/Square150x150Logo.png differ
diff --git a/maxc_desktop/src-tauri/icons/Square284x284Logo.png b/maxc_desktop/src-tauri/icons/Square284x284Logo.png
index d9a4738..3189931 100644
Binary files a/maxc_desktop/src-tauri/icons/Square284x284Logo.png and b/maxc_desktop/src-tauri/icons/Square284x284Logo.png differ
diff --git a/maxc_desktop/src-tauri/icons/Square30x30Logo.png b/maxc_desktop/src-tauri/icons/Square30x30Logo.png
index 6d04ccd..4778b28 100644
Binary files a/maxc_desktop/src-tauri/icons/Square30x30Logo.png and b/maxc_desktop/src-tauri/icons/Square30x30Logo.png differ
diff --git a/maxc_desktop/src-tauri/icons/Square310x310Logo.png b/maxc_desktop/src-tauri/icons/Square310x310Logo.png
index 57fc8dc..cf0bf64 100644
Binary files a/maxc_desktop/src-tauri/icons/Square310x310Logo.png and b/maxc_desktop/src-tauri/icons/Square310x310Logo.png differ
diff --git a/maxc_desktop/src-tauri/icons/Square44x44Logo.png b/maxc_desktop/src-tauri/icons/Square44x44Logo.png
index a6624b1..ae83744 100644
Binary files a/maxc_desktop/src-tauri/icons/Square44x44Logo.png and b/maxc_desktop/src-tauri/icons/Square44x44Logo.png differ
diff --git a/maxc_desktop/src-tauri/icons/Square71x71Logo.png b/maxc_desktop/src-tauri/icons/Square71x71Logo.png
index 9b8114d..7fc6fab 100644
Binary files a/maxc_desktop/src-tauri/icons/Square71x71Logo.png and b/maxc_desktop/src-tauri/icons/Square71x71Logo.png differ
diff --git a/maxc_desktop/src-tauri/icons/Square89x89Logo.png b/maxc_desktop/src-tauri/icons/Square89x89Logo.png
index 098c959..d0d9b3c 100644
Binary files a/maxc_desktop/src-tauri/icons/Square89x89Logo.png and b/maxc_desktop/src-tauri/icons/Square89x89Logo.png differ
diff --git a/maxc_desktop/src-tauri/icons/StoreLogo.png b/maxc_desktop/src-tauri/icons/StoreLogo.png
index 5b99242..9c92165 100644
Binary files a/maxc_desktop/src-tauri/icons/StoreLogo.png and b/maxc_desktop/src-tauri/icons/StoreLogo.png differ
diff --git a/maxc_desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png b/maxc_desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png
index db90a65..62c7740 100644
Binary files a/maxc_desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png and b/maxc_desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png differ
diff --git a/maxc_desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png b/maxc_desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png
index 1859d09..6a0091a 100644
Binary files a/maxc_desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png and b/maxc_desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/maxc_desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png b/maxc_desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png
index bb5c1a1..a13c9db 100644
Binary files a/maxc_desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png and b/maxc_desktop/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/maxc_desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png b/maxc_desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png
index acb8307..c0b7c74 100644
Binary files a/maxc_desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png and b/maxc_desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png differ
diff --git a/maxc_desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png b/maxc_desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png
index 229ab37..f6aa3a3 100644
Binary files a/maxc_desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png and b/maxc_desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/maxc_desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png b/maxc_desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png
index da6a97e..6c4db50 100644
Binary files a/maxc_desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png and b/maxc_desktop/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/maxc_desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png b/maxc_desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png
index 1825044..3b7040b 100644
Binary files a/maxc_desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png and b/maxc_desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png differ
diff --git a/maxc_desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png b/maxc_desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png
index e94c20b..2fcd9b6 100644
Binary files a/maxc_desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png and b/maxc_desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/maxc_desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png b/maxc_desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png
index 74d318a..7edee03 100644
Binary files a/maxc_desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png and b/maxc_desktop/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/maxc_desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png b/maxc_desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png
index 4410a09..a44a382 100644
Binary files a/maxc_desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png and b/maxc_desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/maxc_desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png b/maxc_desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png
index e2c69c2..3080049 100644
Binary files a/maxc_desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png and b/maxc_desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/maxc_desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png b/maxc_desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png
index 8f83704..8564d05 100644
Binary files a/maxc_desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png and b/maxc_desktop/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/maxc_desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png b/maxc_desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png
index e5e3f0d..eeacbaa 100644
Binary files a/maxc_desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png and b/maxc_desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/maxc_desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png b/maxc_desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png
index bc66a02..d8b2b33 100644
Binary files a/maxc_desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png and b/maxc_desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/maxc_desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png b/maxc_desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png
index 3496176..0f88f66 100644
Binary files a/maxc_desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png and b/maxc_desktop/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/maxc_desktop/src-tauri/icons/icon.icns b/maxc_desktop/src-tauri/icons/icon.icns
index 58b5de2..cd69e2d 100644
Binary files a/maxc_desktop/src-tauri/icons/icon.icns and b/maxc_desktop/src-tauri/icons/icon.icns differ
diff --git a/maxc_desktop/src-tauri/icons/icon.ico b/maxc_desktop/src-tauri/icons/icon.ico
index 0a1aa64..f9cbc13 100644
Binary files a/maxc_desktop/src-tauri/icons/icon.ico and b/maxc_desktop/src-tauri/icons/icon.ico differ
diff --git a/maxc_desktop/src-tauri/icons/icon.png b/maxc_desktop/src-tauri/icons/icon.png
index 3171898..1e6e364 100644
Binary files a/maxc_desktop/src-tauri/icons/icon.png and b/maxc_desktop/src-tauri/icons/icon.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-20x20@1x.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-20x20@1x.png
index bb90734..19c78e8 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-20x20@1x.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-20x20@1x.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-20x20@2x-1.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-20x20@2x-1.png
index 56f37ec..5f8efb6 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-20x20@2x-1.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-20x20@2x-1.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-20x20@2x.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-20x20@2x.png
index 56f37ec..5f8efb6 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-20x20@2x.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-20x20@2x.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-20x20@3x.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-20x20@3x.png
index 637f43c..2c55293 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-20x20@3x.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-20x20@3x.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-29x29@1x.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-29x29@1x.png
index a30e841..1bf9f0f 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-29x29@1x.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-29x29@1x.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-29x29@2x-1.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-29x29@2x-1.png
index 7104d80..3d444bf 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-29x29@2x-1.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-29x29@2x-1.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-29x29@2x.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-29x29@2x.png
index 7104d80..3d444bf 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-29x29@2x.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-29x29@2x.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-29x29@3x.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-29x29@3x.png
index 9e20913..138bd33 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-29x29@3x.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-29x29@3x.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-40x40@1x.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-40x40@1x.png
index 56f37ec..5f8efb6 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-40x40@1x.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-40x40@1x.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-40x40@2x-1.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-40x40@2x-1.png
index 9901aed..6cc980f 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-40x40@2x-1.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-40x40@2x-1.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-40x40@2x.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-40x40@2x.png
index 9901aed..6cc980f 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-40x40@2x.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-40x40@2x.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-40x40@3x.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-40x40@3x.png
index 4198d76..9999c67 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-40x40@3x.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-40x40@3x.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-512@2x.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-512@2x.png
index 7b5b70f..a66a9d4 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-512@2x.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-512@2x.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-60x60@2x.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-60x60@2x.png
index 4198d76..9999c67 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-60x60@2x.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-60x60@2x.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-60x60@3x.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-60x60@3x.png
index 8ffd068..55197bb 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-60x60@3x.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-60x60@3x.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-76x76@1x.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-76x76@1x.png
index f8302e4..5f49dec 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-76x76@1x.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-76x76@1x.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-76x76@2x.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-76x76@2x.png
index d12831d..2bb8482 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-76x76@2x.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-76x76@2x.png differ
diff --git a/maxc_desktop/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png b/maxc_desktop/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png
index 58125b4..296f156 100644
Binary files a/maxc_desktop/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png and b/maxc_desktop/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png differ
diff --git a/maxc_desktop/src-tauri/src/lib.rs b/maxc_desktop/src-tauri/src/lib.rs
index b1a91e1..139af8e 100644
--- a/maxc_desktop/src-tauri/src/lib.rs
+++ b/maxc_desktop/src-tauri/src/lib.rs
@@ -1,10 +1,10 @@
-use std::path::Path;
+use std::path::{Path, PathBuf};
use std::sync::{Arc, OnceLock};
use std::time::{SystemTime, UNIX_EPOCH};
use maxc_automation::RpcServer;
use maxc_core::BackendConfig;
-use tauri::State;
+use tauri::{Manager, State};
use tauri_plugin_updater::UpdaterExt;
use url::Url;
@@ -15,8 +15,17 @@ struct RpcState {
static RPC_STATE: OnceLock = OnceLock::new();
-fn init_server() -> RpcState {
- let config = BackendConfig::from_env().unwrap_or_else(|_| BackendConfig::default());
+fn init_server(data_dir: Option) -> RpcState {
+ let mut config = BackendConfig::from_env().unwrap_or_else(|_| BackendConfig::default());
+
+ // Resolve event_dir to an absolute path under the app data directory.
+ // On Windows this is %APPDATA%/com.polluxstudio.maxc-desktop/
+ // This ensures the event store is always writable regardless of CWD.
+ if let Some(dir) = data_dir {
+ let events_dir = dir.join("events");
+ config.event_dir = events_dir.to_string_lossy().to_string();
+ }
+
let server = RpcServer::new(config).expect("failed to start backend automation server");
RpcState {
server: Arc::new(server),
@@ -140,20 +149,29 @@ async fn update_download_and_install(app: tauri::AppHandle, channel: String) ->
.download_and_install(|_, _| {}, || {})
.await
.map_err(|e| e.to_string())?;
+
+ // Restart the app after successful update install
+ app.restart();
}
Ok(())
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
- let state = RPC_STATE.get_or_init(init_server).clone();
-
tauri::Builder::default()
- .manage(state)
.plugin(tauri_plugin_opener::init())
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_notification::init())
.plugin(tauri_plugin_updater::Builder::new().build())
+ .setup(|app| {
+ // Resolve the app data directory for reliable event store path.
+ let data_dir = app.path().app_data_dir().ok();
+ let state = RPC_STATE
+ .get_or_init(|| init_server(data_dir))
+ .clone();
+ app.manage(state);
+ Ok(())
+ })
.invoke_handler(tauri::generate_handler![
rpc_call,
get_git_branch,
diff --git a/maxc_desktop/src-tauri/tauri.conf.json b/maxc_desktop/src-tauri/tauri.conf.json
index ff5e732..d5ceb33 100644
--- a/maxc_desktop/src-tauri/tauri.conf.json
+++ b/maxc_desktop/src-tauri/tauri.conf.json
@@ -15,9 +15,13 @@
"title": "maxc",
"width": 1280,
"height": 832,
+ "minWidth": 1100,
+ "minHeight": 720,
"decorations": false,
"center": true,
"maximized": true,
+ "resizable": true,
+ "maximizable": true,
"fullscreen": false
}
],
@@ -25,17 +29,22 @@
"csp": null
}
},
- "bundle": {
- "active": true,
- "targets": "all",
- "createUpdaterArtifacts": true,
- "icon": [
- "icons/32x32.png",
- "icons/128x128.png",
- "icons/128x128@2x.png",
- "icons/icon.icns",
- "icons/icon.ico"
- ]
+ "bundle": {
+ "active": true,
+ "targets": "all",
+ "createUpdaterArtifacts": true,
+ "icon": [
+ "icons/32x32.png",
+ "icons/128x128.png",
+ "icons/128x128@2x.png",
+ "icons/icon.icns",
+ "icons/icon.ico"
+ ],
+ "windows": {
+ "nsis": {
+ "installMode": "currentUser"
+ }
+ }
},
"plugins": {
"updater": {
diff --git a/maxc_desktop/src/App.css b/maxc_desktop/src/App.css
index 2ee91bf..2dcabd9 100644
--- a/maxc_desktop/src/App.css
+++ b/maxc_desktop/src/App.css
@@ -38,6 +38,9 @@
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
+ --scrollbar-thumb: oklch(0.62 0 0 / 0.35);
+ --scrollbar-thumb-hover: oklch(0.52 0 0 / 0.5);
+ --scrollbar-track: transparent;
}
.dark {
@@ -72,6 +75,9 @@
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.556 0 0);
+ --scrollbar-thumb: oklch(0.8 0 0 / 0.25);
+ --scrollbar-thumb-hover: oklch(0.9 0 0 / 0.4);
+ --scrollbar-track: transparent;
}
@theme inline {
@@ -152,3 +158,28 @@
width: 0;
height: 0;
}
+
+.settings-scroll {
+ scrollbar-width: thin;
+ scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
+}
+
+.settings-scroll::-webkit-scrollbar {
+ width: 8px;
+ height: 8px;
+}
+
+.settings-scroll::-webkit-scrollbar-thumb {
+ background: var(--scrollbar-thumb);
+ border-radius: 999px;
+ border: 2px solid transparent;
+ background-clip: content-box;
+}
+
+.settings-scroll::-webkit-scrollbar-thumb:hover {
+ background: var(--scrollbar-thumb-hover);
+}
+
+.settings-scroll::-webkit-scrollbar-track {
+ background: var(--scrollbar-track);
+}
diff --git a/maxc_desktop/src/App.tsx b/maxc_desktop/src/App.tsx
index d500274..02967c8 100644
--- a/maxc_desktop/src/App.tsx
+++ b/maxc_desktop/src/App.tsx
@@ -10,15 +10,15 @@ import {
import { getVersion } from "@tauri-apps/api/app";
import {
Bell,
- ChevronDown,
ChevronRight,
- Check,
FolderOpen,
GitBranch,
Keyboard,
+ Loader2,
Minus,
Moon,
Plus,
+ ScrollText,
Settings,
Square,
Sun,
@@ -29,33 +29,21 @@ import {
import logoDark from "./assets/maxc_logo_dark.svg";
import logoWhite from "./assets/maxc_logo_white.svg";
import { Button } from "@/components/ui/button";
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog";
import { type XtermHandle } from "@/components/XtermTerminal";
import { PaneContainer, type PaneNode, type BrowserState } from "@/components/PaneContainer";
import { type SurfaceState } from "@/components/SurfaceTabBar";
import { NotificationPanel, type NotificationItem } from "@/components/NotificationPanel";
+import { SettingsDialog } from "@/components/SettingsDialog";
import { cn } from "@/lib/utils";
import "./App.css";
-// ---------------------------------------------------------------------------
-// RPC helper
-// ---------------------------------------------------------------------------
-
-async function rpc(method: string, params: Record): Promise {
- const request = {
- id: crypto.randomUUID(),
- method,
- params,
- };
- const raw = await invoke("rpc_call", { request: JSON.stringify(request) });
- const parsed = JSON.parse(raw);
- if (parsed.error) {
- const code = parsed.error.code || "ERROR";
- const message = parsed.error.message || "Unknown error";
- throw new Error(code + ": " + message);
- }
- return parsed.result as T;
-}
-
// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------
@@ -84,14 +72,146 @@ type Readiness = {
};
type EnvEntry = { key: string; value: string };
-type UpdateInfo = {
- available: boolean;
- version?: string;
- current_version?: string;
- date_ms?: number | null;
- body?: string | null;
+
+type ShortcutDef = {
+ id: string;
+ label: string;
+ defaultKeys: string;
+};
+
+type ShortcutBinding = ShortcutDef & { keys: string };
+
+type ParsedShortcut = ShortcutBinding & {
+ binding: {
+ key: string;
+ ctrl: boolean;
+ shift: boolean;
+ alt: boolean;
+ } | null;
+};
+
+const LOG_FILTERS = [
+ { id: "all", label: "All" },
+ { id: "system", label: "system.*" },
+ { id: "session", label: "session.*" },
+ { id: "workspace", label: "workspace.*" },
+ { id: "pane", label: "pane.*" },
+ { id: "surface", label: "surface.*" },
+ { id: "terminal", label: "terminal.*" },
+ { id: "browser", label: "browser.*" },
+ { id: "agent", label: "agent.*" },
+ { id: "notification", label: "notification.*" },
+ { id: "other", label: "Other" },
+];
+
+type BackendLogEntry = {
+ timestamp_ms: number;
+ level: "trace" | "debug" | "info" | "warn" | "error";
+ component: string;
+ event: string;
+ correlation_id: string;
+ command_id?: string | null;
+ connection_id?: string | null;
+ workspace_id?: string | null;
+ surface_id?: string | null;
+ method?: string | null;
+ duration_ms?: number | null;
+ status?: string | null;
+ fields?: Record;
};
+const DEFAULT_SHORTCUTS: ShortcutDef[] = [
+ { id: "new-window", label: "New window", defaultKeys: "Ctrl+Shift+N" },
+ { id: "new-workspace", label: "New workspace", defaultKeys: "Ctrl+N" },
+ { id: "new-terminal", label: "New terminal", defaultKeys: "Ctrl+T" },
+ { id: "new-browser", label: "New browser", defaultKeys: "Ctrl+B" },
+ { id: "split-right", label: "Split pane right", defaultKeys: "Ctrl+D" },
+ { id: "split-down", label: "Split pane down", defaultKeys: "Ctrl+Shift+D" },
+ { id: "toggle-shortcuts", label: "Toggle shortcuts", defaultKeys: "Ctrl+/" },
+];
+
+const MODIFIER_ALIASES = new Map([
+ ["ctrl", "ctrl"],
+ ["control", "ctrl"],
+ ["cmd", "ctrl"],
+ ["command", "ctrl"],
+ ["meta", "ctrl"],
+ ["shift", "shift"],
+ ["alt", "alt"],
+ ["option", "alt"],
+]);
+
+function normalizeKeyToken(token: string) {
+ return token.length === 1 ? token.toLowerCase() : token.toLowerCase();
+}
+
+function parseShortcutKeys(raw: string) {
+ const trimmed = raw.trim();
+ if (!trimmed) return null;
+ const parts = trimmed.split("+").map((p) => p.trim()).filter(Boolean);
+ if (parts.length === 0) return null;
+ let ctrl = false;
+ let shift = false;
+ let alt = false;
+ const keyPart = parts[parts.length - 1];
+ for (const part of parts.slice(0, -1)) {
+ const mod = MODIFIER_ALIASES.get(part.toLowerCase());
+ if (mod === "ctrl") ctrl = true;
+ if (mod === "shift") shift = true;
+ if (mod === "alt") alt = true;
+ }
+ if (MODIFIER_ALIASES.has(keyPart.toLowerCase())) return null;
+ return {
+ key: normalizeKeyToken(keyPart),
+ ctrl,
+ shift,
+ alt,
+ };
+}
+
+function matchesShortcutEvent(e: KeyboardEvent, binding: { key: string; ctrl: boolean; shift: boolean; alt: boolean }) {
+ const key = normalizeKeyToken(e.key);
+ if (key !== binding.key) return false;
+ const hasCtrl = e.ctrlKey || e.metaKey;
+ if (binding.ctrl !== hasCtrl) return false;
+ if (binding.shift !== e.shiftKey) return false;
+ if (binding.alt !== e.altKey) return false;
+ return true;
+}
+
+function getMethodFamily(method?: string | null) {
+ if (!method) return "other";
+ const normalized = method.toLowerCase();
+ const idx = normalized.indexOf(".");
+ if (idx <= 0) return "other";
+ return normalized.slice(0, idx);
+}
+
+function extractLogMethod(entry: BackendLogEntry) {
+ if (entry.method) return entry.method;
+ const fieldMethod = entry.fields?.method;
+ return typeof fieldMethod === "string" ? fieldMethod : null;
+}
+
+function shortcutsFromStorage(): Record | null {
+ if (typeof window === "undefined") return null;
+ try {
+ const raw = window.localStorage.getItem("maxc-shortcuts");
+ if (!raw) return null;
+ const parsed = JSON.parse(raw);
+ return typeof parsed === "object" && parsed !== null ? parsed : null;
+ } catch {
+ return null;
+ }
+}
+
+function buildShortcutMap(overrides?: Record | null) {
+ const map: Record = {};
+ for (const def of DEFAULT_SHORTCUTS) {
+ map[def.id] = overrides?.[def.id] ?? def.defaultKeys;
+ }
+ return map;
+}
// ---------------------------------------------------------------------------
// Title Bar
// ---------------------------------------------------------------------------
@@ -106,6 +226,7 @@ function TitleBar({ theme }: { theme: "dark" | "light" }) {
}, []);
const handleMin = () => appWindow?.minimize().catch(console.error);
+ const handleMax = () => appWindow?.toggleMaximize().catch(console.error);
const handleClose = () => appWindow?.close().catch(console.error);
return (
@@ -114,7 +235,7 @@ function TitleBar({ theme }: { theme: "dark" | "light" }) {
@@ -131,10 +252,9 @@ function TitleBar({ theme }: { theme: "dark" | "light" }) {