Add production www layout for levkin.ca hosting.

- build:www maps / to spec and /folders to stack-folder
- Umami tracking via stats.levkin.ca
- nginx deploy config for site LXC

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ilia 2026-05-22 21:57:15 -04:00
parent 85229b09c8
commit 6a571de240
27 changed files with 453 additions and 2 deletions

15
deploy/nginx-levkin.conf Normal file
View File

@ -0,0 +1,15 @@
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /var/www/levkin/www;
index index.html;
location /folders/ {
try_files $uri $uri/ /folders/index.html;
}
location / {
try_files $uri $uri/ /index.html;
}
}

View File

@ -6,6 +6,7 @@
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
"build:www": "node scripts/prepare-www.mjs",
"preview": "vite preview", "preview": "vite preview",
"capture-previews": "node scripts/capture-previews.mjs", "capture-previews": "node scripts/capture-previews.mjs",
"test:folder": "node scripts/test-stack-folder.mjs" "test:folder": "node scripts/test-stack-folder.mjs"

60
scripts/prepare-www.mjs Normal file
View File

@ -0,0 +1,60 @@
#!/usr/bin/env node
/**
* Build Vite output and lay out www/ for production nginx:
* / spec
* /folders/ stack-folder
*/
import { cp, mkdir, rm, readFile, writeFile } from 'fs/promises';
import { execSync } from 'child_process';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
const root = join(dirname(fileURLToPath(import.meta.url)), '..');
const dist = join(root, 'dist');
const www = join(root, 'www');
const umamiId = process.env.UMAMI_WEBSITE_ID || '2a3bc7b2-b827-4770-8b31-c94016667734';
const umamiScript = ` <script defer src="https://stats.levkin.ca/script.js" data-website-id="${umamiId}"></script>\n`;
function injectUmami(html) {
if (html.includes('stats.levkin.ca')) return html;
return html.replace('</head>', `${umamiScript} </head>`);
}
function patchHtml(html, patches) {
let out = html;
for (const [from, to] of patches) {
out = out.split(from).join(to);
}
return injectUmami(out);
}
execSync('npm run build', { cwd: root, stdio: 'inherit' });
await rm(www, { recursive: true, force: true });
await mkdir(join(www, 'assets'), { recursive: true });
await mkdir(join(www, 'folders'), { recursive: true });
await cp(join(dist, 'assets'), join(www, 'assets'), { recursive: true });
await cp(join(root, 'public', 'favicon.svg'), join(www, 'favicon.svg'));
const specHtml = await readFile(join(dist, 'spec', 'index.html'), 'utf8');
await writeFile(
join(www, 'index.html'),
patchHtml(specHtml, [
['<a href="/" class="back">← all options</a>', '<a href="/folders/" class="back">← folders</a>'],
]),
'utf8',
);
const folderHtml = await readFile(join(dist, 'stack-folder', 'index.html'), 'utf8');
await cp(join(root, 'stack-folder', 'previews'), join(www, 'folders', 'previews'), { recursive: true });
await writeFile(
join(www, 'folders', 'index.html'),
patchHtml(folderHtml, [
['href="/spec/"', 'href="/"'],
]),
'utf8',
);
console.log(`www/ ready (Umami id: ${umamiId})`);

View File

@ -24,7 +24,7 @@
<a class="skip-link" href="#main">Skip to specification</a> <a class="skip-link" href="#main">Skip to specification</a>
<aside class="toc" aria-labelledby="toc-heading"> <aside class="toc" aria-labelledby="toc-heading">
<a href="/" class="back">all options</a> <a href="/folders/" class="back">folders</a>
<p class="toc-doc-id">LK-SPEC-1.0</p> <p class="toc-doc-id">LK-SPEC-1.0</p>
<h2 id="toc-heading" class="toc-title">Table of contents</h2> <h2 id="toc-heading" class="toc-title">Table of contents</h2>
<nav aria-label="Specification sections"> <nav aria-label="Specification sections">

View File

