▶ Run preview

Dashboard

Connect all your apps to a single dashboard

Built by@moganBronze
DAT Data / dashboard AI-assisted Checked ▶ Preview
Published 2 Oct 2026 · Created 2 Oct 2026
dashboard — Preview● Secure sandbox
PROOF CARD
Dashboard
@mogan · AI-assisted · Arena ai · 8/10 checks
Problem. You don't need to login diff apps for maintenance
  • ✓ README
  • ✓ Files or snippet
  • ✓ Security scan ran
  • ✓ Checked — virus/secrets clean
  • ✓ AI tool named
  • — AI workflow note
  • — Human contribution stated
  • ✓ Original (no parent)
  • ✓ Live preview
  • ✓ Published in public record
CAPABILITIES DEMONSTRATED

Based on this build, not self-reported. Select a skill to find matching builders.

Share to WhatsApp
SHIP READINESS — PRECISE CHECKS
  • ✓ Scan completed
  • — No test files detected
  • ✓ No known-vulnerable dependencies listed
  • ✓ No secret-shaped hits in the scan report
  • — Maintenance history: 0 stored versions, 1 platform event

These are precise checks on this object. BlaqVibes does not guarantee this app is secure.

PROJECT EVIDENCE
Creator identityAvailable — @mogan
Project filesAvailable — snippet inline
READMEAvailable
Live previewAvailable — runs sandboxed
Security scanChecked — virus clean, no secrets
Project historyAvailable — 1 event
ReviewsNot available — none yet
StarsNot available — no stars yet
Remix lineageAvailable — original project
Build methodAvailable — AI-assisted · Arena ai
BUILD METHOD
AI-assisted — The builder used Arena ai during development and remains responsible for the published work. · Tool: Arena ai
PROJECT HISTORY — WHAT CHANGED
Oct 2 First version published
COMMUNITY — COMMENTS · 0
Please sign in to comment.
No comments yet. Leave the first.
COMMUNITY — REVIEWS · 0
Please sign in to review. Trade or star first.
No witnesses yet.
NEXT ACTIONS
Start with the idea, change it, and publish your version.
Comment
README — REQUIRED FOR EVERY PROJECT

Nova Workspace Dashboard — app-link scaffold

This project adds real, configurable launch destinations to the dashboard. It uses Node.js built-ins only; there are no npm dependencies.

Run locally

Requires Node.js 18 or later.

npm start

Open http://localhost:4173 (or the port shown in the server log). The dashboard calls the same-origin API and saves configured destinations to app-links.json.

Configure app destinations

  1. Open Applications → Manage links in the dashboard.
  2. Enter the URL for each app, e.g. https://studio.your-company.com.
  3. Save. The matching Open app button will launch that URL in a new tab.
  4. Clear a field and save to remove that destination.

The server accepts only http:// and https:// URLs, rejects embedded credentials, and writes the config atomically. You can also edit app-links.json directly. If you open the HTML without the included server, destinations are saved in that browser's local storage instead.

API

  • GET /api/health — basic server health response.
  • GET /api/app-links — read the six configured destinations.
  • PUT /api/app-links — replace the destinations with a JSON object keyed by app name.

Example:

curl -X PUT http://localhost:4173/api/app-links \
  -H 'Content-Type: application/json' \
  -d '{"Creative Studio":"https://studio.example.com","Analytics Hub":"https://analytics.example.com"}'

Missing app keys are saved as empty destinations. A hostname without a scheme is stored as HTTPS.

Important before deployment

The dashboard's KPI values, chart series, and service-health indicators are still illustrative sample data; this scaffold only makes the app launch links configurable. The included API has no authentication or authorization and is intended for local development. Before deploying it to a shared or public environment, add authentication, authorization, request-origin/CSRF protections, HTTPS, and suitable persistent storage for your environment.

