Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Svelte 5 + TypeScript + Vite. Public repository.
| Value bonus for owning a front | `ownedBonus` in `data/production.ts` (019) |
| Shut-down businesses (owned, not running) | `isRunning` in `lib/properties.ts` (020) |
| Theme tokens | `src/app.css` (decision 009) |
| Link previews (Open Graph), preview image | `index.html`, `scripts/og-image.html` |
| CI, templates | `.github/` |
| Skills: `handoff`, `finish-pr`; agent: `scout` | `.claude/` |

Expand Down
21 changes: 21 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,29 @@
name="description"
content="Los Santos Operating System: track GTA Online businesses, safes and cooldowns in your browser."
/>
<meta name="theme-color" content="#62d394" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="canonical" href="https://lsos.toothy.dev/" />
<title>LSOS</title>

<!-- Link previews (Discord, Slack, X, ...). The image source is scripts/og-image.html. -->
<meta property="og:type" content="website" />
<meta property="og:site_name" content="LSOS" />
<meta property="og:url" content="https://lsos.toothy.dev/" />
<meta property="og:title" content="LSOS: GTA Online business tracker" />
<meta
property="og:description"
content="Keep it open while you play: stock, supplies, safes and cooldowns at a glance, so you know when to sell, collect or start the next heist. Free, no account, runs in your browser."
/>
<meta property="og:image" content="https://lsos.toothy.dev/og-image.png" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta
property="og:image:alt"
content="LSOS, Los Santos Operating System: track your GTA Online businesses, safes and cooldowns."
/>
<meta name="twitter:card" content="summary_large_image" />
</head>
<body>
<div id="app"></div>
Expand Down
Binary file added public/og-image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
191 changes: 191 additions & 0 deletions scripts/og-image.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
<!doctype html>
<!--
Source of public/og-image.png, the 1200x630 link preview (Open Graph) image. Colours and font
match src/app.css. To regenerate: open this file in a browser at 1200x630 and screenshot it,
e.g. with Playwright: page.setViewportSize({ width: 1200, height: 630 }), page.screenshot().
-->
<html lang="en">
<head>
<meta charset="UTF-8" />
<style>
@font-face {
font-family: 'Oswald Variable';
font-weight: 200 700;
src: url('../node_modules/@fontsource-variable/oswald/files/oswald-latin-wght-normal.woff2')
format('woff2-variations');
}
* {
box-sizing: border-box;
margin: 0;
}
html,
body {
width: 1200px;
height: 630px;
}
body {
background: #12161b;
color: #e8ecef;
font-family: 'Oswald Variable', 'Arial Narrow', sans-serif;
position: relative;
overflow: hidden;
}
body::after {
content: '';
position: absolute;
inset: 0;
background: repeating-linear-gradient(
to bottom,
rgb(0 0 0 / 0.14) 0 1px,
transparent 1px 4px
);
pointer-events: none;
}
.frame {
position: absolute;
inset: 36px;
border: 2px solid #34404c;
border-radius: 6px;
background: linear-gradient(135deg, #1a1f26, #12161b 70%);
padding: 64px 72px;
display: flex;
gap: 64px;
}
.left {
flex: 1;
display: flex;
flex-direction: column;
}
.brand {
display: flex;
align-items: center;
gap: 28px;
}
.icon {
width: 112px;
height: 112px;
}
h1 {
font-size: 132px;
line-height: 1;
font-weight: 600;
letter-spacing: 0.08em;
}
.sub {
margin-top: 22px;
font-size: 27px;
letter-spacing: 0.22em;
text-transform: uppercase;
color: #62d394;
}
.tag {
margin-top: 36px;
font-size: 40px;
font-weight: 400;
line-height: 1.25;
}
.foot {
margin-top: auto;
font-size: 24px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: #9aa7b3;
}
.cards {
width: 330px;
display: flex;
flex-direction: column;
gap: 22px;
justify-content: center;
}
.card {
background: #20262e;
border: 1px solid #34404c;
border-radius: 4px;
padding: 20px 24px;
}
.card h2 {
font-size: 22px;
font-weight: 500;
letter-spacing: 0.18em;
text-transform: uppercase;
margin-bottom: 14px;
}
.bar {
display: flex;
gap: 5px;
height: 14px;
margin-top: 8px;
}
.bar i {
flex: 1;
background: #2b343e;
border: 1px solid #6b7a88;
border-radius: 1px;
}
.bar.stock i.on {
background: #3a9e66;
border-color: #3a9e66;
}
.bar.sup i.on {
background: #3f6db8;
border-color: #3f6db8;
}
.bar.warn i.on {
background: #f0b450;
border-color: #f0b450;
}
</style>
</head>
<body>
<div class="frame">
<div class="left">
<div class="brand">
<svg class="icon" viewBox="0 0 32 32">
<rect width="32" height="32" rx="4" fill="#0b0f0c" />
<path
d="M7 10l6 6-6 6"
fill="none"
stroke="#7dff9b"
stroke-width="3"
stroke-linecap="square"
/>
<path d="M16 23h9" stroke="#7dff9b" stroke-width="3" />
</svg>
<h1>LSOS</h1>
</div>
<p class="sub">Los Santos Operating System</p>
<p class="tag">Track your GTA Online businesses,<br />safes and cooldowns.</p>
<p class="foot">Free · No account · Runs in your browser</p>
</div>
<div class="cards">
<div class="card">
<h2>Businesses</h2>
<div class="bar stock">
<i class="on"></i><i class="on"></i><i class="on"></i><i class="on"></i
><i class="on"></i><i class="on"></i><i></i><i></i><i></i><i></i>
</div>
<div class="bar sup">
<i class="on"></i><i class="on"></i><i class="on"></i><i></i><i></i><i></i><i></i><i></i
><i></i><i></i>
</div>
</div>
<div class="card">
<h2>Safes</h2>
<div class="bar stock">
<i class="on"></i><i class="on"></i><i class="on"></i><i class="on"></i
><i class="on"></i><i class="on"></i><i class="on"></i><i class="on"></i
><i class="on"></i><i></i>
</div>
</div>
<div class="card">
<h2>Cooldowns</h2>
<div class="bar warn">
<i class="on"></i><i class="on"></i><i class="on"></i><i class="on"></i><i></i><i></i
><i></i><i></i><i></i><i></i>
</div>
</div>
</div>
</div>
</body>
</html>
Loading