migrate to Hugo + PaperMod

This commit is contained in:
nik
2025-09-23 16:51:19 +03:00
parent adcb77aa47
commit 0b50d19e21
8 changed files with 49 additions and 375 deletions

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
public/
resources/
.hugo_build.lock
node_modules/
.DS_Store

17
Jenkinsfile vendored
View File

@@ -1,19 +1,28 @@
pipeline { pipeline {
agent any agent any
options { timestamps(); disableConcurrentBuilds() }
environment { environment {
DEPLOY_HOST = 'web@23.26.156.61' DEPLOY_HOST = 'web@23.26.156.61'
DEPLOY_PATH = '/srv/www/masha-site' DEPLOY_PATH = '/srv/www/masha-site'
SSH_CRED_ID = 'web-ssh' SSH_CRED_ID = 'web-ssh'
} }
triggers {
githubPush()
}
stages { stages {
stage('Checkout') { stage('Checkout') { steps { checkout scm } }
steps { checkout scm } stage('Build site') {
steps {
sh '''
if [ ! -f go.mod ]; then docker run --rm -u $(id -u):$(id -g) -v "$PWD":/src -w /src klakegg/hugo:ext-alpine hugo mod init site; fi
docker run --rm -u $(id -u):$(id -g) -v "$PWD":/src -w /src klakegg/hugo:ext-alpine hugo mod get -u github.com/adityatelange/hugo-PaperMod
docker run --rm -u $(id -u):$(id -g) -v "$PWD":/src -w /src klakegg/hugo:ext-alpine hugo --minify
'''
}
} }
stage('Deploy') { stage('Deploy') {
steps { steps {
sshagent(credentials: [env.SSH_CRED_ID]) { sshagent(credentials: [env.SSH_CRED_ID]) {
sh 'bash deploy/deploy.sh "$DEPLOY_HOST" "$DEPLOY_PATH"' sh 'bash deploy/deploy.sh $DEPLOY_HOST $DEPLOY_PATH'
} }
} }
} }

21
config.yaml Normal file
View File

@@ -0,0 +1,21 @@
baseURL: https://маша-дергачева.рф/
title: Маша Дергачева
theme: PaperMod
languageCode: ru
defaultContentLanguage: ru
paginate: 10
params:
defaultTheme: light
disableThemeToggle: true
homeInfoParams:
Title: Привет, я Маша
Content: Делаю простые вещи и веду заметки.
menu:
main:
- name: Attendance
url: /attendance/
weight: 10
- name: Submit
url: /attendance/submit/
weight: 11

5
content/_index.md Normal file
View File

@@ -0,0 +1,5 @@
---
title: Главная
---
Добро пожаловать.

View File

@@ -2,8 +2,8 @@
set -euo pipefail set -euo pipefail
HOST="${1:-}" HOST="${1:-}"
DEST="${2:-}" DEST="${2:-}"
TMP="$DEST.new" BUILD_DIR="public"
ssh -o StrictHostKeyChecking=no "$HOST" "rm -rf '$TMP' && mkdir -p '$TMP'" ssh -o StrictHostKeyChecking=no "$HOST" "mkdir -p '$DEST/.release_tmp'"
tar -cz --exclude .git --exclude Jenkinsfile --exclude deploy -C . . | ssh -o StrictHostKeyChecking=no "$HOST" "tar -xz -C '$TMP'" tar -cz -C "$BUILD_DIR" . | ssh -o StrictHostKeyChecking=no "$HOST" "tar -xz -C '$DEST/.release_tmp'"
ssh -o StrictHostKeyChecking=no "$HOST" "mkdir -p '$DEST'; rm -rf '${DEST}.prev'; mv '$DEST' '${DEST}.prev' 2>/dev/null || true; mv '$TMP' '$DEST'" ssh -o StrictHostKeyChecking=no "$HOST" "bash -lc 'shopt -s dotglob nullglob; rm -rf \"$DEST\"/* \"$DEST\"/.[!.]* \"$DEST\"/..?*; mv \"$DEST/.release_tmp\"/* \"$DEST\"/; rmdir \"$DEST/.release_tmp\"'"

View File

@@ -1,367 +0,0 @@
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Маша Дергачева</title>
<meta name="description" content="Личная страница Маши Дергачевой." />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap"
rel="stylesheet"
/>
<style>
:root {
--bg: 252 252 253;
--fg: 15 18 25;
--muted: 103 106 115;
--line: 228 231 235;
--accent: 39 108 234;
--card: 255 255 255;
}
:root.dark {
--bg: 12 14 18;
--fg: 235 238 245;
--muted: 160 166 178;
--line: 45 49 58;
--accent: 101 146 255;
--card: 18 21 27;
}
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
}
body {
margin: 0;
font-family:
Inter,
system-ui,
-apple-system,
Segoe UI,
Roboto,
Ubuntu,
Cantarell,
Noto Sans,
sans-serif;
background: rgb(var(--bg));
color: rgb(var(--fg));
-webkit-font-smoothing: antialiased;
letter-spacing: 0.1px;
}
.container {
width: 100%;
max-width: 920px;
margin: 0 auto;
padding: 0 20px;
}
.header {
position: sticky;
top: 0;
background: rgba(var(--bg), 0.8);
backdrop-filter: blur(8px);
border-bottom: 1px solid rgba(var(--line), 0.8);
z-index: 10;
}
.header-inner {
height: 64px;
display: flex;
align-items: center;
justify-content: space-between;
}
.brand {
font-weight: 800;
letter-spacing: -0.2px;
}
.nav {
display: flex;
gap: 18px;
}
.nav a {
color: rgb(var(--fg));
text-decoration: none;
font-weight: 600;
opacity: 0.8;
}
.nav a:hover {
opacity: 1;
}
.hero {
padding: 80px 0 48px;
}
.h1 {
font-size: 56px;
line-height: 1.03;
margin: 0 0 10px;
letter-spacing: -0.6px;
}
.subtitle {
font-size: 18px;
line-height: 1.7;
color: rgb(var(--muted));
max-width: 640px;
margin: 0;
}
.actions {
display: flex;
gap: 12px;
margin-top: 22px;
flex-wrap: wrap;
}
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 12px 16px;
border-radius: 12px;
font-weight: 700;
text-decoration: none;
}
.btn-solid {
background: rgb(var(--fg));
color: #fff;
}
.btn-ghost {
border: 1px solid rgb(var(--line));
color: rgb(var(--fg));
background: transparent;
}
.section {
padding: 40px 0;
}
.section h2 {
margin: 0 0 12px;
font-size: 22px;
}
.grid {
display: grid;
gap: 14px;
}
.card {
background: rgb(var(--card));
border: 1px solid rgb(var(--line));
border-radius: 14px;
padding: 16px;
}
.card h3 {
margin: 0 0 6px;
font-size: 16px;
}
.card p {
margin: 0;
color: rgb(var(--muted));
line-height: 1.6;
}
.list {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.badge {
padding: 6px 10px;
border-radius: 999px;
background: rgba(var(--fg), 0.04);
border: 1px solid rgb(var(--line));
font-size: 12px;
color: rgb(var(--muted));
font-weight: 600;
}
.footer {
padding: 40px 0;
border-top: 1px solid rgb(var(--line));
color: rgb(var(--muted));
font-size: 14px;
}
.theme {
width: 36px;
height: 36px;
border: 1px solid rgb(var(--line));
border-radius: 10px;
background: transparent;
display: grid;
place-items: center;
}
.icon {
width: 18px;
height: 18px;
}
@media (min-width: 680px) {
.grid.cols-2 {
grid-template-columns: 1fr 1fr;
}
.h1 {
font-size: 64px;
}
.hero {
padding: 96px 0 56px;
}
}
</style>
</head>
<body>
<header class="header">
<div class="container header-inner">
<a class="brand" href="#top">Маша Дергачева</a>
<nav class="nav">
<a href="#about">О себе</a>
<a href="#work">Проекты</a>
<a href="#notes">Заметки</a>
<a href="#contact">Контакты</a>
</nav>
</div>
</header>
<main id="top">
<section class="hero">
<div class="container">
<h1 class="h1">Привет, я Маша</h1>
<p class="subtitle">
Делаю аккуратные вещи и записываю мысли. Люблю простые интерфейсы,
живые тексты и порядок.
</p>
<div class="actions">
<a class="btn btn-solid" href="#work">Смотреть проекты</a>
<a class="btn btn-ghost" href="#contact">Написать</a>
</div>
</div>
</section>
<section class="section" id="about">
<div class="container grid cols-2">
<div>
<h2>О себе</h2>
<p class="subtitle">
Несколько предложений: чем занимаюсь сейчас, что интересно и чему
учусь. Коротко и по делу.
</p>
<div class="list" style="margin-top: 12px">
<span class="badge">учёба</span>
<span class="badge">тексты</span>
<span class="badge">маленькие проекты</span>
</div>
</div>
<div class="grid" style="gap: 12px">
<div class="card">
<h3>Фокус</h3>
<p>Мини‑исследования, заметки по книгам и интерфейсам.</p>
</div>
<div class="card">
<h3>Сейчас</h3>
<p>Пишу маленькие штуки, читаю, поддерживаю личный сайт.</p>
</div>
</div>
</div>
</section>
<section class="section" id="work">
<div class="container">
<h2>Проекты</h2>
<div class="grid cols-2">
<a class="card" href="#">
<h3>Мини‑сайт</h3>
<p>Лёгкая страница без сборок. Чистая типографика.</p>
</a>
<a class="card" href="#">
<h3>Заметки</h3>
<p>Подборки мыслей и коротких эссе.</p>
</a>
<a class="card" href="#">
<h3>Фото</h3>
<p>Небольшие серии без лишних эффектов.</p>
</a>
<a class="card" href="#">
<h3>Эксперимент</h3>
<p>Игрушки и микро‑интеракции.</p>
</a>
</div>
</div>
</section>
<section class="section" id="notes">
<div class="container">
<h2>Заметки</h2>
<div class="grid">
<a class="card" href="#"
><h3>Как вести личный сайт</h3>
<p>Очень краткий чек‑лист без лишнего.</p></a
>
<a class="card" href="#"
><h3>Минимализм в интерфейсах</h3>
<p>Что убрать, чтобы стало лучше.</p></a
>
</div>
</div>
</section>
<section class="section" id="contact">
<div class="container">
<h2>Контакты</h2>
<div class="grid" style="gap: 10px; max-width: 620px">
<div
class="card"
style="
display: flex;
gap: 10px;
align-items: center;
justify-content: space-between;
"
>
<input
id="email"
value="hi@masha-dergacheva.рф"
readonly
style="
flex: 1;
border: 1px solid rgb(var(--line));
background: transparent;
border-radius: 10px;
padding: 12px 14px;
color: rgb(var(--fg));
outline: none;
"
/>
<button class="btn btn-ghost" id="copy">Скопировать</button>
</div>
<div class="card" style="display: flex; gap: 10px; flex-wrap: wrap">
<a
class="btn btn-solid"
href="https://t.me/username"
target="_blank"
rel="noopener noreferrer"
>Телеграм</a
>
<a class="btn btn-ghost" href="mailto:hi@masha-дергачева.рф"
>Почта</a
>
</div>
</div>
</div>
</section>
</main>
<footer class="footer">
<div
class="container"
style="
display: flex;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
"
>
<span>© <span id="year"></span> маша‑дергачева.рф</span>
<span>Минимализм без сборок</span>
</div>
</footer>
<script>
document.getElementById("year").textContent = new Date().getFullYear();
const copy = document.getElementById("copy");
copy.addEventListener("click", async () => {
const v = document.getElementById("email").value;
try {
await navigator.clipboard.writeText(v);
copy.textContent = "Скопировано";
setTimeout(() => (copy.textContent = "Скопировать"), 1500);
} catch (e) {
copy.textContent = "Ошибка";
}
});
</script>
</body>
</html>