FILE TREE
No file tree — this is a snippet. See Code tab.
Click any file to preview (200KB max). Full ZIP has everything.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Master Dashboard - WebGL Liquid</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            overflow-x: hidden;
            background: #0a0a0a;
            color: #fff;
        }

        #liquid-canvas {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: 0;
        }

        .dashboard {
            position: relative;
            z-index: 1;
            padding: 20px;
            max-width: 1400px;
            margin: 0 auto;
        }

        header {
            background: rgba(255, 255, 255, 0.05);
            backdrop-filter: blur(20px);
            border-radius: 20px;
            padding: 30px;
            margin-bottom: 30px;
            border: 1px solid rgba(255, 255, 255, 0.1);
        }

        h1 {
            font-size: 2.5em;
            background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            margin-bottom: 10px;
        }

        .subtitle {
            color: rgba(255, 255, 255, 0.6);
            font-size: 1.1em;
        }

        .stats-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 20px;
            margin-bottom: 30px;
        }

        .stat-card {
            background: rgba(255, 255, 255, 0.05);
            backdrop-filter: blur(20px);
            border-radius: 15px;
            padding: 25px;
            border: 1px solid rgba(255, 255, 255, 0.1);
            transition: all 0.3s ease;
            cursor: pointer;
        }

        .stat-card:hover {
            transform: translateY(-5px);
            background: rgba(255, 255, 255, 0.08);
            box-shadow: 0 10px 40px rgba(102, 126, 234, 0.3);
        }

        .stat-icon {
            width: 50px;
            height: 50px;
            border-radius: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 24px;
            margin-bottom: 15px;
        }

        .stat-value {
            font-size: 2em;
            font-weight: bold;
            margin-bottom: 5px;
        }

        .stat-label {
            color: rgba(255, 255, 255, 0.6);
            font-size: 0.9em;
        }

        .apps-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 25px;
            margin-bottom: 30px;
        }

        .app-card {
            background: rgba(255, 255, 255, 0.05);
            backdrop-filter: blur(20px);
            border-radius: 20px;
            padding: 30px;
            border: 1px solid rgba(255, 255, 255, 0.1);
            transition: all 0.3s ease;
            cursor: pointer;
        }

        .app-card:hover {
            transform: translateY(-5px);
            background: rgba(255, 255, 255, 0.08);
            box-shadow: 0 15px 50px rgba(0, 0, 0, 0.4);
        }

        .app-header {
            display: flex;
            align-items: center;
            margin-bottom: 20px;
        }

        .app-icon {
            width: 60px;
            height: 60px;
            border-radius: 15px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 30px;
            margin-right: 15px;
        }

        .app-info h3 {
            font-size: 1.3em;
            margin-bottom: 5px;
        }

        .app-status {
            font-size: 0.85em;
            padding: 4px 12px;
            border-radius: 20px;
            display: inline-block;
        }

        .status-active {
            background: rgba(34, 197, 94, 0.2);
            color: #4ade80;
        }

        .status-warning {
            background: rgba(251, 191, 36, 0.2);
            color: #fbbf24;
        }

        .app-metrics {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 15px;
            margin-top: 20px;
        }

        .metric {
            background: rgba(255, 255, 255, 0.03);
            padding: 15px;
            border-radius: 10px;
        }

        .metric-value {
            font-size: 1.5em;
            font-weight: bold;
            color: #667eea;
        }

        .metric-label {
            font-size: 0.85em;
            color: rgba(255, 255, 255, 0.5);
            margin-top: 5px;
        }

        .progress-bar {
            width: 100%;
            height: 8px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 10px;
            overflow: hidden;
            margin-top: 15px;
        }

        .progress-fill {
            height: 100%;
            background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
            border-radius: 10px;
            transition: width 0.3s ease;
        }

        .btn {
            background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
            color: white;
            border: none;
            padding: 12px 25px;
            border-radius: 10px;
            font-size: 1em;
            cursor: pointer;
            margin-top: 15px;
            transition: all 0.3s ease;
        }

        .btn:hover {
            transform: scale(1.05);
            box-shadow: 0 5px 20px rgba(102, 126, 234, 0.5);
        }
    </style>
