add
Deploy Static Site / deploy (push) Successful in 10m9s

This commit is contained in:
Lars Nolden
2026-08-13 23:31:03 +02:00
parent 9582ea0198
commit 1eb73a957b
29 changed files with 77 additions and 39 deletions
@@ -1,48 +0,0 @@
name: Deploy Static Site
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install dependencies
run: npm ci
- name: Build static site
run: npm run build
- name: Setup SSH key
run: |
mkdir -p ~/.ssh
echo "${{ secrets.DEPLOY_SSH_KEY }}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
- name: Deploy static files to server
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
REMOTE_DIR: /home/deploy/projects/ge-bos/static
run: |
SSH="ssh -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new"
# Recreate the target dir so removed files don't linger (rsync --delete equivalent)
$SSH deploy@"$DEPLOY_HOST" "rm -rf '$REMOTE_DIR' && mkdir -p '$REMOTE_DIR'"
# Stream the build output over ssh and extract it on the server
tar -czf - -C out . | $SSH deploy@"$DEPLOY_HOST" "tar -xzf - -C '$REMOTE_DIR'"
- name: Run deployment script
run: |
ssh -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new \
deploy@${{ secrets.DEPLOY_HOST }} \
"cd /home/deploy/projects/ge-bos && ./deploy.sh"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

