krasnov.dev - Portfolio Website

Statically generated website written in Svelte, showcasing my skills and experience.

demo

Yes, this is a demo for this very website. Yes, you can do inception with iframes ;)

svelte

This website is written in Svelte. It's a lightweight React-like component framework. Here's the skill component from the main page:

<script lang="ts">
    export let image: string;
    export let title: string;
    export let summary: string;
</script>

<div class="skill-container">
    <img src="{image}" alt="{title} icon"/>
    <h2>{title}</h2>
    <p>{@html summary}</p>
</div>

<style>
    img {
        height: 48px;
        width: 48px;
        margin-bottom: 12px;
        user-select: none;
    }

    /* ... */
</style>

Here's how the skill component is used:

<Section id="skills" watermarkPadding dark>
    <WatermarkHeader title="skills"/>
    <Skills>
        {#each data.skills as skill}
            <Skill {...skill}/>
        {/each}
    </Skills>
</Section>

compilation

Modern frontend frameworks enable amazing developer productivity. Static websites are simple to deploy and have great performance. I'm using SvelteKit, a modern framework for Svelte which compiles into a static website (similar to Next.js).

Parsing source code and highlighting keywords is a relatively expensive operation. I do this at compile time, which lets me avoid shipping the 112KB highlight.js library to the end user. The context="module" script is executed during compile time. The resulting HTML code snippets are passed as a prop into the component.

<script context="module" lang="ts">
    import hljs from "highlight.js";

    export async function load({fetch}) {
        const loadSvelteResponse = await fetch("/case_study/portfolio/snippet/load.svelte");
        // ...

        return {
            props: {
                codeSnippets: {
                    loadSvelte: hljs.highlight(await loadSvelteResponse.text(), {language: "HTML"}).value,
                    // ...
                }
            }
        }
    }
</script>

<script lang="ts">
    import CodeSnippet from "../../components/CodeSnippet.svelte";

    export let codeSnippets;
</script>

<CodeSnippet snippet={codeSnippets.loadSvelte}/>

This is what you'll find in this page's source (no trace of JavaScript).

<pre class="s-wg3bUO75wPN6">
	<code class="hljs s-wg3bUO75wPN6">
		<span class="hljs-tag">&lt;
			<span class="hljs-name">script</span>
			<span class="hljs-attr">context</span>=
			<span class="hljs-string">&quot;module&quot;</span>
			<span class="hljs-attr">lang</span>=
			<span class="hljs-string">&quot;ts&quot;</span>&gt;
		</span>
		<span class="language-javascript">
			<span class="hljs-keyword">import</span> hljs
			<span class="hljs-keyword">from</span>
			<span class="hljs-string">&quot;highlight.js&quot;</span>;

            <!-- ... -->

deployment

This website is hosted on the cloudflare CDN because it's boring and it works well.

For hosting locally and on Kubernetes I have this nifty 4-line bash script that generates the OCI image (alternative to a Dockerfile).

npm run build
CONTAINER=$(buildah from nginx:1.21.5-alpine)
buildah copy $CONTAINER build /usr/share/nginx/html
buildah commit --rm $CONTAINER portfolio-website

docker run --rm -it -p 8080:80 portfolio-website