Skip to main content
COSMICBYTEZLABS
NewsSecurityHOWTOsToolsStudyTraining
ProjectsChecklistsAI RankingsNewsletterStatusTagsAbout
Subscribe

Press Enter to search or Esc to close

News
Security
HOWTOs
Tools
Study
Training
Projects
Checklists
AI Rankings
Newsletter
Status
Tags
About
RSS Feed
Reading List
Subscribe

Stay in the Loop

Get the latest security alerts, tutorials, and tech insights delivered to your inbox.

Subscribe NowFree forever. No spam.
COSMICBYTEZLABS

Your trusted source for IT intelligence, cybersecurity insights, and hands-on technical guides.

429+ Articles
114+ Guides

CONTENT

  • Latest News
  • Security Alerts
  • HOWTOs
  • Projects
  • Exam Prep

RESOURCES

  • Search
  • Browse Tags
  • Newsletter Archive
  • Reading List
  • RSS Feed

COMPANY

  • About Us
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CosmicBytez Labs. All rights reserved.

System Status: Operational
  1. Home
  2. HOWTOs
  3. IT Service Dashboards with PowerShell Universal
IT Service Dashboards with PowerShell Universal
HOWTOIntermediate

IT Service Dashboards with PowerShell Universal

Build interactive IT service management dashboards using PowerShell Universal. Create real-time client portals, automated ticketing views, and...

Dylan H.

IT Administration

February 4, 2026
6 min read

Prerequisites

  • PowerShell 7+
  • Basic SQL knowledge
  • Windows Server administration

Overview

PowerShell Universal transforms PowerShell scripts into web dashboards, APIs, and automation workflows. This guide builds an IT service management portal with real-time client information, ticket tracking, and infrastructure health monitoring.

What You'll Build

  • Client management dashboard with contact info and contract status
  • Live infrastructure health panel pulling from monitoring APIs
  • Automated ticket summary views with filtering and export
  • Role-based access control for different team views

Requirements

ComponentRequirement
PowerShell7.2+
PowerShell Universal4.0+
SQL Server2019+ (for data storage)
Windows Server2022 (recommended)

Installation

# Install PowerShell Universal
Install-Module -Name Universal -Scope CurrentUser
Install-PSUServer
 
# Or use MSI installer for production
# Download from ironmansoftware.com

Process

Step 1: Configure the PSU Server

# appsettings.json
{
  "Kestrel": {
    "Endpoints": {
      "HTTP": { "Url": "http://*:5000" }
    }
  },
  "Data": {
    "ConnectionString": "Server=localhost;Database=ClientManager;Trusted_Connection=True;"
  }
}

Step 2: Create the Database Schema

-- SQL Server schema for client management
CREATE TABLE Clients (
    ClientId INT IDENTITY(1,1) PRIMARY KEY,
    CompanyName NVARCHAR(200) NOT NULL,
    PrimaryContact NVARCHAR(100),
    Email NVARCHAR(254),
    Phone NVARCHAR(20),
    ContractStart DATE,
    ContractEnd DATE,
    Tier NVARCHAR(20) DEFAULT 'Standard', -- Standard, Premium, Enterprise
    Active BIT DEFAULT 1,
    Notes NVARCHAR(MAX),
    CreatedAt DATETIME2 DEFAULT GETDATE()
);
 
CREATE TABLE Tickets (
    TicketId INT IDENTITY(1,1) PRIMARY KEY,
    ClientId INT FOREIGN KEY REFERENCES Clients(ClientId),
    Subject NVARCHAR(200) NOT NULL,
    Description NVARCHAR(MAX),
    Priority NVARCHAR(10) DEFAULT 'Medium', -- Low, Medium, High, Critical
    Status NVARCHAR(20) DEFAULT 'Open',     -- Open, In Progress, Resolved, Closed
    AssignedTo NVARCHAR(100),
    CreatedAt DATETIME2 DEFAULT GETDATE(),
    ResolvedAt DATETIME2
);

Step 3: Build the Dashboard

# dashboards/client-portal.ps1
 
