diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000..aceb061 Binary files /dev/null and b/public/apple-touch-icon.png differ diff --git a/public/favicon.ico b/public/favicon.ico index 7f48a94..642ae0c 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/src/assets/me-bangkok.jpg b/src/assets/me-bangkok.jpg new file mode 100644 index 0000000..c3d6d60 Binary files /dev/null and b/src/assets/me-bangkok.jpg differ diff --git a/src/assets/me.avif b/src/assets/me.avif new file mode 100644 index 0000000..c12783e Binary files /dev/null and b/src/assets/me.avif differ diff --git a/src/components/AboutPage.astro b/src/components/AboutPage.astro new file mode 100644 index 0000000..065ad4b --- /dev/null +++ b/src/components/AboutPage.astro @@ -0,0 +1,558 @@ +--- +import { Image } from 'astro:assets'; +import meBangkok from '~/assets/me-bangkok.jpg'; +import JsonLd from '~/components/JsonLd.astro'; +import BaseLayout from '~/layouts/BaseLayout.astro'; +import type { Locale } from '~/consts'; + +interface Props { + locale: Locale; +} + +const { locale } = Astro.props; + +const identityLinks = [ + { + platform: 'Mastodon', + handle: '@altner@mastodon.social', + href: 'https://mastodon.social/@altner', + rel: 'me noopener noreferrer', + }, + { + platform: 'Instagram', + handle: '@adrian.altner', + href: 'https://www.instagram.com/adrian.altner/', + rel: 'me noopener noreferrer', + }, +]; + +const copy = { + de: { + title: 'Über mich', + description: 'Über Adrian Altner – Leidenschaft für das Web, Fotografie und Reisen.', + url: 'https://adrian-altner.de/ueber-mich', + country: 'Deutschland', + bio: [ + 'Begeistert vom Web seit 1997. Autodidakt aus Überzeugung – ich baue Dinge zum Vergnügen und bringe mir selbst bei, was mich gerade interessiert.', + 'Fotografie ist eines meiner Hauptthemen. Meistens auf Reisen oder bei Photowalks – Straßenszenen, Architektur und das Licht, das nie wartet.', + ], + contactHref: '/kontakt', + contactLabel: 'Kontakt →', + headings: { web: 'Im Netz', now: 'Gerade', site: 'Diese Seite' }, + webNote: { + before: 'Diese Links tragen ', + code: 'rel="me"', + between: ' zur ', + linkLabel: 'IndieWeb-Identitätsverifikation', + after: '. Meine kanonische Identität ist ', + canonical: 'adrian-altner.de', + end: '.', + }, + now: [ + 'Ich arbeite einen Stapel Fotos aus meiner letzten Reise nach Südostasien auf. In der Freizeit lerne ich mehr über Container-Orchestrierung und Selfhosting. Ich lese gerade zum zweiten Mal ', + 'The Pragmatic Programmer', + '.', + ], + nowNote: { + before: 'Inspiriert von ', + link: 'nownownow.com', + after: '. Zuletzt aktualisiert April 2026.', + }, + site: [ + { + before: 'Gebaut mit ', + link: { href: 'https://astro.build', label: 'Astro' }, + after: + ', betrieben auf einem selbst gehosteten VPS in Deutschland. Inhalte liegen als Markdown-Dateien vor, versioniert in Git. Kein Tracking, keine Cookies, keine JavaScript-Frameworks.', + }, + { + before: 'Diese Seite unterstützt ', + link: { href: 'https://indieweb.org/Webmention', label: 'Webmentions' }, + middle: ' – wer von der eigenen Website hierüber schreibt, bekomme ich möglicherweise mit. Neue Beiträge werden via ', + link2: { href: 'https://indieweb.org/POSSE', label: 'POSSE' }, + after: ' auf Mastodon syndiziert.', + }, + ], + photoAlt: 'Adrian Altner in Bangkok', + }, + en: { + title: 'About', + description: 'About Adrian Altner – passionate about the web, photography, and travel.', + url: 'https://adrian-altner.de/en/about', + country: 'Germany', + bio: [ + 'Fascinated by the web since 1997. Self-taught by conviction — I build things for fun and teach myself whatever happens to catch my interest.', + 'Photography is one of my main pursuits. Usually while travelling or on photowalks — street scenes, architecture, and the light that never waits.', + ], + contactHref: '/en/contact', + contactLabel: 'Contact →', + headings: { web: 'Elsewhere', now: 'Now', site: 'This site' }, + webNote: { + before: 'These links carry ', + code: 'rel="me"', + between: ' for ', + linkLabel: 'IndieWeb identity verification', + after: '. My canonical identity is ', + canonical: 'adrian-altner.de', + end: '.', + }, + now: [ + "Working through a stack of photos from my latest trip to Southeast Asia. In my spare time I'm learning more about container orchestration and self-hosting. Currently reading ", + 'The Pragmatic Programmer', + ' for the second time.', + ], + nowNote: { + before: 'Inspired by ', + link: 'nownownow.com', + after: '. Last updated April 2026.', + }, + site: [ + { + before: 'Built with ', + link: { href: 'https://astro.build', label: 'Astro' }, + after: + ', running on a self-hosted VPS in Germany. Content lives as Markdown files, versioned in Git. No tracking, no cookies, no JavaScript frameworks.', + }, + { + before: 'This site supports ', + link: { href: 'https://indieweb.org/Webmention', label: 'Webmentions' }, + middle: " – if you write about something here from your own site, there's a good chance I'll see it. New posts are syndicated to Mastodon via ", + link2: { href: 'https://indieweb.org/POSSE', label: 'POSSE' }, + after: '.', + }, + ], + photoAlt: 'Adrian Altner in Bangkok', + }, +} as const; + +const t = copy[locale]; + +const profilePageSchema = { + '@context': 'https://schema.org', + '@type': 'ProfilePage', + url: t.url, + ...(locale === 'en' ? { inLanguage: 'en' } : {}), + mainEntity: { + '@type': 'Person', + name: 'Adrian Altner', + url: 'https://adrian-altner.de', + sameAs: [ + 'https://mastodon.social/@altner', + 'https://www.instagram.com/adrian.altner/', + ], + }, +}; + +const techList = [ + 'Astro 6 · SSR · Node.js', + 'Microformats2 · Webmentions · POSSE', + 'Self-hosted · Germany · No CDN', + 'RSS feeds for all content types', +]; +--- + + + + +
+ +
+ + +
+
+ {t.photoAlt} +
+ +
+

