1import{f as o,a as i}from"./Cpq5cWSF.js";import"./DFSKp5ky.js";import{O as n}from"./DW3PFlcl.js";const r={title:"Creating this site",description:"SvelteKit + Markdown static site & blog",date:"2026-01-01",categories:["sveltekit","svelte","frontend","web dev"],published:!0},{title:h,description:c,date:p,categories:g,published:u}=r;var a=o('<p>I created this personal site as a way of documenting all that I was learning and building. Along the way, I learned about SvelteKit and TypeScript, including how to preprocess and dynamically render blog posts like this one. I deployed the site to GitHub Pages, where youâre now able to read it.</p> <h2>The Very Basics of Frontend Development</h2> <p>At its most basic, a static site just consists of HTML (for the content of the site) and CSS (for the styling). Theyâre stored as HTML documents, and accessed by a web server through an HTTP connection to be displayed on a browser client. There exists a variety of tools and frameworks that aim to make managing large and complex websites easier, and to answer the question of where HTML gets generated.</p> <p>To clarify the client-server architecture models, there are two main approaches to rendering: server-side rendering and client-side rendering.</p> <ul><li>In <strong>server-side rendering</strong>, the browser requests a URL, the web server responds with HTML, and the browser renders it - the HTML is fully generated by the server.</li> <li>In <strong>client-side rendering</strong>, the server sends minimal HTML with a JavaScript bundle, the browser downloads JavaScript, and the final webpage is generated on the client side by that bundle.</li></ul> <p>This makes a difference to the end user, since it can affect the initial loading time (where SSR is faster) as well as the reactivity (where CSR has the advantage).</p> <p>Before we even get to rendering, though, thereâs also a distinction to be made between build time and runtime.</p> <ul><li><strong>Build time</strong>: before any rendering can happen, all code needs to be compiled into executable JavaScript.</li> <li><strong>Runtime</strong>: when a user visits the site, content is rendered, either on the server side or client side as defined above. Runtime rendering is when SSR/CSR come into play.</li></ul> <p>With frameworks like SvelteKit (or React), we can use a hybrid of these approaches, as well as take advantage of pre-built components and optimizations for fast loading. SvelteKit, by default, renders a component first on the server side, then âhydratesâ it on the client side to allow for reactivity. For pages that can be represented as simple HTML files at build time, we can set <code>prerender=true</code>, which means it doesnât need to be rendered again on the server or client side at runtime.</p> <h2>Using Svelte & SvelteKit</h2> <p>This site was built using Svelte, SvelteKit, and Markdown for these blog posts. Each of these are responsible for a different part of the stack, explained well in the <a href="https://svelte.dev/docs/kit/introduction" rel="nofollow">Svelte</a> and <a href="https://github.com/pngwn/MDsveX" rel="nofollow">mdsvex</a> docs. Hereâs a summary:</p> <ul><li><strong>Svelte</strong> is the UI framework, defining component <code>.svelte</code> files. It converts components to JavaScript which renders the HTML/CSS, and handles reactivity, events, and rendering.</li> <li><strong>SvelteKit</strong> is the application framework, providing the structure for the website or web app. It adds the data and logic to Svelte, including support for routers, SSR/CSR, and various optimizations. It operates on <code>.js</code> or <code>.ts</code> files, which fetch/prepare data before it is injected into <code>.svelte</code> components for rendering.</li></ul> <p>I found the most interesting part to be the way that blog posts are rendered. Blog posts all follow the same format - title, date, content - and thus can be stored as markdown files. In order to integrate markdown into the SvelteKit setup, I used mdsvex, which preprocesses <code>.md</code> files and turns them into Svelte components - I followed <a href="https://joyofcode.xyz/sveltekit-markdown-blog" rel="nofollow">
1this guide</a>. Rather than hard-coding posts, we can add posts simply by adding a new markdown file. These posts are all discovered by a globbing pattern and turned into data, exposed at the <code>api/posts</code> route. This data is rendered at <code>/writing/[post-name]</code> - the slug <code>[post-name]</code> is matched to the URL, and the corresponding markdown file renders it. These dynamics routes are a runtime concept - when a request comes in (a user visits the site), we load the markdown file and send a response.</p> <p>There are some restrictions as to what content can be prerendered (compiled to HTML at build time). According to the <a href="https://svelte.dev/docs/kit/page-options#prerender-When-not-to-prerender" rel="nofollow">docs</a>, âThe basic rule is this: for a page to be prerenderable, any two users hitting it directly must get the same content from the server.â Our blog posts, then, which only use parameters known at build time, can be prerendered. The prerenderer works by starting at the root of the app and crawling the files, generating HTML for all prerenderable pages and scanning each one for <code><a></code> elements pointing to other pages. Note that we need to explicitly specify all possible parameter values for our dynamic slug so that the prerenderer knows the routes for which it must generate HTML - otherwise, weâll run into an error like the following: <code>/writing/[slug] was marked prerenderable, but was not found while crawling</code>.</p> <p>The overall model Iâve clarified is markdown files -> modules -> data -> UI.</p> <h2>Deploying to GitHub Sites</h2> <p>Next is deploying the site - once we create the SvelteKit web app, it needs to be made available on the internet. I deployed the site on GitHub Pages, which hosts static sites - sites that donât require any server-side functionality. I use a basic GitHub Actions workflow to build the site - it installs dependencies, builds the site, and uploads the artifacts to blob storage. Finally, the artifacts are fetched and deployed to emma-x1.github.io/, where youâre seeing this now.</p> <h2>Conclusion</h2> <p>Overall, I was able to learn a lot about frontend and full stack development through creating this site. All of the source code is available at <a href="https://github.com/emma-x1/emma-x1.github.io" rel="nofollow">this repo</a>, and Iâm hoping to continue to update and improve it.</p>',1);function m(e){var t=a();n(36),i(e,t)}export{m as default,r as metadata};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.