Make the resume bilingual and part of the shared site chrome
Deploy to GitHub Pages / build (push) Canceled after 0s
Deploy to GitHub Pages / deploy (push) Canceled after 0s

Adds a Russian version (data/resume.ru.json, default language) with an RU/EN
switch stored under the key shared with the front page and the portfolio.
The top bar becomes the site-wide one (brand, Resume, Portfolio, Gitea,
Contact, language, theme) with a second row of anchors for this page's
sections, and the fonts move to Unbounded and Onest so the three pages share
one type system. Portfolio links now point at /portfolio/.

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 23:48:38 +03:00
co-authored by Claude Sonnet 5
parent 4d485fc19d
commit 04c1cc5877
27 changed files with 425 additions and 176 deletions
+15 -12
View File
@@ -1,25 +1,28 @@
import type { Metadata } from 'next'
import localFont from 'next/font/local'
import './globals.css'
// Both fonts are bundled (SIL Open Font License), so building never depends on the network.
const display = localFont({ src: './fonts/BricolageGrotesque-Variable.woff2', variable: '--font-display', weight: '200 800', display: 'swap' })
const text = localFont({ src: './fonts/InstrumentSans-Variable.woff2', variable: '--font-text', weight: '400 700', display: 'swap' })
export const metadata: Metadata = {
title: 'Emil Shanayev — Resume',
description: 'Resume of Emil Shanayev: backend, DevOps, AI systems, scientific software and game technology.',
authors: [{ name: 'Emil Shanayev' }],
title: 'Эмиль Шанаев — Резюме',
description: 'Резюме Эмиля Шанаева: бэкенд, DevOps, системы на базе ИИ, научное ПО и игровые технологии.',
authors: [{ name: 'Эмиль Шанаев' }],
}
// Dark is the default theme; a stored choice of "light" is applied before the first paint so the page never flashes.
const THEME_SCRIPT = "try{if(localStorage.getItem('theme')==='light')document.documentElement.dataset.theme='light'}catch(e){}"
// Before the first paint: the language (the stored choice, otherwise Russian) and the theme (dark unless "light" was
// chosen). Both keys are shared with the rest of shanaty.ru, so a choice carries over between the pages.
const BOOT_SCRIPT = `try{var d=document.documentElement,l=localStorage.getItem('lang');if(l!=='ru'&&l!=='en')l='ru';d.dataset.lang=l;d.lang=l;if(localStorage.getItem('theme')==='light')d.dataset.theme='light';document.title=d.getAttribute('data-title-'+l)||document.title}catch(e){}`
export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
return (
<html lang="en" data-theme="dark" className={`${display.variable} ${text.variable}`} suppressHydrationWarning>
<html
lang="ru"
data-lang="ru"
data-theme="dark"
data-title-ru="Эмиль Шанаев — Резюме"
data-title-en="Emil Shanayev — Resume"
suppressHydrationWarning
>
<head>
<script dangerouslySetInnerHTML={{ __html: THEME_SCRIPT }} />
<script dangerouslySetInnerHTML={{ __html: BOOT_SCRIPT }} />
</head>
<body>{children}</body>
</html>