mirror of
https://github.com/Patiun/com.gregkilmer.www.git
synced 2026-11-08 04:08:24 +00:00
Phase 5: every page of the site, the resume PDF and RSS
Landing, About, Now, Resume (with a generated PDF), Work and case studies, Inquiries and the sent page, Library and the Shelf, Workshop and craft pages, Tabletop, Blog with topics and posts, RSS, the Store, product lines, the order form and the 404, all rendered from the content service's notes. Schema: experience previousRoles, skills stack core items, page stats, make tags and deck favorite. Icon names from notes map to brand icons in one place, and HTML comments are dropped when Markdown renders. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012aSbo2D1qP8cMFQCykf7kx
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
---
|
||||
/**
|
||||
* The landing's "From the blog": one featured post (pinned, else newest) with
|
||||
* its image and topic, and the two most recent beside it. Renders nothing when
|
||||
* there are no posts.
|
||||
*/
|
||||
import StarChartArt from "@gk/ui/components/StarChartArt.astro";
|
||||
import { slugify } from "@gk/schema";
|
||||
import { blogStrip, readMinutes } from "../../lib/home.ts";
|
||||
import { formatDate, mediaSrc, type SiteIndex } from "../../lib/site.ts";
|
||||
|
||||
interface Props {
|
||||
site: SiteIndex;
|
||||
}
|
||||
const { site: s } = Astro.props;
|
||||
const { featured, recent } = blogStrip(s);
|
||||
const topicHref = (topic: string) => `/blog/topic/${slugify(topic)}`;
|
||||
---
|
||||
{
|
||||
featured && (
|
||||
<div class="strip">
|
||||
<div class="head">
|
||||
<div class="gk-heading-sm">
|
||||
<h3 id="from-blog">From the blog</h3>
|
||||
<span class="underline" aria-hidden="true" />
|
||||
</div>
|
||||
<a href="/blog" class="gk-text all">All articles</a>
|
||||
</div>
|
||||
<div class="posts">
|
||||
<article class="featured gk-card gk-linked">
|
||||
<StarChartArt
|
||||
seal="seven-metals"
|
||||
ratio="auto"
|
||||
src={mediaSrc(featured.data.cover)}
|
||||
alt={featured.data.cover ? featured.title : ""}
|
||||
class="art"
|
||||
/>
|
||||
<div class="body">
|
||||
<div class="tags">
|
||||
<span class="label">{featured.data.pinned ? "Featured" : "Latest"}</span>
|
||||
<a class="gk-chip" href={topicHref(featured.data.topic)}>{featured.data.topic}</a>
|
||||
</div>
|
||||
<h4 class="ftitle">
|
||||
<a href={s.href(featured) ?? "/blog"}>{featured.title}</a>
|
||||
</h4>
|
||||
<p class="summary">{featured.data.summary}</p>
|
||||
<span class="date">
|
||||
<time datetime={featured.data.date}>{formatDate(featured.data.date)}</time> · {readMinutes(featured.body)} min read
|
||||
</span>
|
||||
</div>
|
||||
</article>
|
||||
{
|
||||
recent.length > 0 && (
|
||||
<div class="recent">
|
||||
{recent.map((p) => (
|
||||
<article class="gk-card gk-linked small">
|
||||
<span class="tags">
|
||||
<span class="label">New</span>
|
||||
<a class="gk-chip" href={topicHref(p.data.topic)}>{p.data.topic}</a>
|
||||
</span>
|
||||
<h4 class="rtitle">
|
||||
<a href={s.href(p) ?? "/blog"}>{p.title}</a>
|
||||
</h4>
|
||||
<span class="date">
|
||||
<time datetime={p.data.date}>{formatDate(p.data.date)}</time> · {readMinutes(p.body)} min read
|
||||
</span>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
<style>
|
||||
.strip {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 22px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
.head {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
}
|
||||
.gk-heading-sm {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.gk-heading-sm h3 {
|
||||
margin: 0;
|
||||
font-size: 22px;
|
||||
letter-spacing: 0.08em;
|
||||
}
|
||||
.underline {
|
||||
display: block;
|
||||
width: 180px;
|
||||
height: 2px;
|
||||
border-radius: 2px;
|
||||
background: linear-gradient(90deg, var(--gk-gold), rgba(201, 162, 74, 0.15) 70%, transparent);
|
||||
box-shadow: 0 0 8px rgba(201, 162, 74, 0.35);
|
||||
}
|
||||
.all {
|
||||
font-size: 14px;
|
||||
}
|
||||
.posts {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
}
|
||||
.featured {
|
||||
flex: 2 1 560px;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 0;
|
||||
}
|
||||
.featured :global(.art) {
|
||||
flex: 1 1 240px;
|
||||
min-width: 0;
|
||||
height: 260px;
|
||||
border-radius: 0;
|
||||
border-right: 2px solid var(--gk-gold);
|
||||
}
|
||||
.body {
|
||||
flex: 2 1 300px;
|
||||
min-width: 0;
|
||||
padding: 26px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
.tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
.label {
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.3em;
|
||||
font-weight: 600;
|
||||
color: var(--gk-gold-bright);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
h4 {
|
||||
margin: 0;
|
||||
font-family: var(--gk-font-display);
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
line-height: 1.2;
|
||||
}
|
||||
h4 a {
|
||||
color: var(--gk-text);
|
||||
text-decoration: none;
|
||||
}
|
||||
h4 a::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
}
|
||||
.tags a {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.ftitle {
|
||||
font-size: 24px;
|
||||
}
|
||||
.rtitle {
|
||||
font-size: 17px;
|
||||
}
|
||||
.summary {
|
||||
margin: 0;
|
||||
font-size: 15px;
|
||||
line-height: 1.6;
|
||||
color: var(--gk-muted);
|
||||
}
|
||||
.date {
|
||||
margin-top: auto;
|
||||
font-size: 12px;
|
||||
color: var(--gk-muted);
|
||||
}
|
||||
.recent {
|
||||
flex: 1 1 280px;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
}
|
||||
.small {
|
||||
padding: 18px 20px;
|
||||
}
|
||||
@media (max-width: 640px) {
|
||||
.featured :global(.art) {
|
||||
border-right: 0;
|
||||
border-bottom: 2px solid var(--gk-gold);
|
||||
height: 200px;
|
||||
flex-basis: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user