Skip to content

Commit a59648e

Browse files
committed
Add AuthorQuote editorial pull-quote to About page
1 parent c354cea commit a59648e

4 files changed

Lines changed: 229 additions & 20 deletions

File tree

‎app/(home)/about/page.tsx‎

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
import { Description } from '@/components/text';
1010
import { TryIt } from '@/components/chapters/TryIt';
1111
import { LikeThisBlock } from '@/components/chapters/LikeThisBlock';
12+
import { AuthorQuote } from '@/components/chapters/AuthorQuote';
1213

1314
/**
1415
* /about — trust page. Personal, first-person, written by Gor.
@@ -25,32 +26,43 @@ export default function AboutPage() {
2526
/>
2627

2728
<Body>
28-
{/* 1. How Nu started — brief factual history of the project, first person. */}
29+
{/* 1. How Nu started — first-person voice, framed as editorial quote. */}
2930
<Chapter>
3031
<SectionHead
3132
title="How Nu started."
3233
lede={<>Two years of refactoring before the shape settled.</>}
3334
/>
3435
<Section>
35-
<Description>
36-
Nu started in fall 2024 as a handful of primitives I kept
37-
pulling out of a real system I was building. State handling
38-
did not fit any of the alternatives at the shape of data I
39-
was moving, so I isolated my own. Then execution. Then
40-
storage. Small pieces, growing.
41-
</Description>
42-
<Description>
43-
January 2025 I split those pieces out into their own repo.
44-
That is the moment Nu officially began. What followed was
45-
over a year of refactoring on a daily basis (hundreds of
46-
interface shapes, several rewrites from scratch) while a
47-
live system ran on top of it and pushed back on every wrong
48-
turn.
49-
</Description>
50-
<Description>
51-
Somewhere in that stretch I stopped calling it a library and
52-
started calling it a primitive. Nu 0.1 is what came out.
53-
</Description>
36+
<AuthorQuote
37+
name="Gor Arakelyan"
38+
role="Author of Nu"
39+
avatarSrc="/gor.png"
40+
avatarAlt="Gor Arakelyan"
41+
handle="arkkln"
42+
paragraphs={[
43+
<>
44+
Nu started in fall 2024 as a handful of primitives I kept
45+
pulling out of a real system I was building. State
46+
handling did not fit any of the alternatives at the shape
47+
of data I was moving, so I isolated my own. Then
48+
execution — a small in-process engine for composing
49+
functions into flows. Small pieces, growing.
50+
</>,
51+
<>
52+
January 2025 I split those pieces out into their own
53+
repo. That is the moment Nu officially began. What
54+
followed was over 1.5 years of refactoring on a daily basis
55+
(hundreds of interface shapes, several rewrites from
56+
scratch) while a live system ran on top of it and pushed
57+
back on every wrong turn.
58+
</>,
59+
<>
60+
Somewhere in that stretch I stopped calling it a library
61+
and started calling it a primitive. Nu 0.1 is what came
62+
out.
63+
</>,
64+
]}
65+
/>
5466
</Section>
5567
</Chapter>
5668

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/* AuthorQuote — editorial pull-quote using the site's text components. */
2+
3+
.figure {
4+
margin: 0;
5+
position: relative;
6+
padding: 0.4em 0 0 3.2em;
7+
max-width: 62ch;
8+
}
9+
10+
.mark {
11+
position: absolute;
12+
left: 0;
13+
top: -0.15em;
14+
font-family: var(--font-display, ui-serif, Georgia, serif);
15+
font-size: 5.5em;
16+
line-height: 1;
17+
color: var(--site-ink-4);
18+
pointer-events: none;
19+
user-select: none;
20+
font-weight: 400;
21+
}
22+
23+
.quote {
24+
margin: 0;
25+
display: flex;
26+
flex-direction: column;
27+
gap: var(--site-gap-normal);
28+
max-width: 58ch;
29+
}
30+
31+
.paragraph {
32+
font-style: italic;
33+
}
34+
35+
.attribution {
36+
display: flex;
37+
align-items: center;
38+
gap: 0.85rem;
39+
margin-top: var(--site-gap-loose);
40+
}
41+
42+
.avatar {
43+
width: 52px;
44+
height: 52px;
45+
border-radius: 999px;
46+
object-fit: cover;
47+
display: block;
48+
border: 1px solid var(--site-border);
49+
box-shadow: 0 0 0 3px var(--site-accent-soft, transparent),
50+
0 0 0 4px var(--site-border-subtle);
51+
}
52+
53+
.rule {
54+
display: block;
55+
width: 2.2rem;
56+
height: 1px;
57+
background: var(--site-border-strong);
58+
flex-shrink: 0;
59+
}
60+
61+
.byline {
62+
display: flex;
63+
flex-direction: column;
64+
gap: 0.15em;
65+
line-height: 1.3;
66+
}
67+
68+
.nameRow {
69+
display: flex;
70+
align-items: baseline;
71+
gap: 0.5rem;
72+
flex-wrap: wrap;
73+
}
74+
75+
.name {
76+
font-size: var(--site-fs-body);
77+
color: var(--site-ink);
78+
font-weight: 400;
79+
}
80+
81+
.handle {
82+
font-size: var(--site-fs-label);
83+
color: var(--site-ink-3);
84+
text-decoration: none;
85+
border-bottom: 1px solid var(--site-border);
86+
transition: color 120ms ease, border-color 120ms ease;
87+
}
88+
89+
.handle:hover {
90+
color: var(--site-accent);
91+
border-bottom-color: var(--site-accent-line);
92+
}
93+
94+
.role {
95+
text-transform: uppercase;
96+
letter-spacing: 0.12em;
97+
}
98+
99+
@media (max-width: 640px) {
100+
.figure {
101+
padding: 0.9em 0 0 0;
102+
}
103+
.mark {
104+
position: absolute;
105+
top: 0;
106+
left: 0;
107+
font-size: 0;
108+
line-height: 0;
109+
width: 2.2rem;
110+
height: 2px;
111+
background: var(--site-border-strong);
112+
color: transparent;
113+
}
114+
.avatar {
115+
width: 44px;
116+
height: 44px;
117+
}
118+
.rule {
119+
width: 1.4rem;
120+
}
121+
.attribution {
122+
gap: 0.65rem;
123+
}
124+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import type { ReactNode } from 'react';
2+
import { Description, Label } from '@/components/text';
3+
import s from './AuthorQuote.module.css';
4+
5+
export interface AuthorQuoteProps {
6+
/** Paragraphs of the quote. Each rendered via <Description>. */
7+
paragraphs: ReactNode[];
8+
name: string;
9+
role: string;
10+
avatarSrc: string;
11+
avatarAlt?: string;
12+
/** Optional handle (e.g. "arkkln"). Rendered as "@handle" next to name. */
13+
handle?: string;
14+
/** Where the handle links to. Defaults to github.com/{handle}. */
15+
handleHref?: string;
16+
}
17+
18+
/**
19+
* AuthorQuote — editorial pull-quote. Oversized hanging drop-quote in the
20+
* left margin, paragraphs rendered with the site's <Description>, hairline
21+
* rule between avatar and byline. Uses site text components and tokens
22+
* throughout so weight/color/size match the rest of the page.
23+
*/
24+
export function AuthorQuote({
25+
paragraphs,
26+
name,
27+
role,
28+
avatarSrc,
29+
avatarAlt,
30+
handle,
31+
handleHref,
32+
}: AuthorQuoteProps) {
33+
const href =
34+
handleHref ?? (handle ? `https://github.com/${handle}` : undefined);
35+
return (
36+
<figure className={s.figure}>
37+
<span aria-hidden="true" className={s.mark}>“</span>
38+
<blockquote className={s.quote}>
39+
{paragraphs.map((p, i) => (
40+
<Description key={i} className={s.paragraph}>
41+
{p}
42+
</Description>
43+
))}
44+
</blockquote>
45+
<figcaption className={s.attribution}>
46+
<img
47+
src={avatarSrc}
48+
alt={avatarAlt ?? name}
49+
className={s.avatar}
50+
width={52}
51+
height={52}
52+
/>
53+
<span className={s.rule} aria-hidden="true" />
54+
<span className={s.byline}>
55+
<span className={s.nameRow}>
56+
<span className={s.name}>{name}</span>
57+
{handle ? (
58+
<a
59+
className={s.handle}
60+
href={href}
61+
target="_blank"
62+
rel="noopener noreferrer"
63+
>
64+
@{handle}
65+
</a>
66+
) : null}
67+
</span>
68+
<Label className={s.role}>{role}</Label>
69+
</span>
70+
</figcaption>
71+
</figure>
72+
);
73+
}

‎public/gor.png‎

215 KB
Loading

0 commit comments

Comments
 (0)