Compare commits
18 Commits
d62e71bafb
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 544d6c866c | |||
| 2d93109831 | |||
| ba9d4afaa6 | |||
| c10bfaa87c | |||
| fa5e52f185 | |||
| 5b031095fa | |||
| 501855ee87 | |||
| 8cf7b70fad | |||
| 3faa7c6ee0 | |||
| e94bd7eb29 | |||
| 4db8a7f103 | |||
| 42c5b4f345 | |||
| c409ecc888 | |||
| b85c765015 | |||
| c767765986 | |||
| b1a4697769 | |||
| 7caadb048a | |||
| 6a445bf1b4 |
@@ -0,0 +1,4 @@
|
|||||||
|
public/
|
||||||
|
resources/
|
||||||
|
.hugo_build.lock
|
||||||
|
.idea/
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
[submodule "themes/gallery"]
|
[submodule "themes/gallery"]
|
||||||
path = themes/gallery
|
path = themes/gallery
|
||||||
url = https://github.com/nicokaiser/hugo-theme-gallery.git
|
url = https://github.com/nicokaiser/hugo-theme-gallery.git
|
||||||
|
[submodule "themes/hugo-video"]
|
||||||
|
path = themes/hugo-video
|
||||||
|
url = https://github.com/martignoni/hugo-video.git
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# rsync -arzP --exclude-from='.rsyncignore' ./ netadmin@4koetter.com:~/plassonke.de
|
||||||
|
|
||||||
|
.git/
|
||||||
|
public/
|
||||||
|
resources/
|
||||||
|
.hugo_build.lock
|
||||||
|
.idea/
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
FROM hugomods/hugo:exts AS builder
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY archetypes/ archetypes/
|
||||||
|
COPY themes/ themes/
|
||||||
|
COPY layouts/ layouts/
|
||||||
|
COPY static/ static/
|
||||||
|
COPY assets/ assets/
|
||||||
|
COPY content/ content/
|
||||||
|
COPY hugo.toml .
|
||||||
|
|
||||||
|
RUN hugo --gc --minify
|
||||||
|
|
||||||
|
FROM alpine:3.20 AS video-posters
|
||||||
|
|
||||||
|
RUN apk add --no-cache python3 ffmpeg
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY --from=builder /src/public /src/public
|
||||||
|
COPY scripts/add-video-posters.py /add-video-posters.py
|
||||||
|
|
||||||
|
RUN python3 /add-video-posters.py /src/public
|
||||||
|
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache openssl
|
||||||
|
|
||||||
|
COPY --from=video-posters /src/public /usr/share/nginx/html
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
||||||
|
|
||||||
|
RUN chmod +x /docker-entrypoint.sh
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||||
@@ -1,250 +1,360 @@
|
|||||||
/* ── Warm colour palette ──────────────────────────────── */
|
/* ── Warm colour palette ──────────────────────────────── */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--surface-1-light: #faf8f4;
|
--surface-1-light: #faf8f4;
|
||||||
--surface-2-light: #f0ece4;
|
--surface-2-light: #f0ece4;
|
||||||
--text-1-light: #1a1614;
|
--text-1-light: #1a1614;
|
||||||
--text-2-light: #6b6258;
|
--text-2-light: #6b6258;
|
||||||
--border-light: #ccc4b8;
|
--border-light: #ccc4b8;
|
||||||
|
|
||||||
--surface-1-dark: #0d0b09;
|
--surface-1-dark: #0d0b09;
|
||||||
--surface-2-dark: #3d3631;
|
--surface-2-dark: #3d3631;
|
||||||
--text-1-dark: #f7f3ee;
|
--text-1-dark: #f7f3ee;
|
||||||
--text-2-dark: #9e948a;
|
--text-2-dark: #9e948a;
|
||||||
--border-dark: #5c5249;
|
--border-dark: #5c5249;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Hero ─────────────────────────────────────────────── */
|
/* ── Hero ─────────────────────────────────────────────── */
|
||||||
|
|
||||||
section.hero {
|
section.hero {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0 0 5rem;
|
margin: 0 0 5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-bg {
|
.hero-bg {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -30%;
|
top: -30%;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 160%;
|
height: 160%;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-bg::after {
|
.hero-bg::after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.35) 0%, transparent 40%);
|
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.35) 0%, transparent 40%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-fg {
|
.hero-fg {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Hero content ─────────────────────────────────────── */
|
/* ── Hero content ─────────────────────────────────────── */
|
||||||
|
|
||||||
.hero-content {
|
.hero-content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 2.5rem 3rem;
|
padding: 2.5rem 3rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background: rgba(10, 8, 6, 0.38);
|
background: rgba(10, 8, 6, 0.38);
|
||||||
backdrop-filter: blur(5px);
|
backdrop-filter: blur(5px);
|
||||||
-webkit-backdrop-filter: blur(8px);
|
-webkit-backdrop-filter: blur(8px);
|
||||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SVG vase title in the hero glass panel */
|
/* SVG vase title in the hero glass panel */
|
||||||
.hero-vase-title {
|
.hero-vase-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 2rem;
|
gap: 2rem;
|
||||||
margin-bottom: 1.25rem;
|
margin-bottom: 1.25rem;
|
||||||
animation: hero-fade-up 1s cubic-bezier(0.16, 1, 0.3, 1) both;
|
animation: hero-fade-up 1s cubic-bezier(0.16, 1, 0.3, 1) both;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (orientation: portrait) {
|
@media (orientation: portrait) {
|
||||||
.hero-vase-title {
|
.hero-vase-title {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-vase-title img {
|
.hero-vase-title img {
|
||||||
filter: brightness(0) invert(1);
|
filter: brightness(0) invert(1);
|
||||||
display: block;
|
display: block;
|
||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-vase-title .vase-name {
|
.hero-vase-title .vase-name {
|
||||||
height: clamp(3rem, 7.5vw, 5.5rem);
|
height: clamp(3rem, 7.5vw, 5.5rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-vase-title .vase-rings {
|
.hero-vase-title .vase-rings {
|
||||||
height: clamp(3rem, 7.5vw, 5.5rem);
|
height: clamp(3rem, 7.5vw, 5.5rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-content p {
|
.hero-content p {
|
||||||
color: rgba(250, 248, 244, 0.8);
|
color: rgba(250, 248, 244, 0.8);
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
letter-spacing: 0.12em;
|
letter-spacing: 0.12em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
text-wrap: balance;
|
text-wrap: balance;
|
||||||
animation: hero-fade-up 1s cubic-bezier(0.16, 1, 0.3, 1) 0.15s both;
|
animation: hero-fade-up 1s cubic-bezier(0.16, 1, 0.3, 1) 0.15s both;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Scroll arrow ─────────────────────────────────────── */
|
/* ── Scroll arrow ─────────────────────────────────────── */
|
||||||
|
|
||||||
.hero-scroll {
|
.hero-scroll {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding-top: 0.5rem;
|
padding-top: 0.5rem;
|
||||||
color: rgba(250, 250, 250, 0.6);
|
color: rgba(250, 250, 250, 0.6);
|
||||||
animation: hero-fade-in 0.6s ease 0.6s both;
|
animation: hero-fade-in 0.6s ease 0.6s both;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-scroll-icon {
|
.hero-scroll-icon {
|
||||||
display: block;
|
display: block;
|
||||||
animation: hero-bounce 2s ease-in-out 1.2s infinite;
|
animation: hero-bounce 2s ease-in-out 1.2s infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-scroll svg {
|
.hero-scroll svg {
|
||||||
width: 1.75rem;
|
width: 1.75rem;
|
||||||
height: 1.75rem;
|
height: 1.75rem;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Intro text section ───────────────────────────────── */
|
/* ── Intro text section ───────────────────────────────── */
|
||||||
|
|
||||||
.home-intro {
|
.home-intro {
|
||||||
max-width: 560px;
|
max-width: 560px;
|
||||||
margin: 4rem auto 5rem;
|
margin: 4rem auto 5rem;
|
||||||
padding: 0 1.5rem;
|
padding: 0 1.5rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-intro .prose p {
|
.home-intro .prose p {
|
||||||
color: var(--text-2);
|
color: var(--text-2);
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
line-height: 1.9;
|
line-height: 1.9;
|
||||||
margin-top: 0.9em;
|
margin-top: 0.9em;
|
||||||
margin-bottom: 0.9em;
|
margin-bottom: 0.9em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-intro .prose p:first-child {
|
.home-intro .prose p:first-child {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
color: var(--text-1);
|
color: var(--text-1);
|
||||||
font-size: 1.1875rem;
|
font-size: 1.1875rem;
|
||||||
line-height: 1.75;
|
line-height: 1.75;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Vase ornament ────────────────────────────────────── */
|
/* ── Vase ornament ────────────────────────────────────── */
|
||||||
|
|
||||||
.home-ornament {
|
.home-ornament {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin: 0 auto 3rem;
|
margin: 0 auto 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-ornament img {
|
.home-ornament img {
|
||||||
height: 240px;
|
height: 240px;
|
||||||
width: auto;
|
width: auto;
|
||||||
opacity: 0.38;
|
opacity: 0.38;
|
||||||
filter: sepia(1);
|
filter: sepia(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="dark"] .home-ornament img {
|
[data-theme="dark"] .home-ornament img {
|
||||||
filter: invert(1) sepia(0.4) brightness(0.85);
|
filter: invert(1) sepia(0.4) brightness(0.85);
|
||||||
opacity: 0.45;
|
opacity: 0.45;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Gallery page header title ────────────────────────── */
|
||||||
|
|
||||||
|
body > header {
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-title {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
letter-spacing: 0.15em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--text-1);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-right {
|
||||||
|
width: 3rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Album card hover ─────────────────────────────────── */
|
||||||
|
|
||||||
|
section.galleries .card figure {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.galleries .card img {
|
||||||
|
transition: transform 0.6s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.galleries .card img:hover {
|
||||||
|
transform: scale(1.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Album card text ──────────────────────────────────── */
|
||||||
|
|
||||||
|
.card > div > h2 {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 0.9375rem;
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card > div > p {
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
letter-spacing: 0.15em;
|
||||||
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Albums divider ───────────────────────────────────── */
|
/* ── Albums divider ───────────────────────────────────── */
|
||||||
|
|
||||||
.home-divider {
|
.home-divider {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 1.25rem;
|
gap: 1.25rem;
|
||||||
max-width: 1280px;
|
max-width: 1280px;
|
||||||
margin: 0 auto 2.5rem;
|
margin: 0 auto 2.5rem;
|
||||||
padding: 0 1.5rem;
|
padding: 0 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-divider::before,
|
.home-divider::before,
|
||||||
.home-divider::after {
|
.home-divider::after {
|
||||||
content: "";
|
content: "";
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
background: var(--border);
|
background: var(--border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-divider span {
|
.home-divider span {
|
||||||
font-size: 0.6875rem;
|
font-size: 0.6875rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
letter-spacing: 0.2em;
|
letter-spacing: 0.2em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--text-2);
|
color: var(--text-2);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Closing line ─────────────────────────────────────── */
|
/* ── Closing line ─────────────────────────────────────── */
|
||||||
|
|
||||||
.home-closing {
|
.home-closing {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin: 4rem auto 2rem;
|
margin: 4rem auto 2rem;
|
||||||
padding: 2.5rem 1.5rem 0;
|
padding: 2.5rem 1.5rem 0;
|
||||||
border-top: 1px solid var(--border);
|
border-top: 1px solid var(--border);
|
||||||
max-width: 1280px;
|
max-width: 1280px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-closing .vase-date {
|
.home-closing .vase-date {
|
||||||
height: 1.75rem;
|
height: 1.75rem;
|
||||||
width: auto;
|
width: auto;
|
||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
filter: sepia(1);
|
filter: sepia(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="dark"] .home-closing .vase-date {
|
[data-theme="dark"] .home-closing .vase-date {
|
||||||
filter: invert(1) sepia(0.3) brightness(0.9);
|
filter: invert(1) sepia(0.3) brightness(0.9);
|
||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Videos ────────────────────────────────── */
|
||||||
|
|
||||||
|
.prose {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(500px, 1fr));
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
padding: 0;
|
||||||
|
padding-top: 4rem;
|
||||||
|
gap: 0.5rem;
|
||||||
|
max-width: unset !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 500px) {
|
||||||
|
.prose {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose video {
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Gallery back link ────────────────────────────────── */
|
||||||
|
|
||||||
|
.gallery-back {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 3rem 1.5rem 2rem;
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
margin-top: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery-back-link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
letter-spacing: 0.15em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--text-2);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery-back-link:hover {
|
||||||
|
color: var(--text-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Keyframes ────────────────────────────────────────── */
|
/* ── Keyframes ────────────────────────────────────────── */
|
||||||
|
|
||||||
@keyframes hero-fade-up {
|
@keyframes hero-fade-up {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(1.5rem);
|
transform: translateY(1.5rem);
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes hero-fade-in {
|
@keyframes hero-fade-in {
|
||||||
from { opacity: 0; }
|
from {
|
||||||
to { opacity: 1; }
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes hero-bounce {
|
@keyframes hero-bounce {
|
||||||
0%, 100% { transform: translateY(0); }
|
0%, 100% {
|
||||||
50% { transform: translateY(7px); }
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(7px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
// Background at 55%, text at 80% — both slower than normal, image slowest
|
// Background at 55%, text at 80% — both slower than normal, image slowest
|
||||||
if (heroBg) heroBg.style.transform = 'translateY(' + (s * 0.25) + 'px)';
|
if (heroBg) heroBg.style.transform = 'translateY(' + (s * 0.25) + 'px)';
|
||||||
if (heroFg) heroFg.style.transform = 'translateY(' + (s * 0.15) + 'px)';
|
if (heroFg) heroFg.style.transform = 'translateY(' + (s * 0.05) + 'px)';
|
||||||
|
|
||||||
// Scroll arrow fades out over the first 30% of hero height
|
// Scroll arrow fades out over the first 30% of hero height
|
||||||
if (heroScroll) {
|
if (heroScroll) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"paths": {
|
"paths": {
|
||||||
"*": [
|
"*": [
|
||||||
"*",
|
"*",
|
||||||
"../themes/gallery/assets/*"
|
"..\\themes\\gallery\\assets\\*"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,23 @@
|
|||||||
---
|
---
|
||||||
title: "Herzlich Willkommen"
|
title: "Lina & Marlin"
|
||||||
params:
|
params:
|
||||||
tagline: "Schön, dass ihr da seid."
|
tagline: "Alles Liebe zu eurer Hochzeit"
|
||||||
albums_label: "Alben"
|
albums_label: "Alben"
|
||||||
closing: "20. Juni 2026"
|
closing: "20. Juni 2026"
|
||||||
---
|
---
|
||||||
|
|
||||||
Hier findet ihr die Erinnerungen an unseren besonderen Tag — festgehalten in Bildern, die für immer bleiben.
|
Liebe Lina, lieber Marlin,
|
||||||
|
|
||||||
Schreibt euch diesen Moment ins Gedächtnis: die Musik, das Lachen, die Umarmungen. Wir freuen uns, ihn mit euch geteilt zu haben.
|
vielleicht habt ihr euren Fehler bereits gefunden?
|
||||||
|
Die Domain `z.app` als Geschenk zu verbieten ist nicht genug, wenn `plassonke.de` noch verfügbar ist.
|
||||||
|
Deshalb bekommt ihr diese jetzt als Teil eures Geschenkes.
|
||||||
|
|
||||||
|
Da ihr dieses Geschenk erst im Nachhinein bekommt, können wir uns Linas große Freude über die erste eigene Domain wohl nur vorstellen.
|
||||||
|
Da es leider kein `z.app` für Marlin gibt, kannst du diese Freude aber teilen.
|
||||||
|
Wenn ihr schon keinen Doppelnamen nehmt, kann man stattdessen vielleicht `zapp.plassonke.de` nutzen.
|
||||||
|
Dann ist auch für Marlin etwas dabei.
|
||||||
|
|
||||||
|
Falls die Freude über die Domain irgendwann doch etwas abebbt,
|
||||||
|
könnt ihr euch hoffentlich mit den Bildern an einen tollen Tag zurückerinnern.
|
||||||
|
|
||||||
|
Wir wünschen euch alles Gute für eure gemeinsame Zukunft!
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 458 KiB |
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Cats"
|
|
||||||
date: 2026-06-18
|
|
||||||
---
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
title: "Empfang"
|
||||||
|
date: 2026-06-10
|
||||||
|
weight: 2
|
||||||
|
resources:
|
||||||
|
- src: IMG_1574.png
|
||||||
|
params:
|
||||||
|
cover: true
|
||||||
|
---
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
title: "Feier"
|
||||||
|
date: 2026-06-10
|
||||||
|
weight: 4
|
||||||
|
resources:
|
||||||
|
- src: IMG_1625.png
|
||||||
|
params:
|
||||||
|
cover: true
|
||||||
|
---
|
||||||
|
Before Width: | Height: | Size: 154 KiB |
|
After Width: | Height: | Size: 74 MiB |
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
title: "Standesamt"
|
||||||
|
date: 2026-02-14
|
||||||
|
weight: 1
|
||||||
|
resources:
|
||||||
|
- src: IMG_1570.png
|
||||||
|
params:
|
||||||
|
cover: true
|
||||||
|
---
|
||||||
|
|
||||||
|
{{< video src="test.mp4" >}}
|
||||||
|
|
||||||
|
{{< video src="test2.mp4" >}}
|
||||||
|
Before Width: | Height: | Size: 56 KiB |
@@ -1,4 +1,9 @@
|
|||||||
---
|
---
|
||||||
title: "Zeremonie"
|
title: "Zeremonie"
|
||||||
date: 2026-06-18
|
date: 2026-06-10
|
||||||
|
weight: 3
|
||||||
|
resources:
|
||||||
|
- src: IMG_1474.png
|
||||||
|
params:
|
||||||
|
cover: true
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
services:
|
||||||
|
web:
|
||||||
|
build: .
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
- reverse-proxy_shared
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
AUTH_USER: hochzeit
|
||||||
|
AUTH_PASS: changeme
|
||||||
|
|
||||||
|
networks:
|
||||||
|
reverse-proxy_shared:
|
||||||
|
external: true
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
echo "${AUTH_USER}:$(openssl passwd -apr1 "${AUTH_PASS}")" > /etc/nginx/.htpasswd
|
||||||
|
exec nginx -g "daemon off;"
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
baseURL = "https://plassonke.de/"
|
baseURL = "https://plassonke.de/"
|
||||||
title = "Hochzeit"
|
title = "Hochzeit"
|
||||||
theme = "gallery"
|
theme = ["hugo-video", "gallery"]
|
||||||
defaultContentLanguage = "de"
|
defaultContentLanguage = "de"
|
||||||
disableKinds = ["taxonomy"]
|
disableKinds = ["taxonomy"]
|
||||||
enableRobotsTXT = true
|
enableRobotsTXT = true
|
||||||
@@ -10,7 +10,8 @@ timeout = "120s"
|
|||||||
|
|
||||||
[params]
|
[params]
|
||||||
defaultTheme = "light"
|
defaultTheme = "light"
|
||||||
description = "Hochzeit"
|
description = "Fotos von Linas und Marlins Hochzeit"
|
||||||
|
images = ["content/hero.png"]
|
||||||
title = "Hochzeit"
|
title = "Hochzeit"
|
||||||
[params.author]
|
[params.author]
|
||||||
name = "Yannis Vierkoetter"
|
name = "Yannis Vierkoetter"
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{{ define "main" }}
|
||||||
|
<section class="galleries">
|
||||||
|
{{ range where .Pages "Params.private" "ne" true }}
|
||||||
|
{{ partial "album-card.html" . }}
|
||||||
|
{{ end }}
|
||||||
|
</section>
|
||||||
|
{{ end }}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{{ define "main" }}
|
||||||
|
{{ partial "gallery.html" . }}
|
||||||
|
{{ partial "related.html" . }}
|
||||||
|
{{ with .Content }}
|
||||||
|
<section class="prose">
|
||||||
|
{{ . }}
|
||||||
|
</section>
|
||||||
|
{{ end }}
|
||||||
|
<div class="gallery-back">
|
||||||
|
<a href="{{ .Site.Home.RelPermalink }}" class="gallery-back-link">
|
||||||
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||||
|
<path d="M19 12H5M5 12l7 7M5 12l7-7"/>
|
||||||
|
</svg>
|
||||||
|
Zurück zur Startseite
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
<style>
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Cormorant Garant';
|
|
||||||
src: url('/fonts/CormorantGarant-Light.woff2') format('woff2');
|
|
||||||
font-weight: 300;
|
|
||||||
font-style: normal;
|
|
||||||
font-display: swap;
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Cormorant Garant';
|
|
||||||
src: url('/fonts/CormorantGarant-LightItalic.woff2') format('woff2');
|
|
||||||
font-weight: 300;
|
|
||||||
font-style: italic;
|
|
||||||
font-display: swap;
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Cormorant Garant';
|
|
||||||
src: url('/fonts/CormorantGarant-Regular.woff2') format('woff2');
|
|
||||||
font-weight: 400;
|
|
||||||
font-style: normal;
|
|
||||||
font-display: swap;
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Cormorant Garant';
|
|
||||||
src: url('/fonts/CormorantGarant-Italic.woff2') format('woff2');
|
|
||||||
font-weight: 400;
|
|
||||||
font-style: italic;
|
|
||||||
font-display: swap;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -7,24 +7,25 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
<a class="btn" href="{{ .Site.Home.RelPermalink }}">
|
<a class="btn btn-square" href="{{ .Site.Home.RelPermalink }}" title="{{ .Site.Title }}">
|
||||||
{{ .Site.Title }}
|
<svg width="24" height="24" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
||||||
|
<path clip-rule="evenodd" fill-rule="evenodd" d="M11.03 3.97a.75.75 0 0 1 0 1.06l-6.22 6.22H21a.75.75 0 0 1 0 1.5H4.81l6.22 6.22a.75.75 0 1 1-1.06 1.06l-7.5-7.5a.75.75 0 0 1 0-1.06l7.5-7.5a.75.75 0 0 1 1.06 0Z"></path>
|
||||||
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ if site.Menus.main }}
|
<h1 class="header-title">{{ .Title }}</h1>
|
||||||
<ul>
|
<div class="header-right">
|
||||||
<li>
|
{{ if site.Menus.main }}
|
||||||
<button class="btn btn-square" id="menu-toggle" aria-expanded="false" type="button" title="{{ T "menu" }}">
|
<button class="btn btn-square" id="menu-toggle" aria-expanded="false" type="button" title="{{ T "menu" }}">
|
||||||
<svg class="icon-menu" width="24" height="24" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
<svg class="icon-menu" width="24" height="24" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
||||||
<path clip-rule="evenodd" fill-rule="evenodd" d="M3 6.75A.75.75 0 0 1 3.75 6h16.5a.75.75 0 0 1 0 1.5H3.75A.75.75 0 0 1 3 6.75ZM3 12a.75.75 0 0 1 .75-.75h16.5a.75.75 0 0 1 0 1.5H3.75A.75.75 0 0 1 3 12Zm0 5.25a.75.75 0 0 1 .75-.75h16.5a.75.75 0 0 1 0 1.5H3.75a.75.75 0 0 1-.75-.75Z"></path>
|
<path clip-rule="evenodd" fill-rule="evenodd" d="M3 6.75A.75.75 0 0 1 3.75 6h16.5a.75.75 0 0 1 0 1.5H3.75A.75.75 0 0 1 3 6.75ZM3 12a.75.75 0 0 1 .75-.75h16.5a.75.75 0 0 1 0 1.5H3.75A.75.75 0 0 1 3 12Zm0 5.25a.75.75 0 0 1 .75-.75h16.5a.75.75 0 0 1 0 1.5H3.75a.75.75 0 0 1-.75-.75Z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
<svg class="icon-close hidden" width="24" height="24" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
<svg class="icon-close hidden" width="24" height="24" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
||||||
<path clip-rule="evenodd" fill-rule="evenodd" d="M5.47 5.47a.75.75 0 0 1 1.06 0L12 10.94l5.47-5.47a.75.75 0 1 1 1.06 1.06L13.06 12l5.47 5.47a.75.75 0 1 1-1.06 1.06L12 13.06l-5.47 5.47a.75.75 0 0 1-1.06-1.06L10.94 12 5.47 6.53a.75.75 0 0 1 0-1.06Z"></path>
|
<path clip-rule="evenodd" fill-rule="evenodd" d="M5.47 5.47a.75.75 0 0 1 1.06 0L12 10.94l5.47-5.47a.75.75 0 1 1 1.06 1.06L13.06 12l5.47 5.47a.75.75 0 1 1-1.06 1.06L12 13.06l-5.47 5.47a.75.75 0 0 1-1.06-1.06L10.94 12 5.47 6.53a.75.75 0 0 1 0-1.06Z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
{{ end }}
|
||||||
</ul>
|
</div>
|
||||||
{{ end }}
|
|
||||||
</header>
|
</header>
|
||||||
{{ partial "menu.html" . }}
|
{{ partial "menu.html" . }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
auth_basic "Hochzeit";
|
||||||
|
auth_basic_user_file /etc/nginx/.htpasswd;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
from urllib.parse import unquote
|
||||||
|
|
||||||
|
|
||||||
|
VIDEO_TAG_RE = re.compile(
|
||||||
|
r"<video(?P<attrs>[^>]*)>(?P<body>.*?)</video>",
|
||||||
|
re.IGNORECASE | re.DOTALL,
|
||||||
|
)
|
||||||
|
|
||||||
|
SOURCE_RE = re.compile(
|
||||||
|
r'<source[^>]+src=["\'](?P<src>[^"\']+)["\'][^>]*>',
|
||||||
|
re.IGNORECASE,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_src(video_attrs: str, video_body: str) -> str | None:
|
||||||
|
"""Extract video path from either <video src=""> or nested <source src="">."""
|
||||||
|
|
||||||
|
video_src = re.search(r'src=["\']([^"\']+)["\']', video_attrs, re.IGNORECASE)
|
||||||
|
if video_src:
|
||||||
|
return video_src.group(1)
|
||||||
|
|
||||||
|
source_src = SOURCE_RE.search(video_body)
|
||||||
|
if source_src:
|
||||||
|
return source_src.group("src")
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def make_poster(video_path: Path, poster_path: Path) -> None:
|
||||||
|
"""Extract a poster frame from a video using ffmpeg."""
|
||||||
|
|
||||||
|
poster_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
"ffmpeg",
|
||||||
|
"-y",
|
||||||
|
"-ss",
|
||||||
|
"00:00:01",
|
||||||
|
"-i",
|
||||||
|
str(video_path),
|
||||||
|
"-frames:v",
|
||||||
|
"1",
|
||||||
|
"-q:v",
|
||||||
|
"3",
|
||||||
|
str(poster_path),
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
stdout=subprocess.DEVNULL,
|
||||||
|
stderr=subprocess.DEVNULL,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def process_file(html_file: Path, root: Path) -> None:
|
||||||
|
"""Replace video preload mode and add poster attributes."""
|
||||||
|
|
||||||
|
content = html_file.read_text(encoding="utf-8")
|
||||||
|
changed = False
|
||||||
|
|
||||||
|
def replace_video(match: re.Match[str]) -> str:
|
||||||
|
nonlocal changed
|
||||||
|
|
||||||
|
attrs = match.group("attrs")
|
||||||
|
body = match.group("body")
|
||||||
|
|
||||||
|
if 'preload="auto"' not in attrs and "preload='auto'" not in attrs:
|
||||||
|
return match.group(0)
|
||||||
|
|
||||||
|
src = extract_src(attrs, body)
|
||||||
|
if not src:
|
||||||
|
return match.group(0)
|
||||||
|
|
||||||
|
src_clean = unquote(src.split("#")[0].split("?")[0])
|
||||||
|
|
||||||
|
if src_clean.startswith(("http://", "https://", "//")):
|
||||||
|
return match.group(0)
|
||||||
|
|
||||||
|
video_path = (html_file.parent / src_clean).resolve()
|
||||||
|
|
||||||
|
try:
|
||||||
|
video_path.relative_to(root.resolve())
|
||||||
|
except ValueError:
|
||||||
|
return match.group(0)
|
||||||
|
|
||||||
|
if not video_path.exists():
|
||||||
|
print(f"Missing video: {video_path}")
|
||||||
|
return match.group(0)
|
||||||
|
|
||||||
|
poster_path = video_path.with_suffix(".jpg")
|
||||||
|
poster_src = src_clean.rsplit(".", 1)[0] + ".jpg"
|
||||||
|
|
||||||
|
if not poster_path.exists():
|
||||||
|
make_poster(video_path, poster_path)
|
||||||
|
|
||||||
|
attrs_new = attrs
|
||||||
|
attrs_new = attrs_new.replace('preload="auto"', 'preload="none"')
|
||||||
|
attrs_new = attrs_new.replace("preload='auto'", 'preload="none"')
|
||||||
|
|
||||||
|
if "poster=" not in attrs_new.lower():
|
||||||
|
attrs_new += f' poster="{poster_src}"'
|
||||||
|
|
||||||
|
changed = True
|
||||||
|
return f"<video{attrs_new}>{body}</video>"
|
||||||
|
|
||||||
|
new_content = VIDEO_TAG_RE.sub(replace_video, content)
|
||||||
|
|
||||||
|
if changed:
|
||||||
|
html_file.write_text(new_content, encoding="utf-8")
|
||||||
|
print(f"Updated: {html_file}")
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Process all HTML files below the given root directory."""
|
||||||
|
|
||||||
|
root = Path(sys.argv[1]).resolve()
|
||||||
|
|
||||||
|
for html_file in root.rglob("*.html"):
|
||||||
|
process_file(html_file, root)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
After Width: | Height: | Size: 7.3 KiB |
@@ -0,0 +1,35 @@
|
|||||||
|
User-agent: *
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
User-agent: GPTBot
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
User-agent: Google-Extended
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
User-agent: ClaudeBot
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
User-agent: anthropic-ai
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
User-agent: CCBot
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
User-agent: Bytespider
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
User-agent: PerplexityBot
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
User-agent: FacebookBot
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
User-agent: Applebot-Extended
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
User-agent: cohere-ai
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
User-agent: Amazonbot
|
||||||
|
Disallow: /
|
||||||