@@ -2,6 +2,7 @@ import * as React from "react"
import { cn } from "@/lib/utils"
import { IconBadge } from "@/components/gebos/icon-tile"
import { GlassNumber } from "@/components/gebos/site-assets"
export interface ProcessStep {
icon?: React.ReactNode
@@ -13,7 +14,7 @@ export interface ProcessStep {
/**
* Numbered process row ("So funktioniert GebOS", steps 15):
* numbered chips joined by a dotted teal line, device icon, title, copy.
* glass numerals joined by a dotted teal line, device icon, title, copy.
*/
function ProcessSteps({
steps,
@@ -32,16 +33,14 @@ function ProcessSteps({
>
<div
aria-hidden="true"
className="absolute inset-x-[10%] top-3.5 hidden border-t-2 border-dotted-brand lg:block"
className="absolute inset-x-[10%] top-[17px] hidden border-t-2 border-dotted-brand lg:block"
/>
{steps.map((step, i) => (
<li
key={i}
className="relative flex flex-col items-center gap-3 text-center"
>
<span className="z-10 flex size-7 items-center justify-center rounded-full bg-card text-xs font-bold text-primary shadow-pill ring-2 ring-brand-300">
{i + 1}
</span>
<GlassNumber n={i + 1} className="z-10 size-9" />
{step.media ?? (
<IconBadge variant="outline" shape="squircle" size="xl">
{step.icon}
@@ -73,14 +72,12 @@ function NumberedList({
<ol className={cn("relative flex flex-col gap-6", className)}>
<div
aria-hidden="true"
className="absolute top-2 bottom-2 left-3.5 border-l-2 border-dotted-brand"
className="absolute top-2 bottom-2 left-[17px] border-l-2 border-dotted-brand"
/>
{steps.map((step, i) => (
<li key={i} className="relative flex items-start gap-4">
<span className="z-10 flex size-7 shrink-0 items-center justify-center rounded-full bg-primary text-xs font-bold text-primary-foreground shadow-pill">
{i + 1}
</span>
<div className="pt-0.5">
<GlassNumber n={i + 1} className="z-10 size-9" />
<div className="flex min-h-9 flex-col justify-center">
<h3 className="text-sm font-bold text-navy">{step.title}</h3>
{step.description ? (
<p className="mt-0.5 text-sm leading-relaxed text-muted-foreground">
@@ -95,7 +92,7 @@ function NumberedList({
}
/**
* Step rail on a card (Selbstinstallation, steps 15): numbered rings threaded
* Step rail on a card (Selbstinstallation, steps 15): glass numerals threaded
* on a solid teal rail, hairline-divided columns beneath, each an asset render
* over title and copy. Each column draws its own half of the rail, so the run
* ends at the first and last ring whatever the step count. Rail and dividers
@@ -120,16 +117,14 @@ function StepRail({
<li key={i} className="relative flex flex-col items-center">
<span
aria-hidden="true"
/* rail sits on the ring's centre line (size-9 ring → 18px) */
/* rail sits on the badge's centre line (size-9 badge → 18px) */
className={cn(
"absolute top-[17px] hidden h-0.5 bg-brand-300 lg:block",
i === 0 ? "left-1/2" : "left-0",
i === steps.length - 1 ? "right-1/2" : "right-0"
)}
/>
<span className="z-10 flex size-9 items-center justify-center rounded-full bg-card text-sm font-bold text-navy ring-2 ring-brand-300">
{i + 1}
</span>
<GlassNumber n={i + 1} className="z-10 size-9" />
<div
className={cn(
"mt-5 flex w-full flex-1 flex-col items-center px-2 text-center",
@@ -447,4 +447,56 @@ function AssetRender({
)
}
export { AssetRender, icons, renders, vectors }
/** glossy glass numerals, index 0 = "1" */
const glassNumbers = [
renders.glassBadge1,
renders.glassBadge2,
renders.glassBadge3,
renders.glassBadge4,
renders.glassBadge5,
renders.glassBadge6,
]
/**
* Glass numeral for a step in an ordered list. Decorative on purpose: the
* enclosing <ol> already carries the ordinal, so the badge is not announced a
* second time. Only 16 exist as renders; a longer list falls back to the
* numeral on a teal disc rather than losing its number.
*/
function GlassNumber({
n,
className,
loading = "lazy",
}: {
n: number
/** sizes the badge pass a `size-*` utility */
className?: string
loading?: "lazy" | "eager"
}) {
const render = glassNumbers[n - 1]
if (!render) {
return (
<span
className={cn(
"flex shrink-0 items-center justify-center rounded-full bg-primary text-xs font-bold text-primary-foreground shadow-pill",
className
)}
>
{n}
</span>
)
}
return (
<AssetRender
render={render}
alt=""
className={cn("flex shrink-0 items-center justify-center", className)}
imgClassName="size-full"
loading={loading}
/>
)
}
export { AssetRender, GlassNumber, icons, renders, vectors }
+3 -13
View File
@@ -17,6 +17,7 @@ import { Container, Section, SectionHeading } from "@/components/gebos/section"
import { PageBreadcrumb } from "@/components/gebos/page-breadcrumb"
import {
AssetRender,
GlassNumber,
renders,
type RenderAsset,
} from "@/components/gebos/site-assets"
@@ -154,15 +155,9 @@ function readPreset(params: URLSearchParams): Preset {
}
}
/** glossy numerals for the three configurator steps */
/** the three configurator steps */
type Step = 1 | 2 | 3
const STEP_BADGES: Record<Step, RenderAsset> = {
1: renders.glassBadge1,
2: renders.glassBadge2,
3: renders.glassBadge3,
}
function StepCard({
step,
title,
@@ -175,12 +170,7 @@ function StepCard({
return (
<Card className="gap-0 p-6 sm:p-7">
<div className="flex items-center gap-3">
<AssetRender
render={STEP_BADGES[step]}
className="flex size-11 shrink-0 items-center justify-center"
imgClassName="w-11"
loading="eager"
/>
<GlassNumber n={step} className="size-11" loading="eager" />
<h3 className="text-lg font-extrabold tracking-tight text-navy">
<span className="sr-only">Schritt {step}: </span>
{title}
+1 -7
View File
@@ -494,13 +494,7 @@ export default function HomePage() {
<div>
<Card className="p-6 gap-0 sm:p-8">
<CardContent className="p-0">
<div className="flex items-center gap-4">
<img
src={vectors.euroOrb}
alt=""
className="size-14"
loading="lazy"
/>
<div>
<h3 className="text-base font-bold text-navy">
In fünf Schritten zum genauen Preis
</h3>