New-UDDashboard -Title "Client Management Portal" -Theme @{
    palette = @{
        primary = @{ main = '#0f3460' }
        background = @{ default = '#0a0a0a' }
    }
} -Pages @(
    # Overview Page
    New-UDPage -Name "Overview" -Content {
        New-UDGrid -Container -Content {
            # Summary Cards
            New-UDGrid -Item -ExtraSmallSize 3 -Content {
                $totalClients = (Invoke-DbaQuery -SqlInstance localhost -Database ClientManager `
                    -Query "SELECT COUNT(*) AS Count FROM Clients WHERE Active = 1").Count
                New-UDCard -Title "Active Clients" -Content {
                    New-UDTypography -Text $totalClients -Variant h2
                }
            }
 
            New-UDGrid -Item -ExtraSmallSize 3 -Content {
                $openTickets = (Invoke-DbaQuery -SqlInstance localhost -Database ClientManager `
                    -Query "SELECT COUNT(*) AS Count FROM Tickets WHERE Status IN ('Open','In Progress')").Count
                New-UDCard -Title "Open Tickets" -Content {
                    New-UDTypography -Text $openTickets -Variant h2
                }
            }
 
            New-UDGrid -Item -ExtraSmallSize 3 -Content {
                $expiringContracts = (Invoke-DbaQuery -SqlInstance localhost -Database ClientManager `
                    -Query "SELECT COUNT(*) AS Count FROM Clients WHERE ContractEnd <= DATEADD(day, 30, GETDATE()) AND Active = 1").Count
                New-UDCard -Title "Expiring Soon" -Content {
                    New-UDTypography -Text $expiringContracts -Variant h2 -Style @{color = '#ff6b6b'}
                }
            }
 
            New-UDGrid -Item -ExtraSmallSize 3 -Content {
                $avgResolution = (Invoke-DbaQuery -SqlInstance localhost -Database ClientManager `
                    -Query "SELECT AVG(DATEDIFF(hour, CreatedAt, ResolvedAt)) AS AvgHours FROM Tickets WHERE ResolvedAt IS NOT NULL").AvgHours
                New-UDCard -Title "Avg Resolution" -Content {
                    New-UDTypography -Text "$([math]::Round($avgResolution, 1))h" -Variant h2
                }
            }
        }
 
        # Recent Tickets Table
        New-UDCard -Title "Recent Tickets" -Content {
            New-UDDynamic -Content {
                $tickets = Invoke-DbaQuery -SqlInstance localhost -Database ClientManager -Query "
                    SELECT TOP 20 t.TicketId, c.CompanyName, t.Subject, t.Priority, t.Status, t.CreatedAt
                    FROM Tickets t JOIN Clients c ON t.ClientId = c.ClientId
                    ORDER BY t.CreatedAt DESC"
 
                New-UDTable -Data $tickets -Columns @(
                    New-UDTableColumn -Property TicketId -Title "ID"
                    New-UDTableColumn -Property CompanyName -Title "Client"
                    New-UDTableColumn -Property Subject -Title "Subject"
                    New-UDTableColumn -Property Priority -Title "Priority" -Render {
                        $color = switch ($EventData.Priority) {
                            'Critical' { '#ff4444' }
                            'High' { '#ff8800' }
                            'Medium' { '#ffbb33' }
                            default { '#00C851' }
                        }
                        New-UDChip -Label $EventData.Priority -Style @{backgroundColor = $color}
                    }
                    New-UDTableColumn -Property Status -Title "Status"
                ) -Sort -Filter -Export
            } -AutoRefresh -AutoRefreshInterval 30
        }
    }
 
    # Client Details Page
    New-UDPage -Name "Clients" -Content {
        New-UDDynamic -Content {
            $clients = Invoke-DbaQuery -SqlInstance localhost -Database ClientManager `
                -Query "SELECT * FROM Clients WHERE Active = 1 ORDER BY CompanyName"
 
            New-UDTable -Data $clients -Columns @(
                New-UDTableColumn -Property CompanyName -Title "Company"
                New-UDTableColumn -Property PrimaryContact -Title "Contact"
                New-UDTableColumn -Property Tier -Title "Tier" -Render {
                    $color = switch ($EventData.Tier) {
                        'Enterprise' { '#6c5ce7' }
                        'Premium' { '#0984e3' }
                        default { '#636e72' }
                    }
                    New-UDChip -Label $EventData.Tier -Style @{backgroundColor = $color}
                }
                New-UDTableColumn -Property ContractEnd -Title "Contract Ends" -Render {
                    $daysLeft = (New-TimeSpan -Start (Get-Date) -End $EventData.ContractEnd).Days
                    $color = if ($daysLeft -le 30) { '#ff4444' } elseif ($daysLeft -le 90) { '#ffbb33' } else { '#00C851' }
                    New-UDTypography -Text "$daysLeft days" -Style @{color = $color}
                }
            ) -Sort -Filter -Search
        }
    }
)

Step 4: Add API Endpoints

# endpoints/client-api.ps1
 
New-PSUEndpoint -Url "/api/clients" -Method GET -Endpoint {
    $clients = Invoke-DbaQuery -SqlInstance localhost -Database ClientManager `
        -Query "SELECT ClientId, CompanyName, Tier, Active FROM Clients WHERE Active = 1"
    $clients | ConvertTo-Json
}
 
New-PSUEndpoint -Url "/api/clients/:id/tickets" -Method GET -Endpoint {
    param($id)
    $tickets = Invoke-DbaQuery -SqlInstance localhost -Database ClientManager `
        -Query "SELECT * FROM Tickets WHERE ClientId = @Id ORDER BY CreatedAt DESC" `
        -SqlParameters @{Id = [int]$id}
    $tickets | ConvertTo-Json
}
 
New-PSUEndpoint -Url "/api/tickets" -Method POST -Endpoint {
    param($Body)
    $data = $Body | ConvertFrom-Json
    Invoke-DbaQuery -SqlInstance localhost -Database ClientManager -Query "
        INSERT INTO Tickets (ClientId, Subject, Description, Priority)
        VALUES (@ClientId, @Subject, @Description, @Priority)" `
        -SqlParameters @{
            ClientId = $data.clientId
            Subject = $data.subject
            Description = $data.description
            Priority = $data.priority
        }
    @{status = "created"} | ConvertTo-Json
}

Step 5: Role-Based Access

# Configure authentication and roles
New-PSURole -Name "Admin" -Description "Full access"
New-PSURole -Name "Technician" -Description "Ticket management only"
New-PSURole -Name "Viewer" -Description "Read-only access"
 
# Assign dashboard access by role
Set-PSUDashboard -Name "Client Portal" -Role @("Admin", "Technician", "Viewer")

Key Takeaways

  • PowerShell Universal turns scripts into production web apps without learning a new framework
  • New-UDDynamic with auto-refresh creates real-time dashboards
  • Use Invoke-DbaQuery (dbatools) for safe parameterized SQL queries
  • Role-based access control is built into the platform
  • Export functionality (CSV/PDF) comes free with New-UDTable -Export
  • Schedule scripts for automated data collection and alerting

Related Reading

  • NinjaOne Scripting: PowerShell Automation Library
  • Windows Security Baseline Audit: CIS Benchmark Compliance
  • Windows Security Event Log Analysis: Detect Threats and
#PowerShell#Dashboard#IT Management#automation#Windows

Related Articles

NinjaOne Scripting: PowerShell Automation Library

Build a comprehensive PowerShell automation library for NinjaOne RMM. Covers script library setup, custom fields, scheduled scripts, and condition-based...

18 min read

Windows Security Baseline Audit: CIS Benchmark Compliance

Automate Windows security baseline checks using PowerShell. Validate configurations against CIS benchmarks for password policies, audit settings, and...

9 min read

Windows Security Event Log Analysis: Detect Threats and

Learn to analyze Windows Security Event Logs to detect brute force attacks, lateral movement, privilege escalation, and other security threats using PowerShell.

9 min read
Back to all HOWTOs