diff --git a/apps/nextjs/src/app/[locale]/manage/about/accordion.module.css b/apps/nextjs/src/app/[locale]/manage/about/accordion.module.css
new file mode 100644
index 000000000..174e134c5
--- /dev/null
+++ b/apps/nextjs/src/app/[locale]/manage/about/accordion.module.css
@@ -0,0 +1,36 @@
+.root {
+ border-radius: var(--mantine-radius-sm);
+ background-color: light-dark(
+ var(--mantine-color-gray-0),
+ var(--mantine-color-dark-6)
+ );
+}
+
+.item {
+ background-color: light-dark(
+ var(--mantine-color-gray-0),
+ var(--mantine-color-dark-6)
+ );
+ border: 1px solid transparent;
+ position: relative;
+ z-index: 0;
+ transition: transform 150ms ease;
+
+ &[data-active] {
+ transform: scale(1.015);
+ z-index: 1;
+ background-color: var(--mantine-color-body);
+ border-color: light-dark(
+ var(--mantine-color-gray-2),
+ var(--mantine-color-dark-4)
+ );
+ box-shadow: var(--mantine-shadow-md);
+ border-radius: var(--mantine-radius-md);
+ }
+}
+
+.chevron {
+ &[data-rotate] {
+ transform: rotate(-90deg);
+ }
+}
diff --git a/apps/nextjs/src/app/[locale]/manage/about/page.tsx b/apps/nextjs/src/app/[locale]/manage/about/page.tsx
new file mode 100644
index 000000000..b7ff7b2a7
--- /dev/null
+++ b/apps/nextjs/src/app/[locale]/manage/about/page.tsx
@@ -0,0 +1,93 @@
+import Image from "next/image";
+import {
+ Accordion,
+ AccordionControl,
+ AccordionItem,
+ AccordionPanel,
+ Center,
+ Group,
+ List,
+ ListItem,
+ Stack,
+ Text,
+ Title,
+} from "@mantine/core";
+import { IconLanguage, IconLibrary, IconUsers } from "@tabler/icons-react";
+
+import { getScopedI18n } from "@homarr/translation/server";
+
+import { getPackageAttributes } from "~/versions/package-reader";
+import logo from "../../../../../public/logo/logo.png";
+import classes from "./accordion.module.css";
+
+export async function generateMetadata() {
+ const t = await getScopedI18n("management");
+ const metaTitle = `${t("metaTitle")} • Homarr`;
+
+ return {
+ title: metaTitle,
+ };
+}
+
+export default async function AboutPage() {
+ const t = await getScopedI18n("management.page.about");
+ const attributes = getPackageAttributes();
+ return (
+
+
+
+
+
+
+ Homarr
+
+
+ {t("version", { version: attributes.version })}
+
+
+
+
+
{t("text")}
+
+
+
+ }>
+ {t("accordion.contributors.title")}
+
+
+
+
+ }>
+ {t("accordion.translators.title")}
+
+
+
+
+ }>
+
+ {t("accordion.libraries.title")}
+
+ {t("accordion.libraries.subtitle", {
+ count: Object.keys(attributes.dependencies).length,
+ })}
+
+
+
+
+
+ {Object.entries(attributes.dependencies).map(([key, value]) => (
+
+ {value.includes("workspace:") ? (
+ {key}
+ ) : (
+ {key}
+ )}
+
+ ))}
+
+
+
+
+
+ );
+}
diff --git a/apps/nextjs/src/react-app-env.d.ts b/apps/nextjs/src/react-app-env.d.ts
new file mode 100644
index 000000000..0357e4f19
--- /dev/null
+++ b/apps/nextjs/src/react-app-env.d.ts
@@ -0,0 +1,4 @@
+declare module "*.png";
+declare module "*.svg";
+declare module "*.jpeg";
+declare module "*.jpg";
diff --git a/apps/nextjs/src/versions/package-reader.ts b/apps/nextjs/src/versions/package-reader.ts
new file mode 100644
index 000000000..4142309ee
--- /dev/null
+++ b/apps/nextjs/src/versions/package-reader.ts
@@ -0,0 +1,13 @@
+import packageJson from "~/../package.json";
+
+const getPackageVersion = () => packageJson.version;
+const getDependencies = (): PackageJsonDependencies => packageJson.dependencies;
+
+export const getPackageAttributes = () => {
+ return {
+ version: getPackageVersion(),
+ dependencies: getDependencies(),
+ };
+};
+
+type PackageJsonDependencies = { [key in string]: string };
diff --git a/packages/translation/src/lang/en.ts b/packages/translation/src/lang/en.ts
index ef24d4bf7..81cc936f6 100644
--- a/packages/translation/src/lang/en.ts
+++ b/packages/translation/src/lang/en.ts
@@ -948,6 +948,22 @@ export default {
},
},
},
+ about: {
+ version: "Version {version}",
+ text: "Homarr is a community driven open source project that is being maintained by volunteers. Thanks to these people, Homarr has been a growing project since 2021. Our team is working completely remote from many different countries on Homarr in their leisure time for no compensation.",
+ accordion: {
+ contributors: {
+ title: "Contributors",
+ },
+ translators: {
+ title: "Translators",
+ },
+ libraries: {
+ title: "Libraries",
+ subtitle: "{count} used",
+ },
+ },
+ },
},
},
} as const;