feat(notebook): rebrand Hnote, favicon X, and hand title fonts
notebook-ci / build-push-deploy (push) Successful in 47s

- Brand: Hnote / hang's note / title suffix X.H.
- Tab icon: circular green X logo
- Decorative titles use Nanum Pen + Zhi Mang Xing
- Drop sticky sidebars; keep fluid layout
This commit is contained in:
secret-deus
2026-07-16 22:46:35 +08:00
parent cfc9c82bfd
commit c11929dccb
15 changed files with 113 additions and 40 deletions
+20
View File
@@ -52,5 +52,25 @@ export default defineConfig({
],
},
},
/* 特殊标题:拉丁钢笔手写(比 Caveat 更干净好看) */
{
provider: fontProviders.google(),
name: 'Nanum Pen Script',
cssVariable: '--font-hand-latin',
weights: [400],
styles: ['normal'],
subsets: ['latin'],
fallbacks: ['"Segoe Print"', 'cursive'],
},
/* 特殊标题:中文行书手写(志莽行,飘逸美观) */
{
provider: fontProviders.google(),
name: 'Zhi Mang Xing',
cssVariable: '--font-hand-zh',
weights: [400],
styles: ['normal'],
subsets: ['chinese-simplified', 'latin'],
fallbacks: ['"KaiTi"', '"STKaiti"', 'cursive'],
},
],
});
Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

