Compare commits
22 Commits
9a1db2c58d
...
main
Author | SHA1 | Date | |
---|---|---|---|
ce54138492 | |||
eb40610536 | |||
dac81fc223 | |||
460617e424 | |||
590a372417 | |||
6b21292003 | |||
89a75c94ca | |||
7e4b13606c | |||
2250721be3 | |||
e22584b600 | |||
758df7627a | |||
738f5a348a | |||
eff9aa55cf | |||
9642bfba10 | |||
3dbfa95a0c | |||
9321d70e3d | |||
8b8c83d002 | |||
63e1df5d01 | |||
f0d3a8ed30 | |||
57634adf42 | |||
6fb19ff89c | |||
00dad9fd3f |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -22,3 +22,4 @@ logs
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
.vercel
|
||||
|
2
.omni.yaml
Normal file
2
.omni.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
up:
|
||||
- just
|
12
Justfile
Normal file
12
Justfile
Normal file
@@ -0,0 +1,12 @@
|
||||
set shell := ["zsh", "-c"]
|
||||
|
||||
deploy:
|
||||
vercel pull --yes --environment=production
|
||||
vercel --prod --yes
|
||||
|
||||
preview:
|
||||
vercel pull --yes --environment=preview
|
||||
vercel --yes
|
||||
|
||||
dev:
|
||||
yarn dev
|
14
README.md
14
README.md
@@ -73,3 +73,17 @@ bun run preview
|
||||
```
|
||||
|
||||
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
||||
|
||||
## Favicons
|
||||
|
||||
The SVG favicon is the source of truth: `public/favicon.svg`.
|
||||
|
||||
Generate a multi-size `favicon.ico` from the SVG using rsvg-convert + ImageMagick:
|
||||
|
||||
```bash
|
||||
yarn favicons
|
||||
```
|
||||
|
||||
Notes:
|
||||
- ImageMagick on macOS can have issues loading arbitrary TTFs by file path (RenderFreetype errors). To avoid font lookup issues entirely, this project rasterizes the SVG directly using `rsvg-convert` and then packages the sizes into a single ICO using ImageMagick.
|
||||
- If browsers fail to load webfonts in an external SVG, consider converting the “b” glyph to paths inside the SVG to guarantee pixel-identical rendering across formats.
|
||||
|
11
app/app.vue
11
app/app.vue
@@ -1,6 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<NuxtRouteAnnouncer />
|
||||
<NuxtWelcome />
|
||||
<Analytics />
|
||||
<SpeedInsights />
|
||||
<NuxtLayout>
|
||||
<NuxtPage />
|
||||
</NuxtLayout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Analytics } from '@vercel/analytics/nuxt'
|
||||
import { SpeedInsights } from '@vercel/speed-insights/nuxt'
|
||||
</script>
|
||||
|
23
app/assets/css/main.css
Normal file
23
app/assets/css/main.css
Normal file
@@ -0,0 +1,23 @@
|
||||
/* Match brosner.com font */
|
||||
@import url("@fontsource-variable/roboto-slab/index.css");
|
||||
@import url("@fontsource/noto-sans-hebrew/400.css");
|
||||
@import url("@fontsource/noto-sans-hebrew/600.css");
|
||||
html, body {
|
||||
font-family: "Roboto Slab Variable", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
font-optical-sizing: auto;
|
||||
}
|
||||
|
||||
/* Ensure navbar icons remain white like the original */
|
||||
.icon > svg > path {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.hebrew, :lang(he) {
|
||||
font-family: "Noto Sans Hebrew", system-ui, sans-serif;
|
||||
}
|
||||
:lang(he) {
|
||||
direction: rtl;
|
||||
unicode-bidi: isolate;
|
||||
}
|
||||
|
||||
|
2070
app/assets/fonts/RobotoSlab-Bold.ttf
Normal file
2070
app/assets/fonts/RobotoSlab-Bold.ttf
Normal file
File diff suppressed because one or more lines are too long
9
app/components/Heb.vue
Normal file
9
app/components/Heb.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<span class="hebrew" lang="he" dir="rtl"><slot /></span>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// no-op
|
||||
</script>
|
||||
|
||||
|
49
app/layouts/default.vue
Normal file
49
app/layouts/default.vue
Normal file
@@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<div>
|
||||
<nav class="navbar">
|
||||
<div class="container">
|
||||
<div class="navbar-brand"></div>
|
||||
<div class="navbar-menu">
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<div class="field is-grouped">
|
||||
<p class="control">
|
||||
<a href="https://github.com/brosner" class="button is-dark" target="_blank" rel="noopener">
|
||||
<span class="icon">
|
||||
<svg version="1.1" role="presentation" width="17.82857142857143" height="20.8" viewBox="0 0 1536 1792" class="fa-icon" style="font-size: 1.3em;"><path d="M768 128q209 0 385.5 103t279.5 279.5 103 385.5q0 251-146.5 451.5t-378.5 277.5q-27 5-40-7t-13-30q0-3 0.5-76.5t0.5-134.5q0-97-52-142 57-6 102.5-18t94-39 81-66.5 53-105 20.5-150.5q0-119-79-206 37-91-8-204-28-9-81 11t-92 44l-38 24q-93-26-192-26t-192 26q-16-11-42.5-27t-83.5-38.5-85-13.5q-45 113-8 204-79 87-79 206 0 85 20.5 150t52.5 105 80.5 67 94 39 102.5 18q-39 36-49 103-21 10-45 15t-57 5-65.5-21.5-55.5-62.5q-19-32-48.5-52t-49.5-24l-20-3q-21 0-29 4.5t-5 11.5 9 14 13 12l7 5q22 10 43.5 38t31.5 51l10 23q13 38 44 61.5t67 30 69.5 7 55.5-3.5l23-4q0 38 0.5 88.5t0.5 54.5q0 18-13 30t-40 7q-232-77-378.5-277.5t-146.5-451.5q0-209 103-385.5t279.5-279.5 385.5-103zM291 1231q3-7-7-12-10-3-13 2-3 7 7 12 9 6 13-2zM322 1265q7-5-2-16-10-9-16-3-7 5 2 16 10 10 16 3zM352 1310q9-7 0-19-8-13-17-6-9 5 0 18t17 7zM394 1352q8-8-4-19-12-12-20-3-9 8 4 19 12 12 20 3zM451 1377q3-11-13-16-15-4-19 7t13 15q15 6 19-6zM514 1382q0-13-17-11-16 0-16 11 0 13 17 11 16 0 16-11zM572 1372q-2-11-18-9-16 3-14 15t18 8 14-14z"></path></svg>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
<p class="control">
|
||||
<a href="https://www.threads.net/@brosner" class="button is-info" target="_blank" rel="noopener">
|
||||
<span class="icon">
|
||||
<svg version="1.1" role="presentation" width="19.314285714285717" height="20.8" viewBox="0 0 1664 1792" class="fa-icon" style="font-size: 1.3em;"><path d="M1620 408q-67 98-162 167 1 14 1 42 0 130-38 259.5t-115.5 248.5-184.5 210.5-258 146-323 54.5q-271 0-496-145 35 4 78 4 225 0 401-138-105-2-188-64.5t-114-159.5q33 5 61 5 43 0 85-11-112-23-185.5-111.5t-73.5-205.5v-4q68 38 146 41-66-44-105-115t-39-154q0-88 44-163 121 149 294.5 238.5t371.5 99.5q-8-38-8-74 0-134 94.5-228.5t228.5-94.5q140 0 236 102 109-21 205-78-37 115-142 178 93-10 186-50z"></path></svg>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="content is-small has-text-centered">
|
||||
<p>
|
||||
Site built with <a href="https://nuxt.com" target="_blank">Nuxt</a> and <a href="https://bulma.io" target="_blank">Bulma</a>. Hosted on <a href="https://vercel.com" target="_blank">Vercel</a>.
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// no-op
|
||||
</script>
|
||||
|
||||
|
78
app/pages/index.vue
Normal file
78
app/pages/index.vue
Normal file
@@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<div id="app" class="hello wrapper">
|
||||
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<h1 class="title is-1">Brian Rosner</h1>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<div class="columns">
|
||||
<div class="column is-two-thirds content is-large">
|
||||
<h2>Work</h2>
|
||||
<p>
|
||||
I am a Staff Software Engineer at
|
||||
<a href="https://ramp.com/" target="_blank">Ramp</a>
|
||||
working on the infrastructure team.
|
||||
</p>
|
||||
<p>
|
||||
Previously, I was a Senior Software Engineer at Reddit, CTO at Gemr and Chief Architect at Eldarion.
|
||||
</p>
|
||||
<h2>Home</h2>
|
||||
<p>
|
||||
I live in <a href="https://en.wikipedia.org/wiki/Denver" target="_blank">Denver</a>,
|
||||
<a href="https://en.wikipedia.org/wiki/Colorado" target="_blank">Colorado</a>. I’m married to Hannah Yabrove‑Rosner. We have two kids, Eddie and Dylan, and three pets: Minnie and Jack (dogs) and Lily (cat).
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section" id="learning">
|
||||
<div class="container">
|
||||
<div class="columns">
|
||||
<div class="column is-two-thirds content is-large">
|
||||
<h2>Learning</h2>
|
||||
<p>These are some topics I am actively exploring:</p>
|
||||
|
||||
<h3 class="title is-4">Aviation</h3>
|
||||
<p>I learn aviation through flight sims—mostly MSFS 2020 (X‑Plane nostalgia is real). I’m drawn to airliners; the A350 and 757 are my favorites.</p>
|
||||
|
||||
<h3 class="title is-4">Israel</h3>
|
||||
<p>I visited Israel for the first time in December 2024. I’m reconnecting with my family’s Jewish roots, and I left with a deep appreciation for the country and its people.</p>
|
||||
|
||||
<h3 class="title is-4">Hebrew</h3>
|
||||
<p><Heb>אני לומד עברית</Heb></p>
|
||||
<p>I’d love to be fluent. I’m a little embarrassed that most of my study is Duolingo right now—but it keeps me consistent—and I lean on <a href="https://www.pealim.com/">Pealim</a> for vocab and verbs.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section" id="projects">
|
||||
<div class="container">
|
||||
<div class="columns">
|
||||
<div class="column is-two-thirds content is-large">
|
||||
<h2>Projects</h2>
|
||||
<h3 class="title is-4">Project Name</h3>
|
||||
<p>Short description of what it is, why it exists, and your role.</p>
|
||||
|
||||
<h3 class="title is-4">Project Name</h3>
|
||||
<p>Short description of what it is, why it exists, and your role.</p>
|
||||
|
||||
<h3 class="title is-4">Project Name</h3>
|
||||
<p>Short description of what it is, why it exists, and your role.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({ layout: 'default' })
|
||||
</script>
|
||||
|
||||
|
@@ -1,5 +1,18 @@
|
||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
compatibilityDate: '2025-07-15',
|
||||
devtools: { enabled: true }
|
||||
devtools: { enabled: true },
|
||||
modules: [],
|
||||
css: ['bulma/css/bulma.min.css', '@/assets/css/main.css'],
|
||||
nitro: {
|
||||
preset: 'vercel'
|
||||
},
|
||||
app: {
|
||||
head: {
|
||||
link: [
|
||||
{ rel: 'icon', type: 'image/svg+xml', href: '/favicon.svg' },
|
||||
{ rel: 'alternate icon', type: 'image/x-icon', href: '/favicon.ico' }
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@@ -7,10 +7,17 @@
|
||||
"dev": "nuxt dev",
|
||||
"generate": "nuxt generate",
|
||||
"preview": "nuxt preview",
|
||||
"favicons": "bash tools/generate-favicon.sh",
|
||||
"postinstall": "nuxt prepare"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource-variable/roboto-slab": "^5.2.6",
|
||||
"@fontsource/noto-sans-hebrew": "^5.2.6",
|
||||
"@vercel/analytics": "^1.5.0",
|
||||
"@vercel/speed-insights": "^1.2.0",
|
||||
"bulma": "^1.0.4",
|
||||
"nuxt": "^4.0.3",
|
||||
"typescript": "^5.6.3",
|
||||
"vue": "^3.5.18",
|
||||
"vue-router": "^4.5.1"
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 31 KiB |
17
public/favicon.svg
Normal file
17
public/favicon.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
|
||||
<defs>
|
||||
<style>
|
||||
.bg { fill: #111111; }
|
||||
.txt {
|
||||
fill: #ffffff;
|
||||
font-family: "Roboto Slab Variable", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 88px;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="bg" x="0" y="0" width="128" height="128" rx="24" ry="24" />
|
||||
<text class="txt" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">b</text>
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 499 B |
40
tools/generate-favicon.sh
Executable file
40
tools/generate-favicon.sh
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Generates a multi-size favicon.ico from public/favicon.svg
|
||||
# Dependencies:
|
||||
# - rsvg-convert (from librsvg)
|
||||
# - ImageMagick (magick)
|
||||
# macOS install:
|
||||
# brew install librsvg imagemagick
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
SVG_PATH="${ROOT_DIR}/public/favicon.svg"
|
||||
OUT_ICO_PATH="${ROOT_DIR}/public/favicon.ico"
|
||||
|
||||
if ! command -v rsvg-convert >/dev/null 2>&1; then
|
||||
echo "ERROR: rsvg-convert not found. Install with: brew install librsvg" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! command -v magick >/dev/null 2>&1; then
|
||||
echo "ERROR: ImageMagick (magick) not found. Install with: brew install imagemagick" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tmp_dir="$(mktemp -d)"
|
||||
cleanup() { rm -rf "${tmp_dir}"; }
|
||||
trap cleanup EXIT
|
||||
|
||||
sizes=(16 32 48 64)
|
||||
pngs=()
|
||||
for s in "${sizes[@]}"; do
|
||||
out_png="${tmp_dir}/favicon-${s}.png"
|
||||
rsvg-convert -w "${s}" -h "${s}" "${SVG_PATH}" -o "${out_png}"
|
||||
pngs+=("${out_png}")
|
||||
done
|
||||
|
||||
magick "${pngs[@]}" "${OUT_ICO_PATH}"
|
||||
echo "Generated ${OUT_ICO_PATH}"
|
||||
|
||||
|
Reference in New Issue
Block a user