@ -61,7 +61,7 @@
<h2>Scope</h2> <h2>Scope</h2>
<p><span class="hi">Boutique practice</span> — not a staffing agency. Clear deliverable and handoff so your team can own what ships.</p> <p><span class="hi">Boutique practice</span> — not a staffing agency. Clear deliverable and handoff so your team can own what ships.</p>
</div> </div>
<a class="site-preview" href="/spec/" target="_blank" rel="noopener noreferrer"> <a class="site-preview" href="/" target="_blank" rel="noopener noreferrer">
<span class="site-preview-bar"><span class="site-preview-url">levkin.ca / spec</span><span class="site-preview-go" aria-hidden="true"></span></span> <span class="site-preview-bar"><span class="site-preview-url">levkin.ca / spec</span><span class="site-preview-go" aria-hidden="true"></span></span>
<span class="site-preview-frame"><img class="site-preview-img" src="./previews/spec.png" alt="" loading="lazy" decoding="async" /></span> <span class="site-preview-frame"><img class="site-preview-img" src="./previews/spec.png" alt="" loading="lazy" decoding="async" /></span>
</a> </a>

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

View File

@ -0,0 +1 @@
(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const e of document.querySelectorAll('link[rel="modulepreload"]'))i(e);new MutationObserver(e=>{for(const r of e)if(r.type==="childList")for(const o of r.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&i(o)}).observe(document,{childList:!0,subtree:!0});function s(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerPolicy&&(r.referrerPolicy=e.referrerPolicy),e.crossOrigin==="use-credentials"?r.credentials="include":e.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function i(e){if(e.ep)return;e.ep=!0;const r=s(e);fetch(e.href,r)}})();

View File

@ -0,0 +1 @@
import"./modulepreload-polyfill-B5Qt9EMX.js";const g="levkin-spec-prefs",a=[.875,1,1.125,1.25,1.375,1.5],d=1;function s(){try{return JSON.parse(localStorage.getItem(g)||"{}")}catch{return{}}}function f(e){localStorage.setItem(g,JSON.stringify(e))}function E(e){const n=a.indexOf(e);return n===-1?d:n}const m={light:"#e8e4dc",dim:"#b8b2a6",dark:"#080807"};function h(e){document.documentElement.dataset.theme=e,document.documentElement.style.colorScheme=e==="dark"?"dark":"light";let n=document.querySelector('meta[name="theme-color"]');n||(n=document.createElement("meta"),n.name="theme-color",document.head.appendChild(n)),n.content=m[e]||m.light;const c=document.querySelector(`input[name="theme"][value="${e}"]`);c&&(c.checked=!0)}function S(e){document.documentElement.style.setProperty("--font-scale",String(e));const n=document.getElementById("font-scale-readout");n&&(n.textContent=`${Math.round(e*100)}%`),document.querySelectorAll(".font-btn").forEach(c=>{const r=c.dataset.action;r==="decrease"&&(c.disabled=e<=a[0]),r==="increase"&&(c.disabled=e>=a[a.length-1])})}function p(){const e=s(),n=e.theme||"light",c=e.fontScale||a[d];let r=E(c);h(n),S(c),document.querySelectorAll('input[name="theme"]').forEach(o=>{o.addEventListener("change",()=>{const t={...s(),theme:o.value};f(t),h(o.value)})}),document.querySelectorAll(".font-btn").forEach(o=>{o.addEventListener("click",()=>{const t=o.dataset.action;t==="reset"?r=d:t==="decrease"&&r>0?r-=1:t==="increase"&&r<a.length-1&&(r+=1);const i=a[r],l={...s(),fontScale:i};f(l),S(i)})})}function v(){const e=document.querySelectorAll(".clause-anchor[id]"),n=document.querySelectorAll(".toc nav a");if(!e.length||!n.length)return;const c=o=>{n.forEach(t=>{const i=t.getAttribute("href")===`#${o}`;t.classList.toggle("is-active",i),i?t.setAttribute("aria-current","location"):t.removeAttribute("aria-current")})};if(window.matchMedia("(prefers-reduced-motion: reduce)").matches){const o=()=>{var l;let t=(l=e[0])==null?void 0:l.id;const i=120;e.forEach(u=>{u.getBoundingClientRect().top-i<=0&&(t=u.id)}),t&&c(t)};window.addEventListener("scroll",o,{passive:!0}),o();return}const r=new IntersectionObserver(o=>{o.forEach(t=>{t.isIntersecting&&c(t.target.id)})},{rootMargin:"-30% 0px -60% 0px"});e.forEach(o=>r.observe(o))}p();v();

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
www/favicon.svg Normal file
View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none">
<rect width="32" height="32" rx="6" fill="#0a0a0b"/>
<path d="M8 22V10h4.2c3.1 0 5 1.6 5 4.2 0 2.4-1.7 3.8-4.5 3.8H12v4H8zm4-7.2h1.8c1.4 0 2.2-.7 2.2-1.8S15.2 11 13.8 11H12v3.8zM20 22V10h6.5v3.2H24v2.2h2.2v3.2H24v3.6H20z" fill="#c4a574"/>
</svg>

