diff --git a/admin-web/index.html b/admin-web/index.html index 06e3bf4..d0dad3b 100644 --- a/admin-web/index.html +++ b/admin-web/index.html @@ -3,6 +3,8 @@ + + NexaVPN Admin diff --git a/admin-web/public/NexaVPN_Logo.png b/admin-web/public/NexaVPN_Logo.png new file mode 100644 index 0000000..6dde518 Binary files /dev/null and b/admin-web/public/NexaVPN_Logo.png differ diff --git a/admin-web/public/NexaVPN_Logo_Only.png b/admin-web/public/NexaVPN_Logo_Only.png new file mode 100644 index 0000000..6cfe6e4 Binary files /dev/null and b/admin-web/public/NexaVPN_Logo_Only.png differ diff --git a/admin-web/public/favicon.ico b/admin-web/public/favicon.ico new file mode 100644 index 0000000..7c339f0 Binary files /dev/null and b/admin-web/public/favicon.ico differ diff --git a/admin-web/public/favicon.png b/admin-web/public/favicon.png new file mode 100644 index 0000000..6cfe6e4 Binary files /dev/null and b/admin-web/public/favicon.png differ diff --git a/admin-web/src/components/Layout.tsx b/admin-web/src/components/Layout.tsx index 7921d9a..ec332f7 100644 --- a/admin-web/src/components/Layout.tsx +++ b/admin-web/src/components/Layout.tsx @@ -14,9 +14,13 @@ export function Layout() { return (
-
-

Enterprise WireGuard

-

Self-hosted VPN management

+
+ NexaVPN mark +
+

Enterprise WireGuard

+

Self-hosted VPN management

+
Secure by design
diff --git a/admin-web/src/features/auth/LoginPage.tsx b/admin-web/src/features/auth/LoginPage.tsx index 3a14f90..15110d8 100644 --- a/admin-web/src/features/auth/LoginPage.tsx +++ b/admin-web/src/features/auth/LoginPage.tsx @@ -58,8 +58,13 @@ export function LoginPage({ onAuthenticated }: LoginPageProps) { return (
-

NexaVPN Admin

-

{mode === "login" ? "Sign in" : "Create initial admin"}

+
+ NexaVPN +
+

NexaVPN Admin

+

{mode === "login" ? "Sign in" : "Create initial admin"}

+
+

{mode === "login" ? "Use your NexaVPN admin credentials." diff --git a/admin-web/src/styles/global.css b/admin-web/src/styles/global.css index 49982f5..051e9de 100644 --- a/admin-web/src/styles/global.css +++ b/admin-web/src/styles/global.css @@ -61,6 +61,45 @@ button { backdrop-filter: blur(12px); } +.auth-brand, +.brand-block, +.topbar-brand { + display: flex; + align-items: center; + gap: 16px; +} + +.brand-block { + align-items: flex-start; +} + +.brand-copy { + display: grid; + gap: 6px; +} + +.brand-tagline { + margin: 0; + color: var(--muted); + max-width: 240px; + line-height: 1.5; +} + +.brand-logo { + display: block; + height: auto; +} + +.brand-logo-full { + width: min(100%, 220px); +} + +.brand-logo-mark { + width: 48px; + border-radius: 14px; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18); +} + .auth-card label { display: grid; gap: 8px; @@ -258,6 +297,18 @@ button { border-bottom: 1px solid var(--line); } + .auth-brand, + .brand-block, + .topbar-brand, + .page-header { + align-items: flex-start; + flex-direction: column; + } + + .brand-logo-full { + width: min(100%, 200px); + } + .grid.two, .grid.three { grid-template-columns: 1fr; diff --git a/desktop-client/index.html b/desktop-client/index.html index fa9f93d..b1f834d 100644 --- a/desktop-client/index.html +++ b/desktop-client/index.html @@ -3,6 +3,7 @@ + NexaVPN diff --git a/desktop-client/public/icon.png b/desktop-client/public/icon.png new file mode 100644 index 0000000..6cfe6e4 Binary files /dev/null and b/desktop-client/public/icon.png differ diff --git a/desktop-client/src-tauri/icons/icon.ico b/desktop-client/src-tauri/icons/icon.ico new file mode 100644 index 0000000..7c339f0 Binary files /dev/null and b/desktop-client/src-tauri/icons/icon.ico differ diff --git a/desktop-client/src-tauri/icons/icon.png b/desktop-client/src-tauri/icons/icon.png new file mode 100644 index 0000000..6cfe6e4 Binary files /dev/null and b/desktop-client/src-tauri/icons/icon.png differ diff --git a/desktop-client/src-tauri/tauri.conf.json b/desktop-client/src-tauri/tauri.conf.json index 5faf365..137197d 100644 --- a/desktop-client/src-tauri/tauri.conf.json +++ b/desktop-client/src-tauri/tauri.conf.json @@ -25,7 +25,10 @@ "bundle": { "active": true, "targets": "all", - "icon": [], + "icon": [ + "icons/icon.png", + "icons/icon.ico" + ], "resources": [ "bundled/**/*" ] diff --git a/scripts/generate_ico_from_png.py b/scripts/generate_ico_from_png.py new file mode 100644 index 0000000..b0ce3ef --- /dev/null +++ b/scripts/generate_ico_from_png.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import struct +import sys +from pathlib import Path + + +PNG_SIGNATURE = b"\x89PNG\r\n\x1a\n" + + +def main() -> int: + if len(sys.argv) != 3: + print("usage: generate_ico_from_png.py ", file=sys.stderr) + return 1 + + source = Path(sys.argv[1]) + target = Path(sys.argv[2]) + + png = source.read_bytes() + if not png.startswith(PNG_SIGNATURE): + print(f"{source} is not a PNG file", file=sys.stderr) + return 1 + + width = int.from_bytes(png[16:20], "big") + height = int.from_bytes(png[20:24], "big") + width_byte = 0 if width >= 256 else width + height_byte = 0 if height >= 256 else height + + header = struct.pack("