+15 -7
View File
@@ -3,7 +3,7 @@ import '../styles/global.css';
import '../styles/board.css';
import type { ImageMetadata } from 'astro';
import { Font } from 'astro:assets';
import { SITE_TITLE } from '../consts';
import { SITE_TITLE, SITE_TITLE_SUFFIX } from '../consts';
interface Props {
title: string;
@@ -13,16 +13,22 @@ interface Props {
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
const { title, description, image } = Astro.props;
const fullTitle =
title === SITE_TITLE || title.endsWith(` · ${SITE_TITLE}`)
? title
: `${title} · ${SITE_TITLE}`;
const fullTitle = (() => {
const t = (title || '').trim();
if (!t || t === SITE_TITLE) return `${SITE_TITLE} · ${SITE_TITLE_SUFFIX}`;
if (t === SITE_TITLE_SUFFIX || t.endsWith(` · ${SITE_TITLE_SUFFIX}`)) return t;
// 兼容旧写法里已带站名的标题
if (t.endsWith(` · ${SITE_TITLE}`)) {
return `${t.slice(0, -(` · ${SITE_TITLE}`).length)} · ${SITE_TITLE_SUFFIX}`;
}
return `${t} · ${SITE_TITLE_SUFFIX}`;
})();
---
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" href="/favicon.ico" />
<link rel="icon" type="image/jpeg" href="/logo.jpg?v=2" sizes="any" />
<link rel="apple-touch-icon" href="/apple-touch-icon.jpg?v=2" />
<link rel="sitemap" href="/sitemap-index.xml" />
<link
rel="alternate"
@@ -33,6 +39,8 @@ const fullTitle =
<meta name="generator" content={Astro.generator} />
<Font cssVariable="--font-atkinson" preload />
<Font cssVariable="--font-hand-latin" />
<Font cssVariable="--font-hand-zh" />
<link rel="canonical" href={canonicalURL} />
+7 -5
View File
@@ -1,11 +1,11 @@
---
import { SITE_TITLE } from '../consts';
import { SITE_BRAND } from '../consts';
import HeaderLink from './HeaderLink.astro';
---
<header>
<nav>
<a class="brand" href="/">{SITE_TITLE}</a>
<a class="brand" href="/">{SITE_BRAND}</a>
<div class="links">
<HeaderLink href="/">首页</HeaderLink>
<HeaderLink href="/posts/">文章</HeaderLink>
@@ -38,11 +38,13 @@ import HeaderLink from './HeaderLink.astro';
box-sizing: border-box;
}
.brand {
font-weight: 700;
font-size: 0.98em;
font-family: var(--font-hand);
font-weight: 400;
font-size: 1.35em;
color: rgb(var(--ink));
text-decoration: none;
letter-spacing: -0.02em;
letter-spacing: 0.06em;
font-synthesis: none;
transition:
color var(--dur-fast) var(--ease-out),
transform var(--dur-fast) var(--ease-out);
+10 -3
View File
@@ -1,7 +1,14 @@
/** 站点全局配置 —— 改这里就能换站名、域名、作者信息 */
export const SITE_TITLE = 'Notebook';
export const SITE_DESCRIPTION = '用 Obsidian 写作,用 Astro 发布的个人笔记博客。';
export const SITE_AUTHOR = '你的名字';
/** 站名(首页大标题、RSS 等) */
export const SITE_TITLE = 'Hnote';
/** 顶栏品牌文案 */
export const SITE_BRAND = "hang's note";
/** 浏览器标题后缀:文章名 · X.H. */
export const SITE_TITLE_SUFFIX = 'X.H.';
export const SITE_DESCRIPTION = '个人技术手记:用 Obsidian 写作,用 Astro 发布。';
export const SITE_AUTHOR = 'xhang';
/** 部署域名,构建 RSS / sitemap 会用到(不要带 https:// */
export const SITE_URL = 'https://notebook.any.me.uk';
+2 -2
View File
@@ -7,7 +7,7 @@ import { getPublishedPosts } from '../lib/content';
const posts = await getPublishedPosts();
---
<BaseLayout title={`关于 · ${SITE_TITLE}`} description={SITE_DESCRIPTION} wide>
<BaseLayout title="关于" description={SITE_DESCRIPTION} wide>
<div class="page-board">
<div class="board-main">
<section class="panel page-title-block">
@@ -20,7 +20,7 @@ const posts = await getPublishedPosts();
<h2>这个站</h2>
</div>
<p>
<strong>{SITE_AUTHOR}</strong> 的笔记博客:在 Obsidian / 坚果云写,用 Astro 发布为<strong
<strong>{SITE_TITLE}</strong>{SITE_AUTHOR}:在 Obsidian / 坚果云写,用 Astro 发布为<strong
>统一文章流</strong
>。
</p>
+11 -7
View File
@@ -27,7 +27,7 @@ const latestDate = (() => {
<div class="page-board with-left home-board">
<aside class="board-left">
<section class="panel profile">
<p class="eyebrow">Notebook</p>
<p class="eyebrow">手记</p>
<h1 class="site-name">{SITE_TITLE}</h1>
<p class="bio">{SITE_DESCRIPTION}</p>
<p class="author meta">
@@ -178,14 +178,14 @@ const latestDate = (() => {
.eyebrow {
margin: 0 0 0.35rem;
color: var(--accent);
font-size: 0.75rem;
letter-spacing: 0.08em;
text-transform: uppercase;
font-weight: 700;
font-size: 1.15rem;
letter-spacing: 0.12em;
text-transform: none;
}
.site-name {
margin: 0 0 0.45rem;
font-size: 1.45rem;
font-size: 2rem;
letter-spacing: 0.08em;
}
.bio {
margin: 0 0 0.7rem;
@@ -250,7 +250,11 @@ const latestDate = (() => {
}
.featured h2 {
margin: 0 0 0.4rem;
font-size: 1.2rem;
font-size: 1.55rem;
font-family: var(--font-hand);
font-weight: 400;
letter-spacing: 0.04em;
font-synthesis: none;
}
.featured p {
margin: 0 0 0.5rem;
+1 -2
View File
@@ -2,7 +2,6 @@
import BaseLayout from '../../../layouts/BaseLayout.astro';
import FolderTree from '../../../components/FolderTree.astro';
import SiteAside from '../../../components/SiteAside.astro';
import { SITE_TITLE } from '../../../consts';
import { getPublishedPosts } from '../../../lib/content';
import {
buildNoteTree,
@@ -31,7 +30,7 @@ if (!node) {
const crumbs = folder.split('/').filter(Boolean);
---
<BaseLayout title={`${node.name} · 文章 · ${SITE_TITLE}`} description={`目录:${folder}`} wide>
<BaseLayout title={`${node.name} · 文章`} description={`目录:${folder}`} wide>
<div class="page-board with-left">
<aside class="board-left">
<section class="panel">
+1 -2
View File
@@ -3,7 +3,6 @@ import BaseLayout from '../../layouts/BaseLayout.astro';
import DenseEntryList from '../../components/DenseEntryList.astro';
import FolderTree from '../../components/FolderTree.astro';
import SiteAside from '../../components/SiteAside.astro';
import { SITE_TITLE } from '../../consts';
import { getPublishedPosts } from '../../lib/content';
import { buildNoteTree, folderHref, getTopFolders } from '../../lib/tree';
@@ -13,7 +12,7 @@ const topFolders = getTopFolders(posts);
const rootEntries = posts.filter((n) => !n.id.includes('/'));
---
<BaseLayout title={`文章 · ${SITE_TITLE}`} description="知识库文章(含从坚果云同步的笔记)" wide>
<BaseLayout title="文章" description="知识库文章(含从坚果云同步的笔记)" wide>
<div class="page-board with-left">
<aside class="board-left">
<section class="panel">
+1 -2
View File
@@ -1,7 +1,6 @@
---
import BaseLayout from '../../layouts/BaseLayout.astro';
import DenseEntryList from '../../components/DenseEntryList.astro';
import { SITE_TITLE } from '../../consts';
import { getPublishedPosts } from '../../lib/content';
import { buildTagStats, normalizeTag, tagHref } from '../../lib/tags';
@@ -21,7 +20,7 @@ const otherTags = buildTagStats(posts, { minCount: 2 })
.slice(0, 12);
---
<BaseLayout title={`#${tag} · ${SITE_TITLE}`} description={`标签:${tag}`} wide>
<BaseLayout title={`#${tag}`} description={`标签:${tag}`} wide>
<div class="page-board">
<div class="board-main">
<section class="panel page-title-block">
+1 -2
View File
@@ -1,7 +1,6 @@
---
import BaseLayout from '../../layouts/BaseLayout.astro';
import SiteAside from '../../components/SiteAside.astro';
import { SITE_TITLE } from '../../consts';
import { getPublishedPosts } from '../../lib/content';
import { buildTagStats, groupTagsByInitial, tagHref } from '../../lib/tags';
@@ -11,7 +10,7 @@ const hotStats = buildTagStats(posts, { minCount: 2 });
const groups = groupTagsByInitial(allStats);
---
<BaseLayout title={`标签 · ${SITE_TITLE}`} description="按标签浏览文章" wide>
<BaseLayout title="标签" description="按标签浏览文章" wide>
<div class="page-board">
<div class="board-main">
<section class="panel page-title-block">
+5 -8
View File
@@ -40,6 +40,8 @@
border: none;
box-shadow: none;
box-sizing: border-box;
overflow: visible;
background: transparent;
}
.panel {
@@ -63,8 +65,8 @@
.panel-head h2,
.panel-head h1 {
margin: 0;
font-size: 0.92rem;
letter-spacing: 0.01em;
/* 字号由 global 手写标题规则控制 */
letter-spacing: 0.04em;
}
.panel-head a,
@@ -287,10 +289,9 @@
}
.prose-board .board-side {
position: sticky;
top: 4rem;
border: none;
width: 100%;
background: transparent;
}
/* 窄于约 900px 或高缩放:单列,主内容优先 */
@@ -318,10 +319,6 @@
flex: none;
}
.prose-board .board-side {
position: static;
}
.page-board .board-main,
.prose-board .article {
order: 1;
+39
View File
@@ -27,6 +27,17 @@
--dur-fast: 150ms;
--dur: 220ms;
--dur-slow: 420ms;
/* 特殊标题手写:Nanum Pen(拉丁)+ 志莽行(中文) */
--font-hand:
var(--font-hand-latin),
var(--font-hand-zh),
'Segoe Print',
'Bradley Hand',
'KaiTi',
'STKaiti',
'楷体',
cursive;
}
@media (prefers-color-scheme: dark) {
@@ -156,6 +167,34 @@ h3 {
margin-top: 1.4em;
}
/* 装饰性标题:真手写体(正文仍 Atkinson) */
.title-hand,
.eyebrow,
.site-name,
.page-title-block h1,
.panel-head h1,
.panel-head h2,
.section-head h2,
.hero h1 {
font-family: var(--font-hand);
/* 手写字体只有 400,禁止伪粗体 */
font-weight: 400;
letter-spacing: 0.04em;
line-height: 1.3;
font-synthesis: none;
-webkit-font-smoothing: antialiased;
}
/* 手写标题略放大,字框更舒展 */
.panel-head h1,
.panel-head h2 {
font-size: 1.2rem;
}
.page-title-block h1 {
font-size: clamp(1.65rem, 3.5vw, 2.1rem);
}
p {
margin: 0 0 0.95em;
}