Adrian Altner

+

+ Dresden, + SN, + {t.country} +

+ +
+ {t.bio.map((paragraph) =>

{paragraph}

)} +
+ + +
+
+
+
+ +
+
+
+

{t.headings.web}

+ +

+ {t.webNote.before}{t.webNote.code}{t.webNote.between} + {t.webNote.linkLabel}{t.webNote.after} + {t.webNote.canonical}{t.webNote.end} +

+
+ +
+

{t.headings.now}

+
+

{t.now[0]}{t.now[1]}{t.now[2]}

+

+ {t.nowNote.before}{t.nowNote.link}{t.nowNote.after} +

+
+
+ +
+

{t.headings.site}

+
+

+ {t.site[0].before} + {t.site[0].link.label} + {t.site[0].after} +

+

+ {t.site[1].before} + {t.site[1].link.label} + {t.site[1].middle} + {t.site[1].link2.label} + {t.site[1].after} +

+
+
    + {techList.map((item) =>
  • {item}
  • )} +
+
+
+
+
+ + diff --git a/src/components/JsonLd.astro b/src/components/JsonLd.astro new file mode 100644 index 0000000..cfbfdae --- /dev/null +++ b/src/components/JsonLd.astro @@ -0,0 +1,9 @@ +--- +interface Props { + schema: Record; +} + +const { schema } = Astro.props; +--- + +