migrate from astro+netlify to tanstack start + self-hosted
Replace the Astro static site with a TanStack Start (Bun runtime) app and add Dockerfile + compose files so the site can be served from home-main-2 behind the home-reverse-proxy-1 Caddy instead of Netlify. CI workflow rewritten to build a container image and SSH-deploy to the home host.
This commit is contained in:
|
Before Width: | Height: | Size: 3.3 MiB After Width: | Height: | Size: 3.3 MiB |
@@ -0,0 +1,68 @@
|
||||
import Section from "./Section";
|
||||
|
||||
type NavigationItem =
|
||||
| { type: "link"; path: string; label: string }
|
||||
| { type: "text"; content: string };
|
||||
|
||||
type NavigationGroup = {
|
||||
title: string;
|
||||
className?: string;
|
||||
items: Array<NavigationItem>;
|
||||
};
|
||||
|
||||
const tree: Array<NavigationGroup> = [
|
||||
{
|
||||
title: "Übersicht",
|
||||
items: [{ type: "link", path: "/", label: "Startseite" }],
|
||||
},
|
||||
{
|
||||
title: "Rechtliches",
|
||||
items: [
|
||||
{ type: "link", path: "/legal/imprint", label: "Impressum" },
|
||||
{ type: "link", path: "/legal/privacy", label: "Datenschutzerklärung" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Zugehöriges",
|
||||
items: [
|
||||
{
|
||||
type: "link",
|
||||
path: "https://enrico.buehler.earth",
|
||||
label: "Enrico Bühler",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "",
|
||||
className: "ml-auto mr-0 self-end",
|
||||
items: [{ type: "text", content: "Made with ❤️ in Rottweil" }],
|
||||
},
|
||||
];
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="bg-neutral-accent">
|
||||
<Section>
|
||||
<div className="flex flex-row flex-wrap gap-12 w-full pb-8">
|
||||
{tree.map((group) => (
|
||||
<div key={group.title || "misc"} className={group.className}>
|
||||
{group.title && <h3 className="mb-2">{group.title}</h3>}
|
||||
<div className="flex flex-col">
|
||||
{group.items.map((item, i) => {
|
||||
if (item.type === "link") {
|
||||
return (
|
||||
<a key={`${item.path}-${i}`} href={item.path}>
|
||||
{item.label}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
return <p key={`text-${i}`}>{item.content}</p>;
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Section>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import Logo from "./Logo";
|
||||
|
||||
export default function Header() {
|
||||
return (
|
||||
<header
|
||||
id="nav-container"
|
||||
className="fixed -top-1 w-full h-height-header z-50"
|
||||
>
|
||||
<div className="flex flex-row justify-between items-center h-full w-full max-w-max-section m-auto px-section-main-x">
|
||||
<Link
|
||||
to="/"
|
||||
className="w-[120px] h-[120px] flex justify-center items-center rounded-3xl p-2 backdrop-blur-3xl"
|
||||
>
|
||||
<Logo />
|
||||
</Link>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { FC, ReactNode } from "react";
|
||||
import Footer from "./Footer";
|
||||
import Header from "./Header";
|
||||
|
||||
const Layout: FC<{ children: ReactNode; showHeader?: boolean }> = ({
|
||||
children,
|
||||
showHeader = true,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
{showHeader && <Header />}
|
||||
<main className="min-h-screen">{children}</main>
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
@@ -1,97 +0,0 @@
|
||||
---
|
||||
import Section from "../Section.astro";
|
||||
|
||||
enum NavigationItemType {
|
||||
Link = 0,
|
||||
Text = 1,
|
||||
}
|
||||
|
||||
type NavigationItem =
|
||||
| {
|
||||
path: string;
|
||||
label: string;
|
||||
type: NavigationItemType.Link;
|
||||
}
|
||||
| {
|
||||
type: NavigationItemType.Text;
|
||||
content: string;
|
||||
};
|
||||
|
||||
type NavigationGroup = {
|
||||
title: string;
|
||||
class?: string;
|
||||
items: Array<NavigationItem>;
|
||||
};
|
||||
|
||||
const tree: Array<NavigationGroup> = [
|
||||
{
|
||||
title: "Übersicht",
|
||||
items: [
|
||||
{
|
||||
path: "/",
|
||||
type: NavigationItemType.Link,
|
||||
label: "Startseite",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Rechtliches",
|
||||
items: [
|
||||
{
|
||||
path: "/legal/imprint",
|
||||
label: "Impressum",
|
||||
type: NavigationItemType.Link,
|
||||
},
|
||||
{
|
||||
path: "/legal/privacy",
|
||||
label: "Datenschutzerklärung",
|
||||
type: NavigationItemType.Link,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Zugehöriges",
|
||||
items: [
|
||||
{
|
||||
path: "https://enrico.buehler.earth",
|
||||
label: "Enrico Bühler",
|
||||
type: NavigationItemType.Link,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "",
|
||||
class: "ml-auto mr-0 self-end",
|
||||
items: [
|
||||
{
|
||||
type: NavigationItemType.Text,
|
||||
content: "Made with ❤️ in Rottweil",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<footer class="bg-neutral-accent">
|
||||
<Section>
|
||||
<div class="flex flex-row flex-wrap gap-12 w-full pb-8">
|
||||
{
|
||||
tree.map((group) => (
|
||||
<div class={group.class}>
|
||||
{group.title && <h3 class="mb-2">{group.title}</h3>}
|
||||
<div class="flex flex-col">
|
||||
{group.items.map((item) => {
|
||||
switch (item.type) {
|
||||
case NavigationItemType.Link:
|
||||
return <a href={item.path}>{item.label}</a>;
|
||||
case NavigationItemType.Text:
|
||||
return <p>{item.content}</p>;
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</Section>
|
||||
</footer>
|
||||
@@ -1,16 +0,0 @@
|
||||
---
|
||||
import Logo from "../Logo/Logo.astro";
|
||||
---
|
||||
|
||||
<header id="nav-container" class="fixed -top-1 w-full h-height-header z-50">
|
||||
<div
|
||||
class="flex flex-row justify-between items-center h-full w-full max-w-max-section m-auto px-section-main-x"
|
||||
>
|
||||
<a
|
||||
href="/"
|
||||
class="w-[120px] h-[120px] flex justify-center items-center rounded-3xl p-2 backdrop-blur-3xl"
|
||||
>
|
||||
<Logo />
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { FC, ReactNode } from "react";
|
||||
import Section from "./Section";
|
||||
|
||||
const LegalPage: FC<{ children: ReactNode }> = ({ children }) => {
|
||||
return (
|
||||
<Section>
|
||||
<article className="markdown">{children}</article>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
export default LegalPage;
|
||||
@@ -1,28 +1,32 @@
|
||||
<!--?xml version="1.0" encoding="UTF-8"?-->
|
||||
<svg
|
||||
id="Ebene_1"
|
||||
data-name="Ebene 1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 643.6 382.49"
|
||||
>
|
||||
<path
|
||||
class="fill-main"
|
||||
d="M128.61,230.82v25.76c-3.39,3.13-15.9,9.57-36.95,9.57s-33.56-6.44-36.95-9.57v-69.51c-6.51-1.15-13.96-1.89-22.4-1.89s-15.9.75-22.4,1.89v71.69c0,30.24,34.38,52.18,81.75,52.18s81.75-21.95,81.75-52.18v-27.9c.54-3.26,10.53-11.58,29.7-16.61v-45.87c-44.16,8.16-74.5,32.3-74.5,62.43Z"
|
||||
></path>
|
||||
<path
|
||||
class="fill-main"
|
||||
d="M552.55,63.76c-27.7,0-50.91,7.57-65.32,19.94-12.48-7.97-28.41-13.93-46.65-17.17.74,3.66,1.14,7.42,1.14,11.28v34.8c19.17,5.03,29.16,13.33,29.7,16.56v52.56c6.51,1.15,13.96,1.89,22.4,1.89s15.9-.75,22.4-1.89v-63.83c3.41-3.08,15.75-9.34,36.33-9.34s32.92,6.26,36.33,9.34v63.83c6.51,1.15,13.96,1.89,22.4,1.89s15.9-.75,22.4-1.89v-66.1c0-30.06-34.12-51.88-81.13-51.88Z"
|
||||
></path>
|
||||
<path
|
||||
class="fill-main"
|
||||
d="M322.42,370.08c-61.63,0-108.1-28.12-108.1-65.41V77.82c0-37.29,46.48-65.41,108.1-65.41s108.1,28.12,108.1,65.41v226.86c0,37.29-46.47,65.41-108.1,65.41ZM322.42,57.2c-41.19,0-62.5,15.85-63.31,20.66v226.81c.81,4.76,22.11,20.61,63.31,20.61s62.5-15.85,63.31-20.66V77.82c-.81-4.76-22.12-20.61-63.31-20.61Z"
|
||||
></path>
|
||||
<path
|
||||
class="fill-main"
|
||||
d="M353.48,72.19c-32.05,10.89-52.91,31.4-53.44,56.03h-.03s0,.96,0,.96v32.77c6.51,1.15,13.96,1.89,22.4,1.89s15.9-.75,22.4-1.89v-32.73c.56-3.27,10.54-11.57,29.7-16.6v-31.07c-2.97-2.53-10.07-6.46-21.03-9.36Z"
|
||||
></path>
|
||||
<path
|
||||
class="fill-main"
|
||||
d="M322.42,290.86c8.44,0,15.9-.75,22.4-1.89v-58.15c0-30.13-30.35-54.26-74.5-62.43v45.87c19.17,5.03,29.16,13.33,29.7,16.56v58.15c6.51,1.15,13.96,1.89,22.4,1.89Z"
|
||||
></path>
|
||||
</svg>
|
||||
export default function Logo() {
|
||||
return (
|
||||
<svg
|
||||
aria-label="unom Logo"
|
||||
role="img"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 643.6 382.49"
|
||||
>
|
||||
<title>unom</title>
|
||||
<path
|
||||
className="fill-main"
|
||||
d="M128.61,230.82v25.76c-3.39,3.13-15.9,9.57-36.95,9.57s-33.56-6.44-36.95-9.57v-69.51c-6.51-1.15-13.96-1.89-22.4-1.89s-15.9.75-22.4,1.89v71.69c0,30.24,34.38,52.18,81.75,52.18s81.75-21.95,81.75-52.18v-27.9c.54-3.26,10.53-11.58,29.7-16.61v-45.87c-44.16,8.16-74.5,32.3-74.5,62.43Z"
|
||||
/>
|
||||
<path
|
||||
className="fill-main"
|
||||
d="M552.55,63.76c-27.7,0-50.91,7.57-65.32,19.94-12.48-7.97-28.41-13.93-46.65-17.17.74,3.66,1.14,7.42,1.14,11.28v34.8c19.17,5.03,29.16,13.33,29.7,16.56v52.56c6.51,1.15,13.96,1.89,22.4,1.89s15.9-.75,22.4-1.89v-63.83c3.41-3.08,15.75-9.34,36.33-9.34s32.92,6.26,36.33,9.34v63.83c6.51,1.15,13.96,1.89,22.4,1.89s15.9-.75,22.4-1.89v-66.1c0-30.06-34.12-51.88-81.13-51.88Z"
|
||||
/>
|
||||
<path
|
||||
className="fill-main"
|
||||
d="M322.42,370.08c-61.63,0-108.1-28.12-108.1-65.41V77.82c0-37.29,46.48-65.41,108.1-65.41s108.1,28.12,108.1,65.41v226.86c0,37.29-46.47,65.41-108.1,65.41ZM322.42,57.2c-41.19,0-62.5,15.85-63.31,20.66v226.81c.81,4.76,22.11,20.61,63.31,20.61s62.5-15.85,63.31-20.66V77.82c-.81-4.76-22.12-20.61-63.31-20.61Z"
|
||||
/>
|
||||
<path
|
||||
className="fill-main"
|
||||
d="M353.48,72.19c-32.05,10.89-52.91,31.4-53.44,56.03h-.03s0,.96,0,.96v32.77c6.51,1.15,13.96,1.89,22.4,1.89s15.9-.75,22.4-1.89v-32.73c.56-3.27,10.54-11.57,29.7-16.6v-31.07c-2.97-2.53-10.07-6.46-21.03-9.36Z"
|
||||
/>
|
||||
<path
|
||||
className="fill-main"
|
||||
d="M322.42,290.86c8.44,0,15.9-.75,22.4-1.89v-58.15c0-30.13-30.35-54.26-74.5-62.43v45.87c19.17,5.03,29.16,13.33,29.7,16.56v58.15c6.51,1.15,13.96,1.89,22.4,1.89Z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Ebene_1" data-name="Ebene 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #654eff;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #fff;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="cls-1" x="87.76" y="87.76" width="824.48" height="824.48" rx="200.39" ry="200.39"/>
|
||||
<g>
|
||||
<path class="cls-2" d="M306.81,545.97v25.76c-3.39,3.13-15.9,9.57-36.95,9.57s-33.56-6.44-36.95-9.57v-69.51c-6.51-1.15-13.96-1.89-22.4-1.89s-15.9.75-22.4,1.89v71.69c0,30.24,34.38,52.18,81.75,52.18s81.75-21.95,81.75-52.18v-27.9c.54-3.26,10.53-11.58,29.7-16.61v-45.87c-44.16,8.16-74.5,32.3-74.5,62.43Z"/>
|
||||
<path class="cls-2" d="M730.75,378.92c-27.7,0-50.91,7.57-65.32,19.94-12.48-7.97-28.41-13.93-46.65-17.17.74,3.66,1.14,7.42,1.14,11.28v34.8c19.17,5.03,29.16,13.33,29.7,16.56v52.56c6.51,1.15,13.96,1.89,22.4,1.89s15.9-.75,22.4-1.89v-63.83c3.41-3.08,15.75-9.34,36.33-9.34s32.92,6.26,36.33,9.34v63.83c6.51,1.15,13.96,1.89,22.4,1.89s15.9-.75,22.4-1.89v-66.1c0-30.06-34.12-51.88-81.13-51.88Z"/>
|
||||
<path class="cls-2" d="M500.62,685.24c-61.63,0-108.1-28.12-108.1-65.41v-226.86c0-37.29,46.48-65.41,108.1-65.41s108.1,28.12,108.1,65.41v226.86c0,37.29-46.47,65.41-108.1,65.41ZM500.62,372.36c-41.19,0-62.5,15.85-63.31,20.66v226.81c.81,4.76,22.11,20.61,63.31,20.61s62.5-15.85,63.31-20.66v-226.81c-.81-4.76-22.12-20.61-63.31-20.61Z"/>
|
||||
<path class="cls-2" d="M531.68,387.34c-32.05,10.89-52.91,31.4-53.44,56.03h-.03s0,.96,0,.96v32.77c6.51,1.15,13.96,1.89,22.4,1.89s15.9-.75,22.4-1.89v-32.73c.56-3.27,10.54-11.57,29.7-16.6v-31.07c-2.97-2.53-10.07-6.46-21.03-9.36Z"/>
|
||||
<path class="cls-2" d="M500.62,606.01c8.44,0,15.9-.75,22.4-1.89v-58.15c0-30.13-30.35-54.26-74.5-62.43v45.87c19.17,5.03,29.16,13.33,29.7,16.56v58.15c6.51,1.15,13.96,1.89,22.4,1.89Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,28 @@
|
||||
export default function LogoQuadBG() {
|
||||
return (
|
||||
<svg
|
||||
aria-label="unom Logo"
|
||||
role="img"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 1000 1000"
|
||||
>
|
||||
<title>unom</title>
|
||||
<rect
|
||||
fill="#654eff"
|
||||
x="87.76"
|
||||
y="87.76"
|
||||
width="824.48"
|
||||
height="824.48"
|
||||
rx="200.39"
|
||||
ry="200.39"
|
||||
/>
|
||||
<g fill="#fff">
|
||||
<path d="M306.81,545.97v25.76c-3.39,3.13-15.9,9.57-36.95,9.57s-33.56-6.44-36.95-9.57v-69.51c-6.51-1.15-13.96-1.89-22.4-1.89s-15.9.75-22.4,1.89v71.69c0,30.24,34.38,52.18,81.75,52.18s81.75-21.95,81.75-52.18v-27.9c.54-3.26,10.53-11.58,29.7-16.61v-45.87c-44.16,8.16-74.5,32.3-74.5,62.43Z" />
|
||||
<path d="M730.75,378.92c-27.7,0-50.91,7.57-65.32,19.94-12.48-7.97-28.41-13.93-46.65-17.17.74,3.66,1.14,7.42,1.14,11.28v34.8c19.17,5.03,29.16,13.33,29.7,16.56v52.56c6.51,1.15,13.96,1.89,22.4,1.89s15.9-.75,22.4-1.89v-63.83c3.41-3.08,15.75-9.34,36.33-9.34s32.92,6.26,36.33,9.34v63.83c6.51,1.15,13.96,1.89,22.4,1.89s15.9-.75,22.4-1.89v-66.1c0-30.06-34.12-51.88-81.13-51.88Z" />
|
||||
<path d="M500.62,685.24c-61.63,0-108.1-28.12-108.1-65.41v-226.86c0-37.29,46.48-65.41,108.1-65.41s108.1,28.12,108.1,65.41v226.86c0,37.29-46.47,65.41-108.1,65.41ZM500.62,372.36c-41.19,0-62.5,15.85-63.31,20.66v226.81c.81,4.76,22.11,20.61,63.31,20.61s62.5-15.85,63.31-20.66v-226.81c-.81-4.76-22.12-20.61-63.31-20.61Z" />
|
||||
<path d="M531.68,387.34c-32.05,10.89-52.91,31.4-53.44,56.03h-.03s0,.96,0,.96v32.77c6.51,1.15,13.96,1.89,22.4,1.89s15.9-.75,22.4-1.89v-32.73c.56-3.27,10.54-11.57,29.7-16.6v-31.07c-2.97-2.53-10.07-6.46-21.03-9.36Z" />
|
||||
<path d="M500.62,606.01c8.44,0,15.9-.75,22.4-1.89v-58.15c0-30.13-30.35-54.26-74.5-62.43v45.87c19.17,5.03,29.16,13.33,29.7,16.56v58.15c6.51,1.15,13.96,1.89,22.4,1.89Z" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
---
|
||||
import type { HTMLAttributes } from "astro/types";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
|
||||
const section = cva("relative w-full", {
|
||||
variants: {
|
||||
padding: {
|
||||
true: "px-section-main-x py-section-main-y",
|
||||
false: "p-0",
|
||||
},
|
||||
maxWidth: {
|
||||
true: "max-w-max-section mx-auto",
|
||||
false: "",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export interface Props
|
||||
extends HTMLAttributes<"section">,
|
||||
VariantProps<typeof section> {}
|
||||
|
||||
const { padding = true, maxWidth = true, ...props } = Astro.props;
|
||||
---
|
||||
|
||||
<section {...props} class={section({ padding, maxWidth })}>
|
||||
<slot />
|
||||
</section>
|
||||
@@ -0,0 +1,36 @@
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import type { HTMLAttributes } from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const section = cva("relative w-full", {
|
||||
variants: {
|
||||
padding: {
|
||||
true: "px-section-main-x py-section-main-y",
|
||||
false: "p-0",
|
||||
},
|
||||
maxWidth: {
|
||||
true: "max-w-max-section mx-auto",
|
||||
false: "",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
padding: true,
|
||||
maxWidth: true,
|
||||
},
|
||||
});
|
||||
|
||||
type Props = HTMLAttributes<HTMLElement> & VariantProps<typeof section>;
|
||||
|
||||
export default function Section({
|
||||
padding,
|
||||
maxWidth,
|
||||
className,
|
||||
...props
|
||||
}: Props) {
|
||||
return (
|
||||
<section
|
||||
{...props}
|
||||
className={cn(section({ padding, maxWidth }), className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
---
|
||||
layout: "@/layouts/MarkdownLayout.astro"
|
||||
title: Impressum
|
||||
---
|
||||
|
||||
# Impressum
|
||||
|
||||
Angaben gemäß § 5 TMG
|
||||
@@ -45,4 +40,4 @@ Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unt
|
||||
Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen.
|
||||
|
||||
Quelle:
|
||||
<https://www.e-recht24.de>
|
||||
<https://www.e-recht24.de>
|
||||
@@ -1,8 +1,3 @@
|
||||
---
|
||||
layout: "@/layouts/MarkdownLayout.astro"
|
||||
title: Datenschutzerklärung
|
||||
---
|
||||
|
||||
# Datenschutzerklärung
|
||||
|
||||
## 1. Datenschutz auf einen Blick
|
||||
@@ -139,4 +134,4 @@ Die Verarbeitung dieser Daten erfolgt auf Grundlage von Art. 6 Abs. 1 lit. b DSG
|
||||
Die von Ihnen an uns per Kontaktanfragen übersandten Daten verbleiben bei uns, bis Sie uns zur Löschung auffordern, Ihre Einwilligung zur Speicherung widerrufen oder der Zweck für die Datenspeicherung entfällt (z. B. nach abgeschlossener Bearbeitung Ihres Anliegens). Zwingende gesetzliche Bestimmungen – insbesondere gesetzliche Aufbewahrungsfristen – bleiben unberührt.
|
||||
|
||||
Quelle:
|
||||
<https://www.e-recht24.de>
|
||||
<https://www.e-recht24.de>
|
||||
@@ -1,36 +0,0 @@
|
||||
---
|
||||
import { cn } from "@/lib/utils.ts";
|
||||
|
||||
const anim = {
|
||||
old: {
|
||||
name: "pageLeave",
|
||||
duration: "0.0s",
|
||||
easing: "ease-out",
|
||||
fillMode: "forwards",
|
||||
},
|
||||
new: {
|
||||
name: "pageEnter",
|
||||
duration: "0.7s",
|
||||
easing: "cubic-bezier(0.23, 1, 0.32, 1)",
|
||||
fillMode: "forwards",
|
||||
},
|
||||
};
|
||||
|
||||
export interface Props {
|
||||
inset?: boolean;
|
||||
}
|
||||
|
||||
const slideAnimation = {
|
||||
forwards: anim,
|
||||
backwards: anim,
|
||||
};
|
||||
|
||||
const { inset = true } = Astro.props;
|
||||
---
|
||||
|
||||
<main
|
||||
transition:animate={slideAnimation}
|
||||
class={cn("min-h-screen", inset ? "pt-height-header" : "")}
|
||||
>
|
||||
<slot />
|
||||
</main>
|
||||
@@ -1,16 +0,0 @@
|
||||
---
|
||||
import "@/styles/markdown.css";
|
||||
import Section from "@/components/Section.astro";
|
||||
import MainLayout from "./MainLayout.astro";
|
||||
import RootLayout from "./RootLayout.astro";
|
||||
|
||||
const { frontmatter } = Astro.props;
|
||||
---
|
||||
|
||||
<RootLayout title={frontmatter.title}>
|
||||
<MainLayout>
|
||||
<Section>
|
||||
<slot />
|
||||
</Section>
|
||||
</MainLayout>
|
||||
</RootLayout>
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
import Footer from "@/components/Layout/Footer.astro";
|
||||
import Header from "@/components/Layout/Header.astro";
|
||||
import "@/styles/global.css";
|
||||
import "@fontsource/inter";
|
||||
import { ClientRouter } from "astro:transitions";
|
||||
|
||||
export interface Props {
|
||||
title: string;
|
||||
showHeader?: boolean;
|
||||
}
|
||||
|
||||
const { title, showHeader = true } = Astro.props;
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="description" content="Kreative Webentwicklung aus Rottweil" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<slot name="head" />
|
||||
<script
|
||||
is:inline
|
||||
defer
|
||||
data-domain="unom.io"
|
||||
src="https://analytics.unom.io/js/plausible.js"></script>
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>unom - {title}</title>
|
||||
<ClientRouter />
|
||||
</head>
|
||||
<body>
|
||||
{showHeader && <Header transition:name="header" transition:persist />}
|
||||
<slot />
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
import RootLayout from "@/layouts/RootLayout.astro";
|
||||
import "../styles/global.css";
|
||||
import MainLayout from "@/layouts/MainLayout.astro";
|
||||
import Landing from "@/sections/Landing/Landing.astro";
|
||||
---
|
||||
|
||||
<RootLayout showHeader={false} title="Kreative Webentwicklung">
|
||||
<MainLayout inset={false}>
|
||||
<Landing />
|
||||
</MainLayout>
|
||||
</RootLayout>
|
||||
@@ -0,0 +1,18 @@
|
||||
import { createRouter as createTanStackRouter } from "@tanstack/react-router";
|
||||
import { routeTree } from "./routeTree.gen";
|
||||
|
||||
export function getRouter() {
|
||||
const router = createTanStackRouter({
|
||||
routeTree,
|
||||
scrollRestoration: true,
|
||||
defaultPreload: "intent",
|
||||
});
|
||||
|
||||
return router;
|
||||
}
|
||||
|
||||
declare module "@tanstack/react-router" {
|
||||
interface Register {
|
||||
router: ReturnType<typeof getRouter>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import {
|
||||
createRootRoute,
|
||||
HeadContent,
|
||||
Scripts,
|
||||
} from "@tanstack/react-router";
|
||||
import "@fontsource/inter";
|
||||
import Layout from "@/components/Layout";
|
||||
import appCss from "../styles/globals.css?url";
|
||||
|
||||
const SITE_URL = "https://unom.io";
|
||||
|
||||
export const Route = createRootRoute({
|
||||
head: () => ({
|
||||
meta: [
|
||||
{ charSet: "utf-8" },
|
||||
{ name: "viewport", content: "width=device-width, initial-scale=1" },
|
||||
{ name: "description", content: "Kreative Webentwicklung aus Rottweil" },
|
||||
{ title: "unom - Kreative Webentwicklung" },
|
||||
{ property: "og:title", content: "unom - Kreative Webentwicklung" },
|
||||
{
|
||||
property: "og:description",
|
||||
content: "Kreative Webentwicklung aus Rottweil",
|
||||
},
|
||||
{ property: "og:url", content: SITE_URL },
|
||||
{ property: "og:type", content: "website" },
|
||||
],
|
||||
links: [
|
||||
{ rel: "stylesheet", href: appCss },
|
||||
{ rel: "icon", type: "image/svg+xml", href: "/favicon.svg" },
|
||||
],
|
||||
scripts: [
|
||||
{
|
||||
defer: true,
|
||||
"data-domain": "unom.io",
|
||||
src: "https://analytics.unom.io/js/plausible.js",
|
||||
},
|
||||
],
|
||||
}),
|
||||
shellComponent: RootDocument,
|
||||
});
|
||||
|
||||
function RootDocument({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html lang="de">
|
||||
<head>
|
||||
<HeadContent />
|
||||
</head>
|
||||
<body>
|
||||
<Layout>{children}</Layout>
|
||||
<Scripts />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import Landing from "@/sections/Landing";
|
||||
|
||||
export const Route = createFileRoute("/")({
|
||||
component: HomePage,
|
||||
head: () => ({
|
||||
meta: [{ title: "unom - Kreative Webentwicklung" }],
|
||||
}),
|
||||
});
|
||||
|
||||
function HomePage() {
|
||||
return <Landing />;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import LegalPage from "@/components/LegalPage";
|
||||
import content from "@/content/legal/imprint.md?raw";
|
||||
|
||||
export const Route = createFileRoute("/legal/imprint")({
|
||||
component: ImprintPage,
|
||||
head: () => ({
|
||||
meta: [{ title: "unom - Impressum" }],
|
||||
}),
|
||||
});
|
||||
|
||||
function ImprintPage() {
|
||||
return (
|
||||
<LegalPage>
|
||||
<ReactMarkdown>{content}</ReactMarkdown>
|
||||
</LegalPage>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import LegalPage from "@/components/LegalPage";
|
||||
import content from "@/content/legal/privacy.md?raw";
|
||||
|
||||
export const Route = createFileRoute("/legal/privacy")({
|
||||
component: PrivacyPage,
|
||||
head: () => ({
|
||||
meta: [{ title: "unom - Datenschutzerklärung" }],
|
||||
}),
|
||||
});
|
||||
|
||||
function PrivacyPage() {
|
||||
return (
|
||||
<LegalPage>
|
||||
<ReactMarkdown>{content}</ReactMarkdown>
|
||||
</LegalPage>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import LogoQuadBG from "@/components/LogoQuadBG";
|
||||
import bgDark from "@/assets/unom_Logo_5_Dark.webp";
|
||||
|
||||
export default function Landing() {
|
||||
return (
|
||||
<div className="w-full h-screen object-cover">
|
||||
<div className="w-full h-full flex items-center justify-center absolute">
|
||||
<div className="w-[200px]">
|
||||
<LogoQuadBG />
|
||||
</div>
|
||||
</div>
|
||||
<img
|
||||
className="h-full w-full object-cover"
|
||||
src={bgDark}
|
||||
width={3840}
|
||||
height={2160}
|
||||
alt="Ein 3D Rendering des unom Logos"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
import { Image } from "astro:assets";
|
||||
import bgDark from "./unom_Logo_5_Dark.webp";
|
||||
import LogoQuadBG from "@/components/Logo/LogoQuadBG.astro";
|
||||
---
|
||||
|
||||
<div class="w-full h-screen object-cover">
|
||||
<div class="w-full h-full flex items-center justify-center absolute">
|
||||
<div class="w-[200px]">
|
||||
<LogoQuadBG />
|
||||
</div>
|
||||
</div>
|
||||
<Image
|
||||
class="h-full object-cover"
|
||||
src={bgDark}
|
||||
width={3840}
|
||||
height={2160}
|
||||
alt="Ein 3D Rendering des unom Logos"
|
||||
/>
|
||||
</div>
|
||||
@@ -0,0 +1,7 @@
|
||||
import handler from "@tanstack/react-start/server-entry";
|
||||
|
||||
export default {
|
||||
fetch(req: Request): Promise<Response> {
|
||||
return handler.fetch(req);
|
||||
},
|
||||
};
|
||||
@@ -1,9 +1,9 @@
|
||||
@import "./timing-functions.css" layer(base);
|
||||
@import "./page-transition.css" layer(base);
|
||||
@import "tailwindcss";
|
||||
|
||||
:root {
|
||||
--main: oklch(100 0 0);
|
||||
--secondary: oklch(0.85 0 0);
|
||||
--brand: oklch(0.5609 0.2483 280.67);
|
||||
--neutral: oklch(0.155 0.0395 285.68);
|
||||
--neutral-accent: oklch(0.1 0.0395 285.68);
|
||||
@@ -13,7 +13,8 @@
|
||||
|
||||
--font-display: "Ubuntu", ui-sans-serif, system-ui, sans-serif;
|
||||
--font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
|
||||
--font-mono: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
||||
--font-mono:
|
||||
Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono, Courier New, monospace;
|
||||
|
||||
--radius: 0.625rem;
|
||||
@@ -51,19 +52,6 @@
|
||||
--container-max-section: 100%;
|
||||
}
|
||||
|
||||
/* @variant dark {
|
||||
:root {
|
||||
--main: oklch(1 0 0);
|
||||
--secondary: oklch(0.8 0 0);
|
||||
--primary: oklch(84.44% 0.2131 153.61);
|
||||
--neutral: oklch(16.36% 0.0088 172.9);
|
||||
--neutral-accent: oklch(19.73% 0.032 168.99);
|
||||
--highlight: oklch(66.39% 0.2398 3.2);
|
||||
--success: oklch(91.1% 0.1605 148.89);
|
||||
--error: oklch(67.36% 0.2339 0.92);
|
||||
}
|
||||
} */
|
||||
|
||||
@variant lg {
|
||||
:root {
|
||||
--container-max-section: 1000px;
|
||||
@@ -93,11 +81,7 @@
|
||||
}
|
||||
|
||||
h1 {
|
||||
@apply text-main font-display;
|
||||
}
|
||||
|
||||
h1 {
|
||||
@apply text-3xl font-bold;
|
||||
@apply text-main font-display text-3xl font-bold;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@@ -120,10 +104,6 @@
|
||||
@apply decoration-main text-main;
|
||||
}
|
||||
|
||||
[astro-icon] {
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
td {
|
||||
@apply px-3 py-1 border;
|
||||
}
|
||||
@@ -151,7 +131,33 @@
|
||||
|
||||
p,
|
||||
li {
|
||||
@apply max-w-[600px] text-base text-secondary;
|
||||
@apply max-w-[600px] text-base text-secondary;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.markdown {
|
||||
& h1 {
|
||||
@apply mb-4! mt-8!;
|
||||
}
|
||||
|
||||
& h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5 {
|
||||
@apply mb-4! mt-6!;
|
||||
}
|
||||
|
||||
& p {
|
||||
@apply mb-2! whitespace-break-spaces;
|
||||
}
|
||||
|
||||
& ul {
|
||||
@apply ml-4!;
|
||||
}
|
||||
|
||||
& li {
|
||||
@apply ml-4!;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
@reference "./global.css";
|
||||
|
||||
h1 {
|
||||
@apply mb-4! mt-8!;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5 {
|
||||
@apply mb-4! mt-6!;
|
||||
}
|
||||
|
||||
p {
|
||||
@apply mb-2! whitespace-break-spaces;
|
||||
}
|
||||
|
||||
ul {
|
||||
@apply ml-4!;
|
||||
}
|
||||
|
||||
li {
|
||||
@apply ml-4!;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
@keyframes pageEnter {
|
||||
from {
|
||||
transform: translateY(40px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
@keyframes pageLeave {
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user