After

Width:  |  Height:  |  Size: 323 B

175
www/folders/index.html Normal file
View File

@ -0,0 +1,175 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Levkin — Company Files</title>
<meta name="description" content="Levkin Inc. — company specification, filed by section." />
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&family=Instrument+Sans:wght@400;500;600&family=Literata:opsz,wght@7..72,400;7..72,600&display=swap" rel="stylesheet" />
<script type="module" crossorigin src="/assets/stackFolder-4cxThntN.js"></script>
<link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
<link rel="stylesheet" crossorigin href="/assets/stackFolder-oqVQaMMI.css">
<script defer src="https://stats.levkin.ca/script.js" data-website-id="2a3bc7b2-b827-4770-8b31-c94016667734"></script>
</head>
<body>
<header class="site-header desk-footer">
Levkin Inc. · production software, automation, and handoff-ready systems ·
<a href="https://cal.levkin.ca/ilia/consult" target="_blank" rel="noopener noreferrer">book discovery call</a>
</header>
<div class="tab-rail" id="tab-rail" aria-label="Layers L0L7">
<button type="button" class="rail-tab active" data-goto="0" data-layer="0">L0</button>
<button type="button" class="rail-tab" data-goto="1" data-layer="1">L1</button>
<button type="button" class="rail-tab" data-goto="2" data-layer="2">L2</button>
<button type="button" class="rail-tab" data-goto="3" data-layer="3">L3</button>
<button type="button" class="rail-tab" data-goto="4" data-layer="4">L4</button>
<button type="button" class="rail-tab" data-goto="5" data-layer="5">L5</button>
<button type="button" class="rail-tab" data-goto="6" data-layer="6">L6</button>
<button type="button" class="rail-tab" data-goto="7" data-layer="7">L7</button>
</div>
<main class="mount">
<article class="folder f0" data-layer="0" id="layer-0">
<button type="button" class="tab" data-goto="0"><span class="tab-code">L0</span><span class="tab-label"> · Company</span></button>
<div class="body body--has-preview">
<div class="body-copy">
<p class="file-id">LK-SPEC-1.0 · Cover sheet</p>
<h1>Levkin Software Development Company</h1>
<p class="lead">Custom applications, automation, and practice systems — <span class="hi">scoped</span>, <span class="hi">documented</span>, and built to run in <span class="hi">production</span>.</p>
<p class="avail"><span class="badge badge--avail">AVAILABLE</span> <span class="hi">Taking on new engagements</span> · remote NA &amp; EU</p>
<div class="cta-block">
<a class="btn btn--primary" href="https://cal.levkin.ca/ilia/consult" target="_blank" rel="noopener noreferrer">Book 15-minute discovery call</a>
<a class="btn btn--ghost" href="mailto:ilia@levkine.ca?subject=Project%20enquiry">ilia@levkine.ca</a>
</div>
</div>
<div class="cal-slot is-blocked" data-cal-embed data-cal-theme="dark" data-cal-target="cal-inline-l0">
<div class="site-preview-bar"><span class="site-preview-url">cal.levkin.ca · book a call</span><a class="site-preview-go" href="https://cal.levkin.ca/ilia/consult" target="_blank" rel="noopener noreferrer" aria-label="Open calendar in new tab"></a></div>
<div class="cal-embed-frame">
<div class="cal-inline" id="cal-inline-l0"></div>
<a class="cal-embed-fallback" href="https://cal.levkin.ca/ilia/consult" target="_blank" rel="noopener noreferrer">
<img src="/assets/cal-dark-CG5J0IJe.png" alt="" decoding="async" />
</a>
</div>
</div>
</div>
</article>
<article class="folder f1" data-layer="1" id="layer-1">
<button type="button" class="tab" data-goto="1"><span class="tab-code">L1</span><span class="tab-label"> · Scope</span></button>
<div class="body body--has-preview">
<div class="body-copy">
<h2>Scope</h2>
<p><span class="hi">Boutique practice</span> — not a staffing agency. Clear deliverable and handoff so your team can own what ships.</p>
</div>
<a class="site-preview" href="/" target="_blank" rel="noopener noreferrer">
<span class="site-preview-bar"><span class="site-preview-url">levkin.ca / spec</span><span class="site-preview-go" aria-hidden="true"></span></span>
<span class="site-preview-frame"><img class="site-preview-img" src="/assets/spec-Cv7nGqro.png" alt="" loading="lazy" decoding="async" /></span>
</a>
</div>
</article>
<article class="folder f2 folder--services" data-layer="2" id="layer-2">
<button type="button" class="tab" data-goto="2"><span class="tab-code">L2</span><span class="tab-label"> · Services</span></button>
<div class="body">
<div class="body-copy">
<h2>Services</h2>
<p class="section-lead">Primary lines — each engagement gets a <span class="hi">statement of work</span> after discovery.</p>
<ul class="service-deep-list">
<li><strong>Custom software</strong> — Web apps, APIs, and internal tools; fit the problem, not a preset stack.</li>
<li><strong>Automation</strong> — Reporting, notifications, data sync, ops in the background. <span class="xref"><a href="https://auto.levkin.ca" target="_blank" rel="noopener noreferrer">auto.levkin.ca</a></span></li>
<li><strong>CaseWare</strong> — Templates, releases, practice customization, pipeline work. <span class="xref"><a href="https://caseware.levkin.ca" target="_blank" rel="noopener noreferrer">caseware.levkin.ca</a></span></li>
<li><strong>Quality &amp; testing</strong> — Test strategy, automation, release confidence. <span class="xref"><a href="https://iliadobkin.com" target="_blank" rel="noopener noreferrer">iliadobkin.com</a></span></li>
</ul>
<p class="service-note"><strong>How we work:</strong> fixed scope · production-ready · handoff-friendly · right-sized solutions.</p>
<p class="service-note">Discovery call → written proposal → delivery with docs → optional support.</p>
</div>
<div class="body-fill" aria-hidden="true"></div>
</div>
</article>
<article class="folder f3" data-layer="3" id="layer-3">
<button type="button" class="tab" data-goto="3"><span class="tab-code">L3</span><span class="tab-label"> · Automation</span></button>
<div class="body body--has-preview">
<div class="body-copy">
<h2>Automation</h2>
<p>Workflows that run <span class="hi">reliably in the background</span> — reporting, sync, ops off your plate.</p>
</div>
<a class="site-preview" href="https://auto.levkin.ca" target="_blank" rel="noopener noreferrer">
<span class="site-preview-bar"><span class="site-preview-url">auto.levkin.ca</span><span class="site-preview-go" aria-hidden="true"></span></span>
<span class="site-preview-frame"><img class="site-preview-img" src="/assets/auto-DdJGDEee.png" alt="" loading="lazy" decoding="async" /></span>
</a>
</div>
</article>
<article class="folder f4" data-layer="4" id="layer-4">
<button type="button" class="tab" data-goto="4"><span class="tab-code">L4</span><span class="tab-label"> · Enterprise</span></button>
<div class="body body--has-preview">
<div class="body-copy">
<h2>CaseWare</h2>
<p>Templates, releases, and practice customization — from small fixes to full pipeline overhauls.</p>
</div>
<a class="site-preview" href="https://caseware.levkin.ca" target="_blank" rel="noopener noreferrer">
<span class="site-preview-bar"><span class="site-preview-url">caseware.levkin.ca</span><span class="site-preview-go" aria-hidden="true"></span></span>
<span class="site-preview-frame"><img class="site-preview-img" src="/assets/caseware-CaGYkxOF.png" alt="" loading="lazy" decoding="async" /></span>
</a>
</div>
</article>
<article class="folder f5" data-layer="5" id="layer-5">
<button type="button" class="tab" data-goto="5"><span class="tab-code">L5</span><span class="tab-label"> · Portfolio</span></button>
<div class="body body--has-preview">
<div class="body-copy">
<h2>Quality &amp; testing</h2>
<p>Test strategy, automation, and release confidence without hiring full-time.</p>
</div>
<a class="site-preview" href="https://iliadobkin.com" target="_blank" rel="noopener noreferrer">
<span class="site-preview-bar"><span class="site-preview-url">iliadobkin.com</span><span class="site-preview-go" aria-hidden="true"></span></span>
<span class="site-preview-frame"><img class="site-preview-img" src="/assets/iliadobkin-B_2flTdO.png" alt="" loading="lazy" decoding="async" /></span>
</a>
</div>
</article>
<article class="folder f6" data-layer="6" id="layer-6">
<button type="button" class="tab" data-goto="6"><span class="tab-code">L6</span><span class="tab-label"> · Source</span></button>
<div class="body body--has-preview">
<div class="body-copy">
<h2>Source &amp; repos</h2>
<p>Project code and templates on our Gitea — private by default, yours on handoff.</p>
</div>
<a class="site-preview" href="https://git.levkin.ca/explore/repos" target="_blank" rel="noopener noreferrer">
<span class="site-preview-bar"><span class="site-preview-url">git.levkin.ca / explore</span><span class="site-preview-go" aria-hidden="true"></span></span>
<span class="site-preview-frame"><img class="site-preview-img" src="/assets/git-repos-B2iogTL_.png" alt="" loading="lazy" decoding="async" /></span>
</a>
</div>
</article>
<article class="folder f7 folder--last" data-layer="7" id="layer-7">
<button type="button" class="tab" data-goto="7"><span class="tab-code">L7</span><span class="tab-label"> · Engage</span></button>
<div class="body body--has-preview">
<div class="body-copy">
<h2>Terms &amp; contact</h2>
<ul class="terms-list">
<li><strong>Fixed scope</strong> — quoted after discovery; no open-ended hourly surprises.</li>
<li><strong>Production-ready</strong> — monitoring, failure handling, documentation included.</li>
<li><strong>Handoff-friendly</strong> — your team or the next vendor can maintain what we ship.</li>
</ul>
</div>
<div class="cal-slot is-blocked" data-cal-embed data-cal-theme="light" data-cal-target="cal-inline-l7">
<div class="site-preview-bar"><span class="site-preview-url">cal.levkin.ca · book a call</span><a class="site-preview-go" href="https://cal.levkin.ca/ilia/consult" target="_blank" rel="noopener noreferrer" aria-label="Open calendar in new tab"></a></div>
<div class="cal-embed-frame">
<div class="cal-inline" id="cal-inline-l7"></div>
<a class="cal-embed-fallback" href="https://cal.levkin.ca/ilia/consult" target="_blank" rel="noopener noreferrer">
<img src="/assets/cal-light-sOepgTJC.png" alt="" decoding="async" />
</a>
</div>
</div>
</div>
</article>
<div class="stack-stop" aria-hidden="true"></div>
</main>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

