feat(identity): real author photo across the site + About page rewrite
Deploy / build (push) Successful in 48s
Deploy / build (push) Successful in 48s
The photo is the identity evidence the external review flagged as the biggest gap. One source image (Pictures/Professional Portrait with Blue Gradient Background.png, 1254x1254), two sizes, WebP first with a JPEG fallback — continuous tone is the case where WebP/JPEG beat PNG: 640x640 42 KB JPG / 26 KB WebP About page (190 CSS px) 128x128 3 KB JPG / 2 KB WebP author card + home hero avatar It now appears in the About hero, the author card at the end of every post, the home hero (both languages), and JSON-LD Person.image — the node search engines read to associate the name with a face. About went from 1,024 characters to five sections: identity with photo, "By the numbers" (162 containers / 3 hosts / 71 essays / 0 hosting companies between me and the servers), the real tech stack in four columns, the Hoelee Enterprise block (website design and development is the main business, email hosting secondary), and a contact split between hiring and business. Also: the headshot's dark-blue background sits close to the page background, so the photo, hero avatar and card avatar get a faint brand ring plus shadow. Pictures/ keeps the converted JPG master next to the untouched PNG.
This commit is contained in:
1 parent
215051ef08
commit
6b7c5a983f
12 files changed
+410
-65
No files matched your search
@@ -3,21 +3,62 @@ import { SITE } from '../config';
|
||||
|
||||
interface Props {
|
||||
bio?: string;
|
||||
lang?: 'en' | 'zh';
|
||||
}
|
||||
|
||||
const { bio = 'Full-stack developer & DevOps engineer. I build web apps, self-host infrastructure, and automate things — this blog is my living portfolio.' } = Astro.props;
|
||||
const {
|
||||
bio = 'Full-stack developer & DevOps engineer based in Malaysia. I run my own production infrastructure and build web systems for small businesses — this blog is the living record.',
|
||||
lang = 'en',
|
||||
} = Astro.props;
|
||||
const isZh = lang === 'zh';
|
||||
|
||||
const t = isZh
|
||||
? {
|
||||
hiring: '招聘方:技术栈与履历',
|
||||
hiringHref: '/zh/about/',
|
||||
sme: '马来西亚中小企业:网站设计与开发',
|
||||
smeHref: SITE.website,
|
||||
stack: '全部技术文章',
|
||||
stackHref: '/zh/posts/',
|
||||
}
|
||||
: {
|
||||
hiring: 'Hiring? Profile & stack',
|
||||
hiringHref: '/about/',
|
||||
sme: 'Malaysian SME? Website design & development',
|
||||
smeHref: SITE.website,
|
||||
stack: 'All posts',
|
||||
stackHref: '/posts/',
|
||||
};
|
||||
---
|
||||
|
||||
<div class="author-card">
|
||||
<div class="avatar" aria-hidden="true">{SITE.handle.charAt(0)}</div>
|
||||
<div>
|
||||
<p class="who">{SITE.author}</p>
|
||||
<picture>
|
||||
<source srcset={SITE.photo.smallWebp} type="image/webp" />
|
||||
<img
|
||||
class="avatar"
|
||||
src={SITE.photo.small}
|
||||
alt={SITE.author}
|
||||
width="64"
|
||||
height="64"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
</picture>
|
||||
<div class="author-body">
|
||||
<p class="who">{SITE.author} · {SITE.handle}</p>
|
||||
<p class="bio">{bio}</p>
|
||||
<div class="links">
|
||||
<a href={SITE.linkedin} target="_blank" rel="noopener">LinkedIn</a>
|
||||
<a href={SITE.github} target="_blank" rel="noopener">GitHub</a>
|
||||
<a href={SITE.gitea} target="_blank" rel="noopener">Gitea</a>
|
||||
<a href={SITE.website} target="_blank" rel="noopener">hoelee.com</a>
|
||||
<a href={`mailto:${SITE.email}`}>{SITE.email}</a>
|
||||
</div>
|
||||
<p class="author-split">
|
||||
<a href={t.hiringHref}>{t.hiring}</a>
|
||||
<span class="sep">·</span>
|
||||
<a href={t.smeHref} target="_blank" rel="noopener">{t.sme} ↗</a>
|
||||
<span class="sep">·</span>
|
||||
<a href={t.stackHref}>{t.stack}</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
Reference in new issue
Block a user