From f76a0f240a016261d781949cac84102c700c83b1 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 6 Aug 2026 21:52:56 +0200 Subject: [PATCH] feat(apps): allow custom URI schemes in application links (#6521) --- apps/docs/docs/management/apps/index.mdx | 11 +++++++---- packages/api/src/router/app.ts | 2 +- packages/validation/src/app.ts | 3 +-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/apps/docs/docs/management/apps/index.mdx b/apps/docs/docs/management/apps/index.mdx index 35c02a4fc..7c84df588 100644 --- a/apps/docs/docs/management/apps/index.mdx +++ b/apps/docs/docs/management/apps/index.mdx @@ -7,8 +7,8 @@ tags: - Ping --- -Apps are the building blocks of your Homarr board. -Most of the time they are a simple link to a website, but used on your board they also support a simple ping to check if your service is up. +Apps are the building blocks of your Homarr board. +Most of the time they are a simple link to a website, but used on your board they also support a simple ping to check if your service is up. Apps are used in the bookmark and app widget. ## Create an app @@ -27,7 +27,7 @@ The name must be at least one character long and can be chosen freely. ### Icon URL -This is the URL to the icon that will be displayed on the app widget. +This is the URL to the icon that will be displayed on the app widget. You can paste a direct HTTP(S) URL to an image, search the included icon repositories by name, or upload a local file through the upload button. Direct image URLs are used as entered and are not searched in the icon repositories. ![Icon URL](./img/app-icon-url.png) @@ -40,11 +40,14 @@ An optional description that can be shown as tooltip on the app widget. The URL to the website you want to link to. Clicking on the app widget or bookmark will open this URL. +You can also use custom URI schemes such as `vscode://file/path`, `microsoft-edge:https://example.com`, or `myapp://open` to link to local applications or third-party programs. We trust that you know what you are doing — only `javascript:` URIs are blocked for security reasons. + ### Ping URL -When you want to use another url for the simple status check you can set it here. +When you want to use another url for the simple status check you can set it here. This will allow you to set a different URL for the ping than the URL that is opened when clicking on the app widget. It's useful when you want to ping the service internally for example with a custom ip but open the website externally. +Note that the ping URL only accepts `http://` and `https://` URLs — custom URI schemes are not supported for pings. ## List of apps diff --git a/packages/api/src/router/app.ts b/packages/api/src/router/app.ts index 3d0285689..3c623b55a 100644 --- a/packages/api/src/router/app.ts +++ b/packages/api/src/router/app.ts @@ -173,7 +173,7 @@ export const appRouter = createTRPCRouter({ mcp: { enabled: true, description: - "Create a new app (bookmark/shortcut to a service). REQUIRED: name (string), iconUrl (icon URL string), href (app URL, http/https or blank). OPTIONAL: description (string or null), pingUrl (URL to check reachability, or empty string)", + "Create a new app (bookmark/shortcut to a service). REQUIRED: name (string), iconUrl (icon URL string), href (app URL or custom URI scheme such as vscode://, or blank). OPTIONAL: description (string or null), pingUrl (URL to check reachability, or empty string)", }, }) .mutation(async ({ ctx, input }) => { diff --git a/packages/validation/src/app.ts b/packages/validation/src/app.ts index 21a4335be..dfc7652a7 100644 --- a/packages/validation/src/app.ts +++ b/packages/validation/src/app.ts @@ -3,8 +3,7 @@ import { z } from "zod/v4"; export const appHrefSchema = z .string() .trim() - .url() - .regex(/^(?!javascript)[a-zA-Z]*:\/\//i) // javascript: is not allowed, i for case insensitive (so Javascript: is also not allowed) + .refine((val) => !/^javascript:/i.test(val), "JavaScript URIs are not permitted") .or(z.literal("")) .transform((value) => (value.length === 0 ? null : value)) .nullable();