chore: refine v2 beta resources

This commit is contained in:
ajnart committed 2026-09-06 19:36:08 +02:00
1 parent 7ba04f8019
commit ce03ba8a59
5 files changed
+116 -76

No files matched your search

+1 -1
View File
@@ -41,7 +41,7 @@ body:
attributes:
label: Affected page, feature, or widget
description: Name the exact page, widget, integration, container, sidebar, or action involved.
placeholder: Board editor — moving a widget into a container
placeholder: "Board editor: moving a widget into a container"
validations:
required: true
+1 -1
View File
@@ -13,7 +13,7 @@ import { IconArrowRight } from '@tabler/icons-react';
:::info Homarr v2 beta is available
There is no release date yet: Homarr v2 will become the default when it is ready. Read [what is new](https://v2.preview.homarr.dev/blog), try the [hosted preview](https://app-v2.preview.homarr.dev), [join us on Discord](https://discord.com/invite/aCsmEV5RgA), and [share your feedback](https://github.com/homarr-labs/homarr/issues/new?template=v2_beta_feedback.yml). Everyone uses Homarr differently, so every report helps us find what breaks or does not feel right before release. SQLite administrators can download a full backup directly from the beta announcement before changing images.
There is no release date yet: Homarr v2 will become the default when it is ready. Read [what is new](https://v2.preview.homarr.dev/blog/2026/09/03/homarr-2.0), browse the [v2 documentation](https://v2.preview.homarr.dev/docs) and [Homarr Workshop](https://v2.preview.homarr.dev/workshop), try the [hosted preview](https://app-v2.preview.homarr.dev), [join us on Discord](https://discord.com/invite/aCsmEV5RgA), and [share your feedback](https://github.com/homarr-labs/homarr/issues/new?template=v2_beta_feedback.yml). Everyone uses Homarr differently, so every report helps us find what breaks or does not feel right before release. SQLite administrators can download a full backup directly from the beta announcement before changing images.
:::
@@ -1,5 +1,7 @@
export const v2BetaBlogUrl = "https://v2.preview.homarr.dev/blog";
export const v2BetaBlogUrl = "https://v2.preview.homarr.dev/blog/2026/09/03/homarr-2.0";
export const v2BetaDocsUrl = "https://v2.preview.homarr.dev/docs";
export const v2BetaPreviewUrl = "https://app-v2.preview.homarr.dev";
export const v2BetaWorkshopUrl = "https://v2.preview.homarr.dev/workshop";
export const v2BetaFeedbackUrl = "https://github.com/homarr-labs/homarr/issues/new?template=v2_beta_feedback.yml";
export const v2BetaDiscussionUrl = "https://github.com/homarr-labs/homarr/issues/6600";
export const discordInviteUrl = "https://discord.com/invite/aCsmEV5RgA";
@@ -11,14 +11,13 @@
.banner::after {
position: absolute;
z-index: -1;
top: -1.75rem;
right: 12%;
right: -0.35rem;
bottom: -1.75rem;
color: rgb(255 255 255 / 9%);
font-size: 5.5rem;
font-weight: 900;
line-height: 1;
content: "v2";
transform: rotate(5deg);
}
.copy {
@@ -40,14 +39,18 @@
.modalHero::after {
position: absolute;
z-index: -1;
top: -3.5rem;
right: 1.5rem;
right: -0.75rem;
bottom: -3.25rem;
color: rgb(255 255 255 / 8%);
font-size: 12rem;
font-weight: 900;
line-height: 1;
content: "v2";
transform: rotate(5deg);
}
.featureCard {
height: 100%;
background: light-dark(var(--mantine-color-white), var(--mantine-color-dark-7));
}
.diffViewer {
@@ -89,13 +92,3 @@
color: light-dark(var(--mantine-color-red-9), var(--mantine-color-red-3));
background: light-dark(var(--mantine-color-red-0), rgb(250 82 82 / 15%));
}
@media (max-width: $mantine-breakpoint-xs) {
.banner::after {
right: 35%;
}
.modalHero::after {
right: -2rem;
}
}
@@ -1,7 +1,6 @@
"use client";
import type { ReactNode } from "react";
import { useState } from "react";
import {
ActionIcon,
Accordion,
@@ -19,6 +18,7 @@ import {
} from "@mantine/core";
import {
IconArrowsMove,
IconBook2,
IconBrandCss3,
IconBrandDiscord,
IconBrandGithub,
@@ -38,7 +38,15 @@ import { setClientCookie } from "@homarr/common";
import { createModal, useModalAction } from "@homarr/modals";
import { BackupExportButton } from "~/components/backup";
import { discordInviteUrl, v2BetaBlogUrl, v2BetaDiscussionUrl, v2BetaFeedbackUrl, v2BetaPreviewUrl } from "./constants";
import {
discordInviteUrl,
v2BetaBlogUrl,
v2BetaDiscussionUrl,
v2BetaDocsUrl,
v2BetaFeedbackUrl,
v2BetaPreviewUrl,
v2BetaWorkshopUrl,
} from "./constants";
import classes from "./v2-beta-announcement.module.css";
const diffLineClassNames = {
@@ -129,37 +137,35 @@ interface V2BetaAnnouncementModalProps {
}
const V2BetaAnnouncementModal = createModal<V2BetaAnnouncementModalProps>(({ innerProps }) => {
const [openedSection, setOpenedSection] = useState<string | null>("workshop");
return (
<Stack gap="lg">
<Paper className={classes.modalHero} p={{ base: "lg", sm: "xl" }} radius="md">
<Stack gap="sm" maw={760}>
<Title order={2}>Help us get Homarr v2 ready</Title>
<Text>
There is no release date yet. Homarr v2 will become the default when it is ready—and we need you to test it
There is no release date yet. Homarr v2 will become the default when it is ready, and we need you to test it
and share feedback before we can be confident enough to make that switch.
</Text>
</Stack>
</Paper>
<Accordion variant="separated" radius="md" value={openedSection} onChange={setOpenedSection}>
<FeatureAccordionItem value="workshop" icon={<IconBrandCss3 size={20} />} title="Homarr Workshop">
<SimpleGrid cols={{ base: 1, sm: 2 }} spacing="md">
<FeatureCard icon={<IconBrandCss3 size={21} />} title="Homarr Workshop">
Share and discover Custom Widgets and CSS made by the Homarr community.
</FeatureAccordionItem>
<FeatureAccordionItem
value="drag-and-drop"
icon={<IconArrowsMove size={20} />}
title="Complete drag-and-drop rewrite"
>
</FeatureCard>
<FeatureCard icon={<IconArrowsMove size={21} />} title="Complete drag-and-drop rewrite">
Move, resize, multi-select, and arrange your dashboard with a board editor rebuilt from the ground up.
</FeatureAccordionItem>
<FeatureAccordionItem value="custom-widgets" icon={<IconWand size={20} />} title="Custom Widgets v2">
</FeatureCard>
<FeatureCard icon={<IconWand size={21} />} title="Custom Widgets v2">
We think you can make almost any widget with live previews, API requests, options, actions, and validation.
</FeatureAccordionItem>
<FeatureAccordionItem value="assistant" icon={<IconRobot size={20} />} title="Homarr Assistant">
Ask questions, find what you need, and manage Homarr through permission-aware tools.
</FeatureAccordionItem>
</FeatureCard>
<FeatureCard icon={<IconRobot size={21} />} title="Homarr Assistant">
Homarr Assistant can directly make a Custom Widget for you. Try giving it the API docs for your latest
selfhosted tool and asking it to build a custom widget for it.
</FeatureCard>
</SimpleGrid>
<Accordion variant="separated" radius="md">
<Accordion.Item value="installation">
<Accordion.Control
icon={
@@ -180,6 +186,18 @@ const V2BetaAnnouncementModal = createModal<V2BetaAnnouncementModalProps>(({ inn
<V2BetaInstallInstructions canExportBackup={innerProps.canExportBackup} />
</Accordion.Panel>
</Accordion.Item>
<FaqAccordionItem value="current-data" title="Can I use my current Homarr data?">
Use the separate <code>homarr-v2</code> volume shown in the example. Keep your current volume untouched so you
can return to your current Homarr instance.
</FaqAccordionItem>
<FaqAccordionItem value="release-date" title="When will Homarr v2 be released?">
There is no release date yet. V2 will become the default when it is ready, after enough testing and feedback
gives us confidence in the release.
</FaqAccordionItem>
<FaqAccordionItem value="feedback" title="What makes a useful feedback report?">
Tell us exactly what happened and what you expected instead. Add screenshots or a recording, your resolution
and browser zoom, board column count, device, browser, and exact reproduction steps whenever possible.
</FaqAccordionItem>
</Accordion>
<Alert variant="light" color="red" icon={<IconHeartHandshake size={22} />} title="Your testing is essential">
@@ -198,6 +216,28 @@ const V2BetaAnnouncementModal = createModal<V2BetaAnnouncementModalProps>(({ inn
>
Try the hosted preview
</Button>
<Button
component="a"
href={v2BetaWorkshopUrl}
target="_blank"
rel="noopener noreferrer"
variant="light"
size="md"
leftSection={<IconBrandCss3 size={18} />}
>
Open Homarr Workshop
</Button>
<Button
component="a"
href={v2BetaDocsUrl}
target="_blank"
rel="noopener noreferrer"
variant="default"
size="md"
leftSection={<IconBook2 size={18} />}
>
Read the v2 docs
</Button>
<Button
component="a"
href={v2BetaBlogUrl}
@@ -220,6 +260,17 @@ const V2BetaAnnouncementModal = createModal<V2BetaAnnouncementModalProps>(({ inn
>
Join us on Discord
</Button>
<Button
component="a"
href={v2BetaDiscussionUrl}
target="_blank"
rel="noopener noreferrer"
variant="default"
size="md"
rightSection={<IconExternalLink size={15} />}
>
Follow v2 development
</Button>
</SimpleGrid>
<Button
@@ -234,23 +285,6 @@ const V2BetaAnnouncementModal = createModal<V2BetaAnnouncementModalProps>(({ inn
>
Report anything that breaks or feels wrong
</Button>
<Group justify="space-between" align="center">
<Text c="dimmed" size="xs" maw={720}>
Please use a separate volume for the beta and keep a backup of your current Homarr data.
</Text>
<Button
component="a"
href={v2BetaDiscussionUrl}
target="_blank"
rel="noopener noreferrer"
variant="subtle"
size="compact-sm"
rightSection={<IconExternalLink size={15} />}
>
Follow v2 development
</Button>
</Group>
</Stack>
);
}).withOptions({
@@ -265,11 +299,6 @@ interface V2BetaInstallInstructionsProps {
const V2BetaInstallInstructions = ({ canExportBackup }: V2BetaInstallInstructionsProps) => (
<Stack gap="lg">
<Alert color="yellow" title="Keep your current Homarr data safe">
Run the beta with the separate <code>homarr-v2</code> volume shown below. Keep a backup, and do not point this
prerelease image at the only copy of your production data.
</Alert>
{canExportBackup ? (
<Paper withBorder p="md" radius="md">
<Stack gap="sm">
@@ -336,31 +365,47 @@ const V2BetaInstallInstructions = ({ canExportBackup }: V2BetaInstallInstruction
</Stack>
);
interface FeatureAccordionItemProps {
value: string;
interface FeatureCardProps {
icon: ReactNode;
title: string;
children: ReactNode;
}
const FeatureAccordionItem = ({ value, icon, title, children }: FeatureAccordionItemProps) => (
<Accordion.Item value={value}>
<Accordion.Control
icon={
<ThemeIcon variant="light" color="red" radius="md" size="lg">
{icon}
</ThemeIcon>
}
aria-label={title}
>
<Text fw={750}>{title}</Text>
</Accordion.Control>
<Accordion.Panel>
<Box pl={48}>
const FeatureCard = ({ icon, title, children }: FeatureCardProps) => (
<Paper className={classes.featureCard} withBorder p="md" radius="md">
<Group gap="sm" align="flex-start" wrap="nowrap">
<ThemeIcon variant="light" color="red" radius="md" size="lg">
{icon}
</ThemeIcon>
<Box>
<Text fw={750} size="sm">
{title}
</Text>
<Text c="dimmed" size="sm">
{children}
</Text>
</Box>
</Group>
</Paper>
);
interface FaqAccordionItemProps {
value: string;
title: string;
children: ReactNode;
}
const FaqAccordionItem = ({ value, title, children }: FaqAccordionItemProps) => (
<Accordion.Item value={value}>
<Accordion.Control aria-label={title}>
<Text fw={700} size="sm">
{title}
</Text>
</Accordion.Control>
<Accordion.Panel>
<Text c="dimmed" size="sm">
{children}
</Text>
</Accordion.Panel>
</Accordion.Item>
);