</head>
<body>
    <canvas id="liquid-canvas"></canvas>
    
    <div class="dashboard">
        <header>
            <h1>Master Dashboard</h1>
            <p class="subtitle">Real-time monitoring and analytics</p>
        </header>

        <div class="stats-grid">
            <div class="stat-card">
                <div class="stat-icon" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
                    📊
                </div>
                <div class="stat-value">1,284</div>
                <div class="stat-label">Total Users</div>
            </div>

            <div class="stat-card">
                <div class="stat-icon" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);">
                    🚀
                </div>
                <div class="stat-value">98.5%</div>
                <div class="stat-label">Uptime</div>
            </div>

            <div class="stat-card">
                <div class="stat-icon" style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);">
                    💰
                </div>
                <div class="stat-value">$45.2K</div>
                <div class="stat-label">Revenue</div>
            </div>

            <div class="stat-card">
                <div class="stat-icon" style="background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);">
                    ⚡
                </div>
                <div class="stat-value">342</div>
                <div class="stat-label">Active Sessions</div>
            </div>
        </div>

        <div class="apps-grid">
            <div class="app-card">
                <div class="app-header">
                    <div class="app-icon" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
                        🎨
                    </div>
                    <div class="app-info">
                        <h3>Creative Studio</h3>
                        <span class="app-status status-active">● Active</span>
                    </div>
                </div>
                <div class="app-metrics">
                    <div class="metric">
                        <div class="metric-value">2.4K</div>
                        <div class="metric-label">Projects</div>
                    </div>
                    <div class="metric">
                        <div class="metric-value">89%</div>
                        <div class="metric-label">Usage</div>
                    </div>
                </div>
                <div class="progress-bar">
                    <div class="progress-fill" style="width: 89%;"></div>
                </div>
                <button class="btn">Open App</button>
            </div>

            <div class="app-card">
                <div class="app-header">
                    <div class="app-icon" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);">
                        📈
                    </div>
                    <div class="app-info">
                        <h3>Analytics Hub</h3>
                        <span class="app-status status-active">● Active</span>
                    </div>
                </div>
                <div class="app-metrics">
                    <div class="metric">
                        <div class="metric-value">15.2K</div>
                        <div class="metric-label">Events</div>
                    </div>
                    <div class="metric">
                        <div class="metric-value">67%</div>
                        <div class="metric-label">Processing</div>
                    </div>
                </div>
                <div class="progress-bar">
                    <div class="progress-fill" style="width: 67%;"></div>
                </div>
                <button class="btn">Open App</button>
            </div>

            <div class="app-card">
                <div class="app-header">
                    <div class="app-icon" style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);">
                        💬
                    </div>
                    <div class="app-info">
                        <h3>Chat System</h3>
                        <span class="app-status status-warning">● Updating</span>
                    </div>
                </div>
                <div class="app-metrics">
                    <div class="metric">
                        <div class="metric-value">892</div>
                        <div class="metric-label">Messages</div>
                    </div>
                    <div class="metric">
                        <div class="metric-value">45</div>
                        <div class="metric-label">Online</div>
                    </div>
                </div>
                <div class="progress-bar">
                    <div class="progress-fill" style="width: 45%;"></div>
                </div>
                <button class="btn">Open App</button>
            </div>

            <div class="app-card">
                <div class="app-header">
                    <div class="app-icon" style="background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);">
                        🔒
                    </div>
                    <div class="app-info">
                        <h3>Security Center</h3>
                        <span class="app-status status-active">● Active</span>
                    </div>
                </div>
                <div class="app-metrics">
                    <div class="metric">
                        <div class="metric-value">0</div>
                        <div class="metric-label">Threats</div>
                    </div>
                    <div class="metric">
                        <div class="metric-value">100%</div>
                        <div class="metric-label">Secure</div>
                    </div>
                </div>
                <div class="progress-bar">
                    <div class="progress-fill" style="width: 100%;"></div>
                </div>
                <button class="btn">Open App</button>
            </div>

            <div class="app-card">
                <div class="app-header">
                    <div class="app-icon" style="background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);">
                        📁
                    </div>
                    <div class="app-info">
                        <h3>File Manager</h3>
                        <span class="app-status status-active">● Active</span>
                    </div>
                </div>
                <div class="app-metrics">
                    <div class="metric">
                        <div class="metric-value">45GB</div>
                        <div class="metric-label">Storage</div>
                    </div>
                    <div class="metric">
                        <div class="metric-value">1.2K</div>
                        <div class="metric-label">Files</div>
                    </div>
                </div>
                <div class="progress-bar">
                    <div class="progress-fill" style="width: 72%;"></div>
                </div>
                <button class="btn">Open App</button>
            </div>

            <div class="app-card">
                <div class="app-header">
                    <div class="app-icon" style="background: linear-gradient(135deg, #30cfd0 0%, #330867 100%);">
                        ⚙️
                    </div>
                    <div class="app-info">
                        <h3>Settings</h3>
                        <span class="app-status status-active">● Active</span>
                    </div>
                </div>
                <div class="app-metrics">
                    <div class="metric">
                        <div class="metric-value">12</div>
                        <div class="metric-label">Configs</div>
                    </div>
                    <div class="metric">
                        <div class="metric-value">8</div>
                        <div class="metric-label">Modules</div>
                    </div>
                </div>
                <div class="progress-bar">
                    <div class="progress-fill" style="width: 92%;"></div>
                </div>
                <button class="btn">Open App</button>
            </div>
        </div>
    </div>

    <script>
        // WebGL Liquid Effect
        const canvas = document.getElementById('liquid-canvas');
        const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');

        if (!gl) {
            alert('WebGL not supported');
        }

        // Vertex shader
        const vertexShaderSource = `
            attribute vec2 a_position;
            void main() {
                gl_Position = vec4(a_position, 0.0, 1.0);
            }
        `;

        // Fragment shader with liquid effect
        const fragmentShaderSource = `
            precision highp float;
            uniform vec2 u_resolution;
            uniform float u_time;
            uniform vec2 u_mouse;

            vec3 palette(float t) {
                vec3 a = vec3(0.5, 0.5, 0.5);
                vec3 b = vec3(0.5, 0.5, 0.5);
                vec3 c = vec3(1.0, 1.0, 1.0);
                vec3 d = vec3(0.263, 0.416, 0.557);
                return a + b * cos(6.28318 * (c * t + d));
            }

            void main() {
                vec2 uv = (gl_FragCoord.xy * 2.0 - u_resolution) / u_resolution.y;
                vec2 uv0 = uv;
                vec3 finalColor = vec3(0.0);

                for (float i = 0.0; i < 4.0; i++) {
                    uv = fract(uv * 1.5) - 0.5;

                    float d = length(uv) * exp(-length(uv0));

                    vec3 col = palette(length(uv0) + i * 0.4 + u_time * 0.4);

                    d = sin(d * 8.0 + u_time) / 8.0;
                    d = abs(d);
                    d = pow(0.01 / d, 1.2);

                    finalColor += col * d;
                }

                // Add mouse interaction
                vec2 mouseEffect = u_mouse / u_resolution;
                float mouseDist = length(uv - mouseEffect);
                finalColor += vec3(0.1, 0.05, 0.2) * (1.0 - smoothstep(0.0, 0.5, mouseDist));

                gl_FragColor = vec4(finalColor * 0.3, 1.0);
            }
        `;

        function createShader(gl, type, source) {
            const shader = gl.createShader(type);
            gl.shaderSource(shader, source);
            gl.compileShader(shader);
            if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
                console.error('Shader compile error:', gl.getShaderInfoLog(shader));
                gl.deleteShader(shader);
                return null;
            }
            return shader;
        }

        function createProgram(gl, vertexShader, fragmentShader) {
            const program = gl.createProgram();
            gl.attachShader(program, vertexShader);
            gl.attachShader(program, fragmentShader);
            gl.linkProgram(program);
            if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
                console.error('Program link error:', gl.getProgramInfoLog(program));
                gl.deleteProgram(program);
                return null;
            }
            return program;
        }

        const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
        const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
        const program = createProgram(gl, vertexShader, fragmentShader);

        const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
        const resolutionUniformLocation = gl.getUniformLocation(program, 'u_resolution');
        const timeUniformLocation = gl.getUniformLocation(program, 'u_time');
        const mouseUniformLocation = gl.getUniformLocation(program, 'u_mouse');

        const positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
        const positions = [
            -1, -1,
            1, -1,
            -1, 1,
            -1, 1,
            1, -1,
            1, 1,
        ];
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

        let mouseX = 0;
        let mouseY = 0;

        document.addEventListener('mousemove', (e) => {
            mouseX = e.clientX;
            mouseY = canvas.height - e.clientY;
        });

        function resizeCanvas() {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
            gl.viewport(0, 0, canvas.width, canvas.height);
        }

        window.addEventListener('resize', resizeCanvas);
        resizeCanvas();

        function render(time) {
            time *= 0.001; // Convert to seconds

            gl.clearColor(0, 0, 0, 1);
            gl.clear(gl.COLOR_BUFFER_BIT);

            gl.useProgram(program);

            gl.enableVertexAttribArray(positionAttributeLocation);
            gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
            gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

            gl.uniform2f(resolutionUniformLocation, canvas.width, canvas.height);
            gl.uniform1f(timeUniformLocation, time);
            gl.uniform2f(mouseUniformLocation, mouseX, mouseY);

            gl.drawArrays(gl.TRIANGLES, 0, 6);

            requestAnimationFrame(render);
        }

        requestAnimationFrame(render);

        // Add interactive animations
        document.querySelectorAll('.stat-card, .app-card').forEach(card => {
            card.addEventListener('click', function() {
                this.style.transform = 'scale(0.95)';
                setTimeout(() => {
                    this.style.transform = '';
                }, 100);
            });
        });

        // Animate stats on load
        window.addEventListener('load', () => {
            document.querySelectorAll('.stat-value').forEach((stat, index) => {
                stat.style.opacity = '0';
                setTimeout(() => {
                    stat.style.transition = 'opacity 0.5s ease';
                    stat.style.opacity = '1';
                }, index * 100);
            });
        });
    </script>
</body>
</html>
body{font-family:system-ui,sans-serif;background:#0b1020;color:#e5e7eb;display:grid;place-items:center;min-height:100vh}
Ask Nolo — assistant, not author
Compare features side-by-side. You decide what to build.
✓ Checked — Virus-scanned clean · no leaked secrets · dependencies checked. What does this mean?
PROJECT DETAILS
Publisher@mogan
StackArena
Files0 · 0 views
Build methodAI-assisted
LicenseMIT
Tip
DOWNLOAD
▶ Run preview
⑂ FORKS — Family tree → · PRs (0) →
No remixes yet.

HOW TO ACCESS

  1. Read README
  2. Explore Files
  3. Check Evidence
  4. Remix or Download
READY TO SHIP?

Deploy your project.

Follow the official launch guide.

Open launch guide ↗
✓ Copied!