diff --git a/package-lock.json b/package-lock.json index 33f0acc..6bbce86 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,6 @@ "": { "devDependencies": { "@tailwindcss/vite": "^4.3.0", - "alpinejs": "^3.15.12", "axios": "^1.11.0", "chart.js": "^4.5.1", "concurrently": "^9.0.1", @@ -1154,23 +1153,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@vue/reactivity": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz", - "integrity": "sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/shared": "3.1.5" - } - }, - "node_modules/@vue/shared": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.1.5.tgz", - "integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==", - "dev": true, - "license": "MIT" - }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -1184,16 +1166,6 @@ "node": ">= 6.0.0" } }, - "node_modules/alpinejs": { - "version": "3.15.12", - "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.15.12.tgz", - "integrity": "sha512-nJvPAQVNPdZZ0NrExJ/kzQco3ijR8LwvCOadQecllESiqT4NyZ/57sN9V2XyvhlBGAbmlKYgeWZvYdKq99ij/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/reactivity": "~3.1.1" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", diff --git a/package.json b/package.json index 10e9c16..7507236 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ }, "devDependencies": { "@tailwindcss/vite": "^4.3.0", - "alpinejs": "^3.15.12", "axios": "^1.11.0", "chart.js": "^4.5.1", "concurrently": "^9.0.1", diff --git a/public/brand/logo-dark.svg b/public/brand/logo-dark.svg new file mode 100644 index 0000000..d2a1d4f --- /dev/null +++ b/public/brand/logo-dark.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + nimuli + diff --git a/public/brand/logo-light.svg b/public/brand/logo-light.svg new file mode 100644 index 0000000..cad075f --- /dev/null +++ b/public/brand/logo-light.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + nimuli + diff --git a/public/brand/logo-mark.svg b/public/brand/logo-mark.svg new file mode 100644 index 0000000..f03c1ef --- /dev/null +++ b/public/brand/logo-mark.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/brand/logo.svg b/public/brand/logo.svg new file mode 100644 index 0000000..27920b7 --- /dev/null +++ b/public/brand/logo.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + nimuli + diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..a2a6502 --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/site.webmanifest b/public/site.webmanifest new file mode 100644 index 0000000..989d9d9 --- /dev/null +++ b/public/site.webmanifest @@ -0,0 +1,13 @@ +{ + "name": "Nimuli", + "short_name": "Nimuli", + "description": "Short links, QR codes, and bio pages — all in one place.", + "start_url": "/dashboard", + "display": "standalone", + "background_color": "#0a0a0f", + "theme_color": "#7c3aed", + "icons": [ + { "src": "/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" }, + { "src": "/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" } + ] +} diff --git a/resources/css/app.css b/resources/css/app.css index af0bf80..ea31b03 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -6,19 +6,26 @@ @source '../**/*.js'; @theme { + /* Dark mode (default) */ --color-bg: #0a0a0f; --color-s1: #111117; --color-s2: #16161e; --color-s3: #1c1c26; - --color-b1: rgb(255 255 255 / 6%); - --color-b2: rgb(255 255 255 / 10%); + --color-b1: rgb(255 255 255 / 8%); + --color-b2: rgb(255 255 255 / 14%); --color-t1: #f0f0f5; --color-t2: #8888a0; --color-t3: #44445a; - --color-blue: #4f8ef7; + + /* Accent — purple-pink gradient, consistent across both themes */ + --color-blue: #7c3aed; + --color-accent: #7c3aed; + --color-accent-2: #ec4899; + --color-green: #3ecf8e; --color-amber: #f5a623; --color-red: #f05252; + --font-mono: 'JetBrains Mono', monospace; --font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; } @@ -33,8 +40,30 @@ --color-t1: #111827; --color-t2: #6b7280; --color-t3: #9ca3af; + --color-blue: #7c3aed; + --color-accent: #7c3aed; + --color-accent-2: #ec4899; + --color-green: #10b981; --color-amber: #f59e0b; --color-red: #ef4444; } + +/* Visible borders on all themes */ +*, ::before, ::after { border-color: var(--color-b1); } + +@layer utilities { + .bg-accent-gradient { + background: linear-gradient(135deg, var(--color-accent), var(--color-accent-2)); + } + .text-accent-gradient { + background: linear-gradient(135deg, var(--color-accent), var(--color-accent-2)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + } + .border-accent-gradient { + border-image: linear-gradient(135deg, var(--color-accent), var(--color-accent-2)) 1; + } +} diff --git a/resources/js/app.js b/resources/js/app.js index 2cf1501..3ade3e0 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -1,34 +1,23 @@ import '../css/app.css'; import './bootstrap'; -import Alpine from 'alpinejs'; import Chart from 'chart.js/auto'; window.Chart = Chart; -// Theme store — reads localStorage, applies to -Alpine.store('theme', { - current: localStorage.getItem('nimuli_theme') || document.documentElement.dataset.theme || 'dark', +// Alpine stores registered via alpine:init — Livewire v3 owns Alpine lifecycle +document.addEventListener('alpine:init', () => { + Alpine.store('theme', { + current: localStorage.getItem('nimuli_theme') || document.documentElement.dataset.theme || 'dark', + init() { this.apply(this.current); }, + apply(theme) { + this.current = theme; + document.documentElement.dataset.theme = theme; + localStorage.setItem('nimuli_theme', theme); + }, + cycle() { + const order = ['dark', 'light', 'system']; + this.apply(order[(order.indexOf(this.current) + 1) % order.length]); + }, + }); - init() { - this.apply(this.current); - }, - - apply(theme) { - this.current = theme; - document.documentElement.dataset.theme = theme; - localStorage.setItem('nimuli_theme', theme); - }, - - cycle() { - const order = ['dark', 'light', 'system']; - const next = order[(order.indexOf(this.current) + 1) % order.length]; - this.apply(next); - }, + Alpine.store('sidebar', { open: false }); }); - -// Sidebar drawer store — mobile open/close -Alpine.store('sidebar', { - open: false, -}); - -window.Alpine = Alpine; -Alpine.start(); diff --git a/resources/views/components/sidebar.blade.php b/resources/views/components/sidebar.blade.php index 7cb42a3..e74ba6a 100644 --- a/resources/views/components/sidebar.blade.php +++ b/resources/views/components/sidebar.blade.php @@ -100,8 +100,9 @@ @click="wsOpen = !wsOpen" class="w-full flex items-center gap-3 px-4 py-4 hover:bg-s2 transition-colors border-b border-white/[.06]" > + Nimuli
-
nimuli.
+
nimuli
@if($workspace)
{{ $workspace->name }}
@else diff --git a/resources/views/layouts/nimuli-app.blade.php b/resources/views/layouts/nimuli-app.blade.php index d596899..37dec95 100644 --- a/resources/views/layouts/nimuli-app.blade.php +++ b/resources/views/layouts/nimuli-app.blade.php @@ -6,11 +6,26 @@ {{ ($title ?? '') ? $title . ' — Nimuli' : 'Nimuli' }} + + + + + + + + + + + + @vite(['resources/js/app.js']) @livewireStyles @@ -30,13 +45,15 @@ aria-hidden="true" >
- + + @persist('sidebar')
+ @endpersist