Skip to content

Commit 79c9438

Browse files
gmoonclaude
andcommitted
Refactor: extract shared styles, constants, and components
- Extract shared style bases (codeBlock, inlineCode, pageWrapper, cardBase, sectionTitle, containerNarrow/Wide) into src/styles.ts (-100 lines net) - Extract CopyButton into src/components/CopyButton.tsx with timer cleanup - Add shared URL constants (LATTICE_DASHBOARD_PATH, GITHUB_REPO_URL, etc.) - Add LATTICE_LAYERS/LATTICE_EDGES constants for layer-color mapping - Add hoverLiftHandlers() helper to eliminate 5 duplicate mouse handlers - Replace recursive regex renderInline with single-pass character scanner - Type route page field as string union for exhaustive switch checking - Memoize ReaderPage node grouping, stats, and traceability computation - Memoize BlogPage renderContent call Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 4658ed5 commit 79c9438

15 files changed

Lines changed: 335 additions & 311 deletions

src/App.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import { ReaderPage } from './pages/ReaderPage'
33
import { BlogPage } from './pages/BlogPage'
44
import { GettingStartedPage } from './pages/GettingStartedPage'
55

6-
export function parseRoute(path: string): { page: string; slug?: string } {
6+
type PageRoute = 'home' | 'reader' | 'getting-started' | 'blog' | 'blog-post'
7+
8+
export function parseRoute(path: string): { page: PageRoute; slug?: string } {
79
if (path === '/reader' || path === '/reader/') return { page: 'reader' }
810
if (path === '/getting-started' || path === '/getting-started/') return { page: 'getting-started' }
911
if (path === '/blog' || path === '/blog/') return { page: 'blog' }

src/components/CopyButton.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { useState, useEffect, useRef } from 'react'
2+
import { colors, fonts } from '../tokens'
3+
4+
export function CopyButton({ text }: { text: string }) {
5+
const [copied, setCopied] = useState(false)
6+
const timerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)
7+
8+
useEffect(
9+
() => () => {
10+
clearTimeout(timerRef.current)
11+
},
12+
[],
13+
)
14+
15+
const handleCopy = () => {
16+
navigator.clipboard.writeText(text).then(() => {
17+
setCopied(true)
18+
clearTimeout(timerRef.current)
19+
timerRef.current = setTimeout(() => setCopied(false), 2000)
20+
})
21+
}
22+
23+
return (
24+
<button
25+
onClick={handleCopy}
26+
style={{
27+
position: 'absolute',
28+
top: '0.5rem',
29+
right: '0.5rem',
30+
background: copied ? colors.accentGreen : 'rgba(255,255,255,0.1)',
31+
color: copied ? '#ffffff' : 'rgba(255,255,255,0.7)',
32+
border: 'none',
33+
borderRadius: '4px',
34+
padding: '0.3rem 0.6rem',
35+
fontSize: '0.75rem',
36+
fontFamily: fonts.system,
37+
cursor: 'pointer',
38+
transition: 'all 0.2s',
39+
}}
40+
>
41+
{copied ? 'Copied!' : 'Copy'}
42+
</button>
43+
)
44+
}

src/components/Footer.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { colors, fonts } from '../tokens'
2+
import { GITHUB_REPO_URL } from '../constants'
23

34
const styles = {
45
footer: {
@@ -21,7 +22,7 @@ export function Footer() {
2122
<footer style={styles.footer}>
2223
<p>
2324
&copy; {new Date().getFullYear()} Forkzero. Built with{' '}
24-
<a href="https://github.com/forkzero/lattice" style={styles.link}>
25+
<a href={GITHUB_REPO_URL} style={styles.link}>
2526
Lattice
2627
</a>
2728
.

src/components/Header.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { colors, fonts } from '../tokens'
2+
import { GITHUB_ORG_URL, GITHUB_REPO_URL } from '../constants'
23

34
const styles = {
45
header: {
@@ -66,7 +67,7 @@ export function Header({ minimal }: { minimal?: boolean }) {
6667
<a href="/blog" style={styles.navLink}>
6768
Blog
6869
</a>
69-
<a href="https://github.com/forkzero" target="_blank" rel="noopener noreferrer" style={styles.navLinkGh}>
70+
<a href={GITHUB_ORG_URL} target="_blank" rel="noopener noreferrer" style={styles.navLinkGh}>
7071
GitHub
7172
</a>
7273
</nav>
@@ -85,7 +86,7 @@ export function PoweredByHeader() {
8586
<span style={{ color: 'rgba(255,255,255,0.7)', fontSize: '0.8rem', fontFamily: fonts.system }}>
8687
Powered by{' '}
8788
<a
88-
href="https://github.com/forkzero/lattice"
89+
href={GITHUB_REPO_URL}
8990
target="_blank"
9091
rel="noopener noreferrer"
9192
style={{ color: colors.textPrimary, textDecoration: 'none' }}

src/components/Hero.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { colors, fonts, gradient } from '../tokens'
2-
import { INSTALL_CMD } from '../constants'
2+
import { INSTALL_CMD, LATTICE_DASHBOARD_PATH } from '../constants'
33

44
const keyframesStyle = `
55
@keyframes lattice-fade-slide-up {
@@ -238,7 +238,7 @@ export function Hero() {
238238
<a href="/getting-started" style={styles.ctaPrimary}>
239239
Get Started
240240
</a>
241-
<a href="/reader?url=https://forkzero.github.io/lattice/lattice-data.json" style={styles.ctaSecondary}>
241+
<a href={LATTICE_DASHBOARD_PATH} style={styles.ctaSecondary}>
242242
See it live
243243
</a>
244244
</div>

src/components/LatticeFlowDiagram.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { colors, radius, fonts } from '../tokens'
2+
import { LATTICE_LAYERS, LATTICE_EDGES } from '../styles'
23

34
const styles: Record<string, React.CSSProperties> = {
45
diagramContainer: {
@@ -58,13 +59,8 @@ const styles: Record<string, React.CSSProperties> = {
5859
},
5960
}
6061

61-
const nodes = [
62-
{ label: 'Sources', color: colors.accentBlue },
63-
{ label: 'Theses', color: colors.accentPurple },
64-
{ label: 'Requirements', color: colors.accentYellow },
65-
{ label: 'Implementations', color: colors.accentGreen },
66-
]
67-
const edges = ['supports', 'derives', 'satisfies']
62+
const nodes = LATTICE_LAYERS.map((layer) => ({ label: layer.label, color: layer.color }))
63+
const edges = [...LATTICE_EDGES]
6864

6965
export function LatticeFlowDiagram() {
7066
return (

src/components/ProjectCard.tsx

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
import { colors, fonts, shadows, radius } from '../tokens'
1+
import { colors, fonts, shadows } from '../tokens'
2+
import { cardBase, hoverLiftHandlers } from '../styles'
23
import type { Project } from '../data/projects'
34

45
const styles = {
56
card: {
6-
background: colors.bgCard,
7-
borderRadius: radius,
7+
...cardBase,
88
padding: '1.5rem',
9-
boxShadow: shadows.md,
10-
border: `1px solid ${colors.borderColor}`,
119
transition: 'transform 0.2s, box-shadow 0.2s',
1210
display: 'flex',
1311
flexDirection: 'column' as const,
@@ -75,17 +73,7 @@ const styles = {
7573

7674
export function ProjectCard({ project }: { project: Project }) {
7775
return (
78-
<div
79-
style={styles.card}
80-
onMouseEnter={(e) => {
81-
e.currentTarget.style.transform = 'translateY(-2px)'
82-
e.currentTarget.style.boxShadow = shadows.lg
83-
}}
84-
onMouseLeave={(e) => {
85-
e.currentTarget.style.transform = 'translateY(0)'
86-
e.currentTarget.style.boxShadow = shadows.md
87-
}}
88-
>
76+
<div style={styles.card} {...hoverLiftHandlers(shadows.md)}>
8977
<div style={styles.header}>
9078
<div>
9179
<h3 style={styles.name}>{project.name}</h3>

src/constants.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,10 @@ export const INSTALL_URL = 'https://forkzero.ai/lattice/install.sh'
22
export const INSTALL_CMD = `curl -fsSL ${INSTALL_URL} | sh`
33
export const INSTALL_URL_WINDOWS = 'https://forkzero.ai/lattice/install.ps1'
44
export const INSTALL_CMD_WINDOWS = `irm ${INSTALL_URL_WINDOWS} | iex`
5+
6+
export const LATTICE_DATA_URL = 'https://forkzero.github.io/lattice/lattice-data.json'
7+
export const LATTICE_DASHBOARD_PATH = '/reader?url=' + LATTICE_DATA_URL
8+
export const LATTICE_DASHBOARD_URL = 'https://forkzero.ai' + LATTICE_DASHBOARD_PATH
9+
10+
export const GITHUB_ORG_URL = 'https://github.com/forkzero'
11+
export const GITHUB_REPO_URL = 'https://github.com/forkzero/lattice'

src/data/blog-posts.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { INSTALL_CMD, LATTICE_DASHBOARD_URL, GITHUB_REPO_URL } from '../constants'
2+
13
export interface BlogAuthor {
24
name: string
35
bio: string
@@ -154,14 +156,14 @@ Think of it as the coordination layer underneath. RAG selects *from* knowledge;
154156
155157
\`\`\`bash
156158
# Install
157-
curl -fsSL https://forkzero.ai/lattice/install.sh | sh
159+
${INSTALL_CMD}
158160
159161
# Initialize a lattice in your project
160162
lattice init
161163
\`\`\`
162164
163-
- [Lattice on GitHub](https://github.com/forkzero/lattice)
164-
- [Live dashboard](https://forkzero.ai/reader?url=https://forkzero.github.io/lattice/lattice-data.json)
165+
- [Lattice on GitHub](${GITHUB_REPO_URL})
166+
- [Live dashboard](${LATTICE_DASHBOARD_URL})
165167
- [Forkzero](https://forkzero.ai)`,
166168
},
167169
]

src/data/projects.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { GITHUB_REPO_URL, LATTICE_DASHBOARD_URL } from '../constants'
2+
13
export interface Project {
24
name: string
35
tagline: string
@@ -18,8 +20,8 @@ export const projects: Project[] = [
1820
status: 'Active',
1921
statusColor: '#10b981',
2022
tech: ['Rust', 'MCP', 'YAML'],
21-
url: 'https://github.com/forkzero/lattice',
22-
readerUrl: 'https://forkzero.ai/reader?url=https://forkzero.github.io/lattice/lattice-data.json',
23+
url: GITHUB_REPO_URL,
24+
readerUrl: LATTICE_DASHBOARD_URL,
2325
},
2426
{
2527
name: 'Team of Rivals',

0 commit comments

Comments
 (0)