> For the complete documentation index, see [llms.txt](https://docs.devolutions.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.devolutions.net/powershell-universal/apps/custom-frontends.md).

# Custom Frontends

## Custom Frontends

Custom frontends are static web applications that you build with standard web tooling and host with PowerShell Universal. They are useful when you want to use a JavaScript framework, reuse an existing design system, or have full control over the client-side experience.

PowerShell Universal does not need to compile or understand your frontend source code. Build the application with your preferred tooling, publish the generated files with a [published folder](/powershell-universal/platform/published-folders.md), and call PowerShell Universal APIs from the browser.

This differs from [static apps](/powershell-universal/apps/static-apps.md), which are built from PowerShell Universal App definitions. Custom frontends use standard HTML, CSS, and JavaScript directly.

## Using JavaScript Libraries

You can use React, Vue, Angular, Svelte, or any other frontend library that produces static files. PowerShell Universal serves the compiled output, such as a `dist`, `build`, or `wwwroot` folder.

A typical workflow is:

1. Create the frontend project with the framework's tooling.
2. Configure the build to use the request path you will publish in PowerShell Universal.
3. Build the frontend.
4. Publish the build output as a published folder.

When hosting the application under a path such as `/dashboard`, configure your bundler's base path so JavaScript, CSS, image, and font URLs resolve correctly. Avoid `/portal` because it conflicts with the built-in PowerShell Universal Portal.

For Vite-based applications, set the `base` option.

```typescript
import { defineConfig } from 'vite'

export default defineConfig({
	base: '/dashboard/'
})
```

For Angular applications, set the base href when building.

```powershell
ng build --base-href /dashboard/
```

If the application uses client-side routing, configure the router to use the published request path. You can also use hash-based routing when you do not want the server to handle deep links directly.

During development, you can run the framework's local development server and call PowerShell Universal APIs from the browser. If the development server runs on a different origin than PowerShell Universal, configure [CorsHosts](/powershell-universal/config/settings.md#corshosts) or use the frontend development server's proxy feature. In production, prefer relative URLs so calls go back to the same PowerShell Universal instance that served the frontend.

## Using CSS Frameworks

You can use CSS frameworks such as Tailwind CSS, Bootstrap, Bulma, or framework-specific component libraries. Include the CSS the same way you would in any static web application.

For most applications, install the CSS framework through your package manager and include it in the bundle. This keeps the application self-contained and avoids depending on external CDNs.

```powershell
npm install bootstrap
```

```javascript
import 'bootstrap/dist/css/bootstrap.min.css'
```

The custom frontend is independent of the Admin Console and the PowerShell Universal App Framework. Include all styles, fonts, and assets your application requires in the build output or serve them from another published folder.

## Calling PSU APIs

Custom frontends can call both custom API endpoints and the PowerShell Universal Management API.

Use [custom API endpoints](/powershell-universal/api/endpoints.md) for application-specific data and actions. This is the recommended approach for most custom frontends because you control the route, input validation, response shape, authentication, and role requirements.

```powershell
New-PSUEndpoint -Url '/frontend/profile' -Method Get -Authentication -Endpoint {
		[PSCustomObject]@{
				UserName = $User.Identity.Name
				ServerTime = Get-Date
		}
}
```

From the frontend, call the endpoint with `fetch`.

```javascript
const response = await fetch('/frontend/profile', {
	credentials: 'same-origin'
})

if (!response.ok) {
	throw new Error(`Request failed: ${response.status}`)
}

const profile = await response.json()
```

For JSON requests, send the `Content-Type` header and parse the body in the endpoint or use a `param` block.

```powershell
New-PSUEndpoint -Url '/frontend/tickets' -Method Post -Authentication -Endpoint {
		$Ticket = ConvertFrom-Json $Body

		[PSCustomObject]@{
				Id = [guid]::NewGuid()
				Title = $Ticket.Title
				Created = Get-Date
		}
}
```

```javascript
await fetch('/frontend/tickets', {
	method: 'POST',
	credentials: 'same-origin',
	headers: {
		'Content-Type': 'application/json'
	},
	body: JSON.stringify({ title: 'Reset development environment' })
})
```

The Management API is available under `/api/v1` and is intended for administrative operations. Use it when you are building an administrative frontend and the signed-in user has the required permissions. For user-facing workflows, consider exposing a smaller custom API endpoint that performs only the operation the frontend needs.

Avoid creating custom endpoint URLs that conflict with internal Management API URLs. See [API endpoints](/powershell-universal/api/endpoints.md) and [API security](/powershell-universal/api/security.md) for more details.

## Documenting APIs with OpenAPI

[OpenAPI](/powershell-universal/api/openapi.md) documentation is helpful when building custom frontends because it describes the API contract in a standard format. Developers and AI agents can use it to understand routes, HTTP methods, parameters, authentication requirements, request bodies, response shapes, and status codes before writing frontend code.

Create an endpoint documentation definition for the API used by your frontend and assign related endpoints to it.

```powershell
New-PSUEndpointDocumentation -Name 'Dashboard API' -Url '/dashboard-api' -Description 'APIs used by the custom dashboard.'

New-PSUEndpoint -Url '/frontend/tickets' -Method Get -Authentication -Documentation 'Dashboard API' -Endpoint {
    <#
    .SYNOPSIS
    Returns tickets displayed by the custom dashboard.

    .DESCRIPTION
    Returns the ticket list for the signed-in user. Operators receive assigned tickets and administrators receive all tickets.

    .OUTPUTS
    200:
      Description: Ticket list returned successfully.
    401:
      Description: The user is not authenticated.
    #>
    Get-Ticket | Select-Object Id, Title, Status, AssignedTo
}
```

OpenAPI definitions appear in the built-in Swagger dashboard.

```http
http://localhost:5000/swagger/index.html
```

Use comment-based help in endpoint scripts to document the purpose of the endpoint and its parameters. For richer API contracts, define input and output types in the endpoint documentation definition and reference them from `.INPUTS` and `.OUTPUTS` sections. This helps generated clients, test tools, and AI agents produce more accurate requests.

When working with an AI agent, provide the OpenAPI document or Swagger URL along with the frontend requirements. The agent can use the contract to generate typed API clients, request helpers, forms, validation, loading states, and error handling that match the real endpoints.

## Authentication

Published folders and API endpoints can require authentication and roles independently.

To require users to sign in before loading the frontend files, enable authentication on the published folder.

```powershell
New-PSUPublishedFolder -Name 'Dashboard' -Path 'C:\Apps\Dashboard\dist' -RequestPath '/dashboard' -DefaultDocument 'index.html' -Authentication -Role 'Operator'
```

To protect data and actions, enable authentication on the API endpoints the frontend calls.

```powershell
New-PSUEndpoint -Url '/frontend/admin-data' -Method Get -Authentication -Role 'Administrator' -Endpoint {
		Get-Date
}
```

When the frontend is served from the same PowerShell Universal instance, cookie authentication works naturally for signed-in users. Use `credentials: 'same-origin'` with `fetch` so browser credentials are included with requests to authenticated endpoints.

App tokens are useful for automation, external integrations, and server-to-server calls. Do not embed app tokens in browser JavaScript, store them in local storage, or commit them with frontend source code. If a frontend needs to perform an operation that requires elevated permissions, create a custom API endpoint with the appropriate authentication, role checks, and server-side logic.

When you do need to call APIs with an app token from a trusted client, send it in the `Authorization` header.

```http
Authorization: Bearer <app-token>
```

PowerShell Universal also supports the `X-PSU-Authorization` header for scenarios where a reverse proxy needs to use the standard `Authorization` header for another purpose. See [App Tokens](/powershell-universal/security/app-tokens.md) for token management guidance.

## Hosting Static Assets

Use [published folders](/powershell-universal/platform/published-folders.md) to host the compiled frontend files. The published folder maps a local file system path to a request path on the PowerShell Universal web server.

```powershell
New-PSUPublishedFolder -Name 'Dashboard' -Path 'C:\Apps\Dashboard\dist' -RequestPath '/dashboard' -DefaultDocument 'index.html'
```

After publishing, users can open the frontend at the request path.

```http
http://localhost:5000/dashboard
```

The `-DefaultDocument` parameter serves `index.html` when the user requests the folder root. This is important for single-page applications. For direct links to nested client-side routes, use hash-based routing or ensure your hosting path can return the frontend entry point for those routes.

Only publish the compiled output folder. Do not publish source folders that contain configuration files, package metadata, environment files, or other content that should not be downloadable.

Static assets such as images, fonts, and generated JavaScript chunks can live inside the same build output folder. If you need to share assets across multiple frontends or apps, publish a separate folder such as `/assets` and reference it from the frontend.

## Building with AI Agents

AI coding agents can help scaffold and iterate on a custom frontend, especially when you provide the PowerShell Universal constraints up front. Give the agent the request path, framework, API routes, authentication expectations, and build command you plan to use.

PowerShell Universal skills can provide AI agents with reusable PSU-specific instructions, scripts, and references. Devolutions maintains a collection of these skills in the [powershell-universal-skills](https://github.com/Devolutions/powershell-universal-skills) repository. These skills follow the Agent Skills format and can help agents perform common PowerShell Universal tasks with more product-specific context.

For example, the repository includes an `install-sandbox-psu` skill for installing PowerShell Universal in a sandbox environment for testing and development. You can install the collection with the skills CLI.

```powershell
npx skills add devolutions/powershell-universal-skills
```

Once installed, supported coding agents can use the skills automatically when a relevant PowerShell Universal task is detected. This can be useful when you want an agent to create a custom frontend and also set up a local PSU instance, configure supporting resources, or validate the frontend against a sandbox environment.

For example:

```
Build a React and Vite frontend for PowerShell Universal. It will be hosted at /dashboard from a published folder. Configure the Vite base path for /dashboard/. Use relative fetch calls to /frontend/profile and /frontend/tickets with same-origin credentials. Do not store app tokens in the browser. Include loading, error, and empty states.
```

Useful details to include in prompts are:

* The framework and package manager to use.
* The published folder request path.
* The expected API endpoint URLs and JSON shapes.
* The OpenAPI document or Swagger URL for the frontend APIs.
* Whether the frontend is public or requires authentication.
* Role-specific behavior the UI should show or hide.
* The build output folder that will be published.
* Any installed PowerShell Universal agent skills the agent should use.

After the agent creates the frontend, review the build configuration, run the production build, and publish only the generated output folder with `New-PSUPublishedFolder` or the Platform / Published Folders page.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.devolutions.net/powershell-universal/apps/custom-frontends.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