191
www/index.html Normal file
View File

@ -0,0 +1,191 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Levkin — Company Specification</title>
<meta name="description" content="Levkin Inc.: software development and automation for production systems." />
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&family=Literata:opsz,wght@7..72,400;7..72,600&display=swap" rel="stylesheet" />
<script>
(function () {
try {
var p = JSON.parse(localStorage.getItem('levkin-spec-prefs') || '{}');
if (p.theme) document.documentElement.dataset.theme = p.theme;
if (p.fontScale) document.documentElement.style.setProperty('--font-scale', p.fontScale);
} catch (e) { /* ignore */ }
})();
</script>
<script type="module" crossorigin src="/assets/spec-BY4A7Wkv.js"></script>
<link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
<link rel="stylesheet" crossorigin href="/assets/spec-BoGenpAF.css">
<script defer src="https://stats.levkin.ca/script.js" data-website-id="2a3bc7b2-b827-4770-8b31-c94016667734"></script>
</head>
<body>
<a class="skip-link" href="#main">Skip to specification</a>
<aside class="toc" aria-labelledby="toc-heading">
<a href="/folders/" class="back">← folders</a>
<p class="toc-doc-id">LK-SPEC-1.0</p>
<h2 id="toc-heading" class="toc-title">Table of contents</h2>
<nav aria-label="Specification sections">
<a href="#preamble"><span class="toc-num"></span> Preamble</a>
<a href="#scope"><span class="toc-num">1</span> Scope</a>
<a href="#services"><span class="toc-num">2</span> Services</a>
<a href="#working"><span class="toc-num">3</span> Terms of engagement</a>
<a href="#links"><span class="toc-num">4</span> References</a>
<a href="#contact"><span class="toc-num">5</span> Contact</a>
</nav>
<section class="prefs" aria-labelledby="prefs-heading">
<h2 id="prefs-heading" class="prefs-heading">Display</h2>
<fieldset class="theme-field">
<legend class="theme-legend">Theme</legend>
<div class="theme-options" role="radiogroup" aria-label="Color theme">
<label class="theme-option">
<input type="radio" name="theme" value="light" checked />
<span>Light</span>
</label>
<label class="theme-option">
<input type="radio" name="theme" value="dim" />
<span>Dim</span>
</label>
<label class="theme-option">
<input type="radio" name="theme" value="dark" />
<span>Dark</span>
</label>
</div>
</fieldset>
<div class="font-controls">
<span class="font-label" id="font-controls-label">Text size</span>
<div class="font-buttons" role="group" aria-labelledby="font-controls-label">
<button type="button" class="font-btn" data-action="decrease" aria-label="Decrease text size">A</button>
<button type="button" class="font-btn" data-action="reset" aria-label="Reset text size to default">A</button>
<button type="button" class="font-btn" data-action="increase" aria-label="Increase text size">A+</button>
</div>
<span class="font-scale-readout" id="font-scale-readout" aria-live="polite">100%</span>
</div>
</section>
<p class="meta">Levkin Inc.<br />Effective May 2026</p>
</aside>
<main id="main" class="main" tabindex="-1">
<div class="desk">
<article class="instrument">
<header class="letterhead">
<p class="doc-class">Company Specification</p>
<h1>Levkin Software Development Company</h1>
<p class="doc-lead">Master overview of services and engagement terms. This document is not a binding agreement; a statement of work is issued for each engagement.</p>
<table class="meta-table">
<tbody>
<tr><th scope="row">Document</th><td>LK-SPEC-1.0</td></tr>
<tr><th scope="row">Entity</th><td>Levkin Inc.</td></tr>
<tr><th scope="row">Status</th><td><span class="badge">ACTIVE</span></td></tr>
<tr><th scope="row">Effective</th><td><time datetime="2026-05-20">20 May 2026</time></td></tr>
</tbody>
</table>
</header>
<div id="preamble" class="preamble clause-anchor">
<h2 class="section-heading"><span class="section-num"></span> Preamble</h2>
<p><strong>Levkin Inc.</strong> builds and maintains software for businesses — custom applications, automation, and specialized practice systems. Work is scoped, documented, and built to run in production without hand-holding.</p>
<p><span class="badge">AVAILABLE</span> Taking on new engagements. Remote across North American and European time zones.</p>
</div>
<section id="scope" class="article clause-anchor" aria-labelledby="scope-heading">
<h2 id="scope-heading" class="section-heading"><span class="section-num">1.</span> Scope</h2>
<p>Boutique practice — not a staffing agency. Projects have a clear start, deliverable, and handoff so your team can own what ships.</p>
<p>Typical flow: a short discovery call, a fixed-scope proposal, delivery with documentation, then optional ongoing support if you want it.</p>
</section>
<section id="services" class="article clause-anchor" data-article="2" aria-labelledby="services-heading">
<h2 id="services-heading" class="section-heading"><span class="section-num">2.</span> Services</h2>
<p class="section-lead">Primary service lines. Scope, timeline, and fees for a given engagement are set out in a separate statement of work.</p>
<div class="subsections">
<div class="subsection">
<h3 class="subsection-title">Custom software</h3>
<p>Web apps, APIs, and internal tools — chosen to fit the problem, not a preset stack.</p>
</div>
<div class="subsection">
<h3 class="subsection-title">Automation</h3>
<p>Workflows and integrations that run reliably in the background — reporting, notifications, data sync, and repetitive ops work off your plate. <span class="xref">See <a href="https://auto.levkin.ca" rel="noopener noreferrer">auto.levkin.ca<span class="sr-only"> (external)</span></a>.</span></p>
</div>
<div class="subsection">
<h3 class="subsection-title">CaseWare</h3>
<p>Templates, releases, and practice customization for firms on CaseWare — from small fixes to full pipeline overhauls. <span class="xref">See <a href="https://caseware.levkin.ca" rel="noopener noreferrer">caseware.levkin.ca<span class="sr-only"> (external)</span></a>.</span></p>
</div>
<div class="subsection">
<h3 class="subsection-title">Quality &amp; testing</h3>
<p>Test strategy, automation, and release confidence for teams that need an experienced QA lead without hiring full-time. <span class="xref">See <a href="https://iliadobkin.com" rel="noopener noreferrer">iliadobkin.com<span class="sr-only"> (external)</span></a>.</span></p>
</div>
</div>
</section>
<section id="working" class="article clause-anchor" data-article="3" aria-labelledby="working-heading">
<h2 id="working-heading" class="section-heading"><span class="section-num">3.</span> Terms of engagement</h2>
<div class="subsections">
<div class="subsection">
<h3 class="subsection-title">Fixed scope</h3>
<p>Quoted after discovery; no open-ended hourly surprises.</p>
</div>
<div class="subsection">
<h3 class="subsection-title">Production-ready</h3>
<p>Monitoring, failure handling, and documentation included by default.</p>
</div>
<div class="subsection">
<h3 class="subsection-title">Handoff-friendly</h3>
<p>Your team or the next vendor can maintain what we ship.</p>
</div>
<div class="subsection">
<h3 class="subsection-title">Right-sized</h3>
<p>The smallest solution that actually solves the problem.</p>
</div>
</div>
</section>
<section id="links" class="article clause-anchor" aria-labelledby="links-heading">
<h2 id="links-heading" class="section-heading"><span class="section-num">4.</span> References</h2>
<table class="contract-table">
<caption class="sr-only">External references</caption>
<thead>
<tr><th scope="col">Reference</th><th scope="col">Purpose</th></tr>
</thead>
<tbody>
<tr><td><a href="https://auto.levkin.ca" rel="noopener noreferrer">auto.levkin.ca<span class="sr-only"> (external)</span></a></td><td>Automation</td></tr>
<tr><td><a href="https://caseware.levkin.ca" rel="noopener noreferrer">caseware.levkin.ca<span class="sr-only"> (external)</span></a></td><td>CaseWare</td></tr>
<tr><td><a href="https://cal.levkin.ca/ilia/consult" rel="noopener noreferrer">cal.levkin.ca<span class="sr-only"> (external)</span></a></td><td>Book a discovery call</td></tr>
</tbody>
</table>
</section>
<section id="contact" class="article article--final clause-anchor" aria-labelledby="contact-heading">
<h2 id="contact-heading" class="section-heading"><span class="section-num">5.</span> Contact</h2>
<p class="section-lead">To discuss a project, use either channel below. A formal statement of work follows acceptance of a written proposal.</p>
<table class="contract-table contract-table--contact">
<caption class="sr-only">Contact channels</caption>
<tbody>
<tr>
<th scope="row">Schedule</th>
<td><a href="https://cal.levkin.ca/ilia/consult" rel="noopener noreferrer">15-minute discovery call<span class="sr-only"> (opens cal.levkin.ca)</span></a></td>
</tr>
<tr>
<th scope="row">Correspondence</th>
<td><a href="mailto:ilia@levkine.ca?subject=Project%20enquiry">ilia@levkine.ca</a></td>
</tr>
</tbody>
</table>
<footer class="instrument-footer">
<p>© Levkin Inc. · Canadian software development</p>
<p>LK-SPEC-1.0 · levkin.ca · Effective 20 May 2026</p>
</footer>
</section>
</article>
</div>
</main>
</body>
</html>