Add a prominent link to the full portfolio
Deploy to GitHub Pages / build (push) Canceled after 0s
Deploy to GitHub Pages / deploy (push) Canceled after 0s

The top bar's accent button becomes Portfolio (Email stays in the hero and
the contact band), the hero gets a Full portfolio button, and the project
list ends with a large block linking to it. The link points at Gitea's list
of repos with the portfolio topic; the sync supplies the count and the
resume file can override the target and label. Also eases the display
weight and tracking of the name in the dark theme.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XtcZtnG4GQA1d6mW5PNrS9
This commit is contained in:
Emil
2026-09-20 22:58:37 +03:00
co-authored by Claude Sonnet 5
parent 15d36d6437
commit 7471d65f54
10 changed files with 115 additions and 18 deletions
+8 -4
View File
@@ -1,7 +1,7 @@
'use client'
import { useEffect, useState } from 'react'
import type { Live, Project, Resume } from '@/lib/types'
import type { Live, Portfolio, Project, Resume } from '@/lib/types'
import Gizmo from './Gizmo'
import Hero from './Hero'
import Projects from './Projects'
@@ -11,12 +11,15 @@ import TopBar from './TopBar'
// Deployed on shanaty.ru the build points at the same-origin file; elsewhere (dev, GitHub Pages) it uses the public URL.
const DATA_URL = process.env.NEXT_PUBLIC_DATA_URL ?? 'https://shanaty.ru/data/resume.json'
const GITEA_PROFILE = 'https://git.shanaty.ru/Emil_Shanaty'
// Used until (or unless) the live data supplies the link, so the portfolio button is always there.
const PORTFOLIO_FALLBACK: Portfolio = { href: 'https://git.shanaty.ru/explore/repos?q=portfolio&topic=1' }
type Status = 'loading' | 'live' | 'offline'
export default function Site({ initial }: Readonly<{ initial: Resume }>) {
const [resume, setResume] = useState<Resume>(initial)
const [projects, setProjects] = useState<Project[]>([])
const [portfolio, setPortfolio] = useState<Portfolio>(PORTFOLIO_FALLBACK)
const [generatedAt, setGeneratedAt] = useState<string>()
const [status, setStatus] = useState<Status>('loading')
@@ -28,6 +31,7 @@ export default function Site({ initial }: Readonly<{ initial: Resume }>) {
if (!data?.resume || !Array.isArray(data.projects)) throw new Error('unexpected data')
setResume(data.resume)
setProjects(data.projects)
if (data.portfolio?.href) setPortfolio(data.portfolio)
setGeneratedAt(data.generated_at)
setStatus('live')
})
@@ -43,11 +47,11 @@ export default function Site({ initial }: Readonly<{ initial: Resume }>) {
return (
<>
<TopBar name={resume.name} mailHref={mailHref} showProjects={showProjects} />
<TopBar name={resume.name} portfolio={portfolio} showProjects={showProjects} />
<Gizmo />
<main>
<Hero resume={resume} mailHref={mailHref} showProjects={showProjects} />
{showProjects && <Projects projects={projects} status={status} generatedAt={generatedAt} profileUrl={GITEA_PROFILE} />}
<Hero resume={resume} portfolio={portfolio} mailHref={mailHref} showProjects={showProjects} />
{showProjects && <Projects projects={projects} status={status} generatedAt={generatedAt} profileUrl={GITEA_PROFILE} portfolio={portfolio} />}
<Skills resume={resume} />
<Experience resume={resume} />
<Education resume={resume} />