<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ludy.dev</title>
    <description>The latest articles on DEV Community by ludy.dev (@lyyluca).</description>
    <link>https://dev.to/lyyluca</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3749447%2F916d0753-f6e8-4be4-9608-6ef818f69843.jpg</url>
      <title>DEV Community: ludy.dev</title>
      <link>https://dev.to/lyyluca</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lyyluca"/>
    <language>en</language>
    <item>
      <title>I built a collection of 160+ client-side utility calculators using Next.js and Tailwind CSS</title>
      <dc:creator>ludy.dev</dc:creator>
      <pubDate>Thu, 25 Jun 2026 14:50:57 +0000</pubDate>
      <link>https://dev.to/lyyluca/i-built-a-collection-of-160-client-side-utility-calculators-using-nextjs-and-tailwind-css-4kjh</link>
      <guid>https://dev.to/lyyluca/i-built-a-collection-of-160-client-side-utility-calculators-using-nextjs-and-tailwind-css-4kjh</guid>
      <description>&lt;p&gt;As web developers, we often build complex SaaS products, but sometimes the most satisfying projects are clean, fast utility tools. Recently, I set out to build &lt;a href="https://multicalctool.com" rel="noopener noreferrer"&gt;MultiCalcTool&lt;/a&gt;, a collection of over 160 free calculators designed to replace the slow, ad-bloated legacy calculator sites that dominate search engines. Here is a breakdown of the tech stack and the architectural decisions I made to keep it fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture: Pure Client-Side Execution
&lt;/h2&gt;

&lt;p&gt;One of my core requirements was speed and privacy. I decided that all calculations should run entirely client-side. There is no backend database processing user inputs. Whether someone is calculating their monthly mortgage payments, estimated income tax, or body mass index, the math happens instantly inside their browser.&lt;/p&gt;

&lt;p&gt;To achieve this, I used Next.js to handle static site generation and page routing, combined with Tailwind CSS for a responsive, clean design system. Each calculator page is statically exported, meaning the HTML is pre-rendered at build time. When a user visits a calculator, they download a tiny, optimized JavaScript bundle that handles only the formula logic for that specific tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Managing 160+ Unique Calculation Formulas
&lt;/h2&gt;

&lt;p&gt;Managing the math logic for over 160 distinct tools was a major organizational challenge. I structured the codebase by separating the UI components from the mathematical engine. Each category (finance, math, health, tax) has a dedicated directory of mathematical utility functions.&lt;/p&gt;

&lt;p&gt;For instance, the financial formulas use standard amortization algorithms, while the construction calculators rely on precise geometry functions. I implemented TypeScript across the entire project to ensure that input variables were strictly typed. This prevented runtime rounding bugs, which are common when dealing with JavaScript's floating-point precision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimizing for Page Speed
&lt;/h2&gt;

&lt;p&gt;Since utility websites rely heavily on organic search traffic, performance metrics were critical. By keeping the pages static and leveraging local client-side execution, the site achieved near-perfect core web vitals. There are no external tracking scripts or advertising SDKs blocking the main thread, resulting in instantaneous page loads even on slower mobile connections.&lt;/p&gt;

&lt;p&gt;The project is now live, and I would love to hear feedback from other developers on how to improve the overall responsive layout.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>javascript</category>
      <category>tailwindcss</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building a Zero-Database, No-Signup Quiz Engine for Instant Psychometric Scoring</title>
      <dc:creator>ludy.dev</dc:creator>
      <pubDate>Tue, 23 Jun 2026 05:18:08 +0000</pubDate>
      <link>https://dev.to/lyyluca/building-a-zero-database-no-signup-quiz-engine-for-instant-psychometric-scoring-hj1</link>
      <guid>https://dev.to/lyyluca/building-a-zero-database-no-signup-quiz-engine-for-instant-psychometric-scoring-hj1</guid>
      <description>&lt;p&gt;The scoring engine is a lightweight, pure JavaScript function. As the user selects answers, the engine mutates an in-memory vector representing the scoring dimensions. &lt;/p&gt;

&lt;p&gt;For the MBTI test, it calculates the raw coordinate offsets across the four dichotomies (E/I, S/N, T/F, J/P). For the IQ test, it matches the cumulative correct answers against a statically loaded age-based standard deviation matrix to output a normalized percentile score instantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge of Shareable Results Without a Database
&lt;/h2&gt;

&lt;p&gt;If there is no database storing the results, how can a user share their unique score page with a friend? &lt;/p&gt;

&lt;p&gt;I solved this by using high-entropy URL state encoding. When a user completes a test, the scoring engine compiles their performance vector, compresses it using a lightweight LZW compression algorithm, and serializes it into a Base64-like URL token:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://quizvex.com/results/mbti?data=e30xNDIsLTEyLDM0fQ==&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When the &lt;code&gt;/results&lt;/code&gt; route loads, the client-side router decompresses the token, hydrates the state vector, and renders the custom SVG charts on the fly. No read queries, no database latency, and absolute privacy for the user.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping CLS at Absolute Zero
&lt;/h2&gt;

&lt;p&gt;Because quizzes involve constant DOM updates as users transition from question to question, Cumulative Layout Shift (CLS) was a major concern. To prevent layout jumps, the question container uses a fixed-aspect-ratio CSS Grid container with hardware-accelerated CSS transitions for slide-in animations. This guarantees a smooth 60fps experience even on low-end mobile devices.&lt;/p&gt;

&lt;p&gt;I’d love to hear your thoughts on this stateless approach. How do you handle complex scoring algorithms without bloating your backend? Let's discuss in the comments!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>serverless</category>
      <category>jamstack</category>
    </item>
    <item>
      <title>Bayesian math is hard, so I built a zero-database A/B test &amp; conversion calculator</title>
      <dc:creator>ludy.dev</dc:creator>
      <pubDate>Tue, 23 Jun 2026 05:17:52 +0000</pubDate>
      <link>https://dev.to/lyyluca/bayesian-math-is-hard-so-i-built-a-zero-database-ab-test-conversion-calculator-3ng7</link>
      <guid>https://dev.to/lyyluca/bayesian-math-is-hard-so-i-built-a-zero-database-ab-test-conversion-calculator-3ng7</guid>
      <description>&lt;h2&gt;
  
  
  Keeping the UI Fast
&lt;/h2&gt;

&lt;p&gt;For the frontend, I went with React and Tailwind CSS. Instead of pulling in heavy charting libraries that bloat the bundle size, I wrote custom lightweight SVG generators for the funnel visualizations. This kept the entire site's initial load size under 45kb gzipped, making it load almost instantly.&lt;/p&gt;

&lt;p&gt;If you are tired of heavy analytics dashboards and just want a fast, clean way to calculate your conversion rates, model your funnels, and test significance, try it out at simplifyconversion.com. I would love to hear your feedback on the math implementation or the UI!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>math</category>
      <category>analytics</category>
    </item>
    <item>
      <title>Building a 10-in-1 Daily Puzzle Hub That Works Offline and Weighs Under 1MB</title>
      <dc:creator>ludy.dev</dc:creator>
      <pubDate>Tue, 23 Jun 2026 05:17:23 +0000</pubDate>
      <link>https://dev.to/lyyluca/building-a-10-in-1-daily-puzzle-hub-that-works-offline-and-weighs-under-1mb-4en2</link>
      <guid>https://dev.to/lyyluca/building-a-10-in-1-daily-puzzle-hub-that-works-offline-and-weighs-under-1mb-4en2</guid>
      <description>&lt;p&gt;By seeding this pseudo-random number generator with the current date, we get consistent daily boards globally without a single API request.&lt;/p&gt;

&lt;h2&gt;
  
  
  True Offline Support with Workbox
&lt;/h2&gt;

&lt;p&gt;To make the app work offline, I configured Vite's PWA plugin with a custom Workbox Service Worker strategy. &lt;/p&gt;

&lt;p&gt;We aggressive-cache all essential game assets (HTML, CSS, JS, and local dictionary modules). Since the daily game configurations are generated programmatically via the local date seed, users can play the current day's puzzles in the middle of a flight or deep inside a subway tunnel without losing their progress. Game states and daily streaks are automatically serialized and synced to &lt;code&gt;localStorage&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Check out the live build at &lt;a href="https://puzzleboxs.com" rel="noopener noreferrer"&gt;https://puzzleboxs.com&lt;/a&gt;, try turning off your network connection, and let me know what you think of the performance and offline synchronization!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>pwa</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Building a distraction-free poetry database that scores 100 on PageSpeed (No bloat, just beautiful layouts)</title>
      <dc:creator>ludy.dev</dc:creator>
      <pubDate>Tue, 23 Jun 2026 05:17:08 +0000</pubDate>
      <link>https://dev.to/lyyluca/building-a-distraction-free-poetry-database-that-scores-100-on-pagespeed-no-bloat-just-beautiful-nbe</link>
      <guid>https://dev.to/lyyluca/building-a-distraction-free-poetry-database-that-scores-100-on-pagespeed-no-bloat-just-beautiful-nbe</guid>
      <description>&lt;p&gt;By parsing this with a customized unified/remark pipeline, I preserved standard line-breaks using CSS &lt;code&gt;white-space: pre-wrap&lt;/code&gt; on the container elements. This ensures that the delicate, visual spacing of poets like Walt Whitman or William Carlos Williams renders exactly as intended on both desktop and mobile screens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Achieving 100/100 PageSpeed
&lt;/h2&gt;

&lt;p&gt;To give students and writers a fast, distraction-free environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static Generation&lt;/strong&gt;: Every page is pre-rendered at build time. No database queries on runtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind CSS&lt;/strong&gt;: Using utility-first CSS keeps the global stylesheet footprint under 6KB.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero Bloat&lt;/strong&gt;: Swapped heavy tracker scripts for privacy-first, lightweight analytics.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'd love to hear your thoughts on how you handle preserving formatting for sensitive text structures. Check out the live build at &lt;a href="https://poemexamples.com/" rel="noopener noreferrer"&gt;poemexamples.com&lt;/a&gt; and let me know what you think of the performance!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>css</category>
      <category>jamstack</category>
    </item>
    <item>
      <title>I built a 3D printing parameter optimizer using Next.js and WebAssembly</title>
      <dc:creator>ludy.dev</dc:creator>
      <pubDate>Tue, 23 Jun 2026 05:16:30 +0000</pubDate>
      <link>https://dev.to/lyyluca/i-built-a-3d-printing-parameter-optimizer-using-nextjs-and-webassembly-2i7m</link>
      <guid>https://dev.to/lyyluca/i-built-a-3d-printing-parameter-optimizer-using-nextjs-and-webassembly-2i7m</guid>
      <description>&lt;p&gt;This keeps the main bundle small while enabling powerful computational modeling on the client. &lt;/p&gt;

&lt;p&gt;I'd love to hear your feedback on the architecture, especially if you've done client-side ML in Next.js before!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>3dprinting</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Building a 100% Client-Side PDF Merger: How I Bypassed Server-Side Processing for Ultimate Privacy</title>
      <dc:creator>ludy.dev</dc:creator>
      <pubDate>Tue, 23 Jun 2026 05:06:01 +0000</pubDate>
      <link>https://dev.to/lyyluca/building-a-100-client-side-pdf-merger-how-i-bypassed-server-side-processing-for-ultimate-privacy-1ida</link>
      <guid>https://dev.to/lyyluca/building-a-100-client-side-pdf-merger-how-i-bypassed-server-side-processing-for-ultimate-privacy-1ida</guid>
      <description>&lt;p&gt;We have all been there. You need to combine three PDFs for a tax filing or a job application, so you search for a quick tool online. You end up uploading sensitive documents containing your SSN, address, or financial history to a mysterious, ad-ridden server. &lt;/p&gt;

&lt;p&gt;As a developer, this always rubbed me the wrong way. Why do we need to send megabytes of personal data over the wire just to append a few byte streams together? The answer is: we don't. &lt;/p&gt;

&lt;p&gt;I set out to build a completely free, zero-registration PDF merger that does 100% of the heavy lifting right inside the user's browser. No backend APIs, no remote servers, and absolutely zero data leaks. Here is how I did it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fknc3ww1xb1lxkudwgx7s.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fknc3ww1xb1lxkudwgx7s.jpg" alt="Featured Image" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tech Stack: Running it All in the Browser
&lt;/h2&gt;

&lt;p&gt;To achieve zero-server processing, I needed a library that could parse, modify, and serialize PDF documents completely on the client side. I chose &lt;code&gt;pdf-lib&lt;/code&gt; due to its robust API and active ecosystem.&lt;/p&gt;

&lt;p&gt;Unlike traditional server-side rendering tools (like PDFKit or standard CLI tools), &lt;code&gt;pdf-lib&lt;/code&gt; allows us to load PDFs as binary &lt;code&gt;ArrayBuffer&lt;/code&gt; data arrays directly in the browser's memory space.&lt;/p&gt;

&lt;p&gt;Here is the high-level architecture of the merge process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user drags and drops their files.&lt;/li&gt;
&lt;li&gt;The browser reads the files as &lt;code&gt;ArrayBuffer&lt;/code&gt; using the HTML5 &lt;code&gt;FileReader&lt;/code&gt; API.&lt;/li&gt;
&lt;li&gt;We instantiate a new &lt;code&gt;PDFDocument&lt;/code&gt; in memory.&lt;/li&gt;
&lt;li&gt;We loop through each uploaded file, load it via &lt;code&gt;pdf-lib&lt;/code&gt;, copy the pages, and add them to the main document.&lt;/li&gt;
&lt;li&gt;The combined PDF is serialized back into a &lt;code&gt;Uint8Array&lt;/code&gt; and instantly triggered as a local browser download.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Overcoming Browser Constraints
&lt;/h2&gt;

&lt;p&gt;While client-side processing is incredible for privacy, it comes with a major bottleneck: browser memory limits. &lt;/p&gt;

&lt;p&gt;If a user tries to merge five 50MB PDFs on a low-end mobile device, the browser tab will easily crash due to out-of-memory (OOM) errors. &lt;/p&gt;

&lt;p&gt;To solve this, I implemented several optimizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Garbage Collection Optimization&lt;/strong&gt;: Explicitly dereferencing massive arrays and forcing garbage collection paths.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asynchronous Chunking&lt;/strong&gt;: Processing page copying in sequential chunks rather than all at once, preventing the UI thread from freezing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On-the-Fly Compression&lt;/strong&gt;: Strip out unnecessary metadata and duplicate font definitions that often bloat merged files.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;The result of this weekend project is pdfmergeapp.com. It is incredibly fast because there is zero network latency for uploads or downloads. Best of all, if you inspect the network tab while using it, you will see exactly zero outbound requests containing your document data. &lt;/p&gt;

&lt;p&gt;I’d love to hear your thoughts on optimization tricks for handling even larger files (100MB+) purely in the browser. Have you experimented with WebAssembly or Web Workers for client-side file manipulation? Let’s chat in the comments!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>security</category>
      <category>webdev</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Programmatic SEO without the bloat: Building a 500+ page static resource hub with Astro</title>
      <dc:creator>ludy.dev</dc:creator>
      <pubDate>Tue, 23 Jun 2026 05:05:09 +0000</pubDate>
      <link>https://dev.to/lyyluca/programmatic-seo-without-the-bloat-building-a-500-page-static-resource-hub-with-astro-43n0</link>
      <guid>https://dev.to/lyyluca/programmatic-seo-without-the-bloat-building-a-500-page-static-resource-hub-with-astro-43n0</guid>
      <description>&lt;p&gt;At build time, Astro parses the JSON array, generates static HTML files for all 500+ routes, and writes them straight to the disk. &lt;/p&gt;

&lt;h2&gt;
  
  
  Overcoming the Build-Time Bottleneck
&lt;/h2&gt;

&lt;p&gt;When you generate hundreds of pages programmatically, asset optimization can slow down your builds significantly. Initially, my build times on Cloudflare Pages were dragging towards the 3-minute mark because of dynamic image optimization and massive CSS parsing per page.&lt;/p&gt;

&lt;p&gt;I solved this by:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Standardizing layout components to prevent style duplication.&lt;/li&gt;
&lt;li&gt;Relying on Tailwind's JIT compiler to keep the global CSS payload under 15kb.&lt;/li&gt;
&lt;li&gt;Pre-indexing the templates into a lightweight local JSON search index so users can query jobs instantaneously without a heavy search engine backend.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The result? The entire project builds in under 22 seconds, scores a perfect 100/100 on Lighthouse desktop performance, and serves instantly to users who just want to grab a template and apply for their next gig.&lt;/p&gt;

&lt;p&gt;Check out the live site at &lt;a href="https://mycoverletter.org" rel="noopener noreferrer"&gt;mycoverletter.org&lt;/a&gt; and let me know what you think of the speed! I'd love to hear your feedback on the UI or how I can optimize the static build pipeline even further.&lt;/p&gt;

</description>
      <category>astro</category>
      <category>webdev</category>
      <category>performance</category>
      <category>jamstack</category>
    </item>
    <item>
      <title>Building a 100% Client-Side JPG to PDF Converter (And Why I Skipped the Backend)</title>
      <dc:creator>ludy.dev</dc:creator>
      <pubDate>Tue, 23 Jun 2026 05:04:54 +0000</pubDate>
      <link>https://dev.to/lyyluca/building-a-100-client-side-jpg-to-pdf-converter-and-why-i-skipped-the-backend-1861</link>
      <guid>https://dev.to/lyyluca/building-a-100-client-side-jpg-to-pdf-converter-and-why-i-skipped-the-backend-1861</guid>
      <description>&lt;p&gt;This reduced the final PDF file size by up to 75% without noticeable loss in document readability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Auto-Fitting to Standard Page Sizes
&lt;/h2&gt;

&lt;p&gt;Calculating the correct scaling factors for arbitrary image ratios to fit beautifully onto A4 pages was a fun math challenge. The tool detects whether the image is landscape or portrait, sets the PDF page orientation dynamically, and computes the margins so that the image is perfectly centered without clipping.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hosting &amp;amp; Zero Overhead
&lt;/h2&gt;

&lt;p&gt;The site is hosted on Cloudflare Pages because the entire app is just static JS, HTML, and Tailwind CSS. The running cost is practically $0/month, and it can scale to millions of users without any server overhead.&lt;/p&gt;

&lt;p&gt;If you want to convert some images securely, give it a spin at &lt;a href="https://jpgtopdfweb.com" rel="noopener noreferrer"&gt;jpgtopdfweb.com&lt;/a&gt;. I'd love to get your feedback on the client-side performance!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>privacy</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Building a static repository for print-perfect PDFs</title>
      <dc:creator>ludy.dev</dc:creator>
      <pubDate>Wed, 17 Jun 2026 07:20:28 +0000</pubDate>
      <link>https://dev.to/lyyluca/building-a-static-repository-for-print-perfect-pdfs-27p8</link>
      <guid>https://dev.to/lyyluca/building-a-static-repository-for-print-perfect-pdfs-27p8</guid>
      <description>&lt;p&gt;Most print-ready websites are slow, bloated, and covered in ads. I wanted to build a clean directory for paper templates that loads instantly and prints perfectly.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://printablecove.com/" rel="noopener noreferrer"&gt;PrintableCove&lt;/a&gt; to solve this. &lt;/p&gt;

&lt;p&gt;The tech stack is lightweight: Astro for generating static pages and Tailwind CSS for styling. The major technical challenge was ensuring that the PDF files and print stylesheets rendered exactly to scale. When dealing with graph paper or lined paper, a millimeter deviation on screen can ruin the physical print grid. &lt;/p&gt;

&lt;p&gt;To solve this, I designed the PDF templates directly using vector exports to guarantee clean scaling at 300 DPI on standard Letter and A4 sizes. I also implemented CSS &lt;code&gt;@media print&lt;/code&gt; rules on the web previews to hide layout grids and menus, allowing users to print directly from the browser window if they choose not to download the PDF. &lt;/p&gt;

&lt;p&gt;Hosting static assets on a global CDN means the site loads in under 200ms anywhere in the world. No databases, no dynamic server lag, just clean vector resources ready for the physical world.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>showdev</category>
      <category>performance</category>
    </item>
    <item>
      <title>I built a fast, static template library for small businesses using Astro and Tailwind</title>
      <dc:creator>ludy.dev</dc:creator>
      <pubDate>Sat, 13 Jun 2026 14:37:04 +0000</pubDate>
      <link>https://dev.to/lyyluca/i-built-a-fast-static-template-library-for-small-businesses-using-astro-and-tailwind-2193</link>
      <guid>https://dev.to/lyyluca/i-built-a-fast-static-template-library-for-small-businesses-using-astro-and-tailwind-2193</guid>
      <description>&lt;p&gt;I recently needed a clean, standard profit and loss template for a side project. After clicking through dozens of template sites that forced me to register or sign up for a trial, I got annoyed enough to build my own open directory of document templates.&lt;/p&gt;

&lt;p&gt;I wanted the site to be incredibly fast, simple, and require zero database overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tech Stack
&lt;/h2&gt;

&lt;p&gt;I chose Astro for this project because it is perfect for content-focused websites. Since the templates themselves (Excel, Word, and Google Sheets files) are static assets, there was no need for a dynamic backend. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Framework&lt;/strong&gt;: Astro (SSG mode)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styling&lt;/strong&gt;: Tailwind CSS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment&lt;/strong&gt;: Cloudflare Pages for global low-latency delivery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using Astro allowed me to keep the JavaScript footprint at absolute zero on the client side. The templates are organized using Astro's content collections, which makes managing metadata for each template type (like category, file formats, and download links) highly structured and type-safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling File Downloads Efficiently
&lt;/h2&gt;

&lt;p&gt;Instead of hosting download files on a heavy cloud storage bucket, I opted to bundle them directly into the static build assets directory. This keeps the download speed high and costs at zero. &lt;/p&gt;

&lt;p&gt;For Google Sheets templates, instead of direct file downloads, the site provides a pre-formatted template copy link (&lt;code&gt;/copy&lt;/code&gt; endpoint pattern) which prompts the user to make a clean copy directly in their own Google Drive workspace, avoiding any permission sharing issues.&lt;/p&gt;

&lt;p&gt;If you want to check out the design or grab some clean files for your own business operations, you can visit &lt;a href="https://bizkitly.com" rel="noopener noreferrer"&gt;BizKitly&lt;/a&gt;. I would love to hear your feedback on the layout and site performance.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>showdev</category>
      <category>astro</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>How I Compiled 30-Year-Old Console Emulators to WebAssembly to Play 3,000+ Retro Games in the Browser</title>
      <dc:creator>ludy.dev</dc:creator>
      <pubDate>Sat, 13 Jun 2026 04:51:20 +0000</pubDate>
      <link>https://dev.to/lyyluca/how-i-compiled-30-year-old-console-emulators-to-webassembly-to-play-3000-retro-games-in-the-3i4j</link>
      <guid>https://dev.to/lyyluca/how-i-compiled-30-year-old-console-emulators-to-webassembly-to-play-3000-retro-games-in-the-3i4j</guid>
      <description>&lt;p&gt;I’ve always had a massive soft spot for retro games. There’s something magical about the 8-bit and 16-bit eras of FC (NES), SFC (SNES), GBA, and classic arcade games. But modern emulation is surprisingly fragmented. You have to download native apps, hunt down sketchily hosted ROMs, configure controller mappings, and hope you don't download a Trojan in the process.&lt;/p&gt;

&lt;p&gt;I wanted to change that. I thought: modern browsers are basically lightweight operating systems. Why not bring the entire console library to the web? &lt;/p&gt;

&lt;p&gt;So, I built &lt;a href="https://laowanke.com/" rel="noopener noreferrer"&gt;laowanke.com&lt;/a&gt;—a zero-download, instant-play nostalgic gaming platform running over 3,000+ retro games directly in the browser. Here is how I pulled off the engineering under the hood.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97rnue40v1o6zlioe722.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97rnue40v1o6zlioe722.jpg" alt="Featured Image" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tech Stack: Porting C/C++ Cores to WebAssembly
&lt;/h2&gt;

&lt;p&gt;The absolute backbone of this project is WebAssembly (Wasm). Instead of writing emulation engines from scratch in JavaScript (which would be painfully slow and inaccurate), I leveraged legendary open-source C/C++ emulation cores (like retroarch/libretro projects) and compiled them using &lt;strong&gt;Emscripten&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By compiling these mature codebases to Wasm, I achieved near-native execution speed. The browser runs the game loops, processes CPU/GPU instructions of these vintage consoles, and pipes the video/audio output directly to a &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element and the Web Audio API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solving the Real-time Save State Challenge
&lt;/h2&gt;

&lt;p&gt;One of the biggest hurdles was managing save states. Classic game cartridges used battery-backed RAM (SRAM) to save progress, while modern emulators use state snapshots (save states). &lt;/p&gt;

&lt;p&gt;To make this feel like a modern cloud gaming experience, I had to map the Wasm virtual file system to the browser's persistent storage. I implemented a hybrid storage system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IndexedDB&lt;/strong&gt; handles local persistence for auto-saves and manual save slots. It operates asynchronously, so I had to write a JS wrapper that hooks into the emulator's save state cycle without blocking the main rendering thread.&lt;/li&gt;
&lt;li&gt;If a player logs in, these IndexedDB blobs are synced to a lightweight backend database, letting them resume their Pokémon GBA run on their phone right where they left off on their desktop.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Taming Audio Latency and Input Lag
&lt;/h2&gt;

&lt;p&gt;In retro action games, a 50ms delay in button inputs or audio sync makes the game completely unplayable. &lt;/p&gt;

&lt;p&gt;To solve input lag, I bypassed the standard browser keyboard events wherever possible and used the &lt;strong&gt;Gamepad API&lt;/strong&gt; with a high-frequency polling loop mapped directly to the Wasm input registers. For audio, standard HTML5 Audio wasn't fast enough, so I implemented a dynamic audio buffer using the &lt;strong&gt;Web Audio API AudioWorklet&lt;/strong&gt;. The Worklet pulls raw PCM audio data directly from the Wasm memory space in real-time, completely eliminating crackling and latency.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Right now, the platform supports keyboard controls, gamepads, save/load states, and a smooth catalog search UI. Next, I'm working on stabilizing WebRTC-based netplay so two players can play cooperative arcade games across different networks.&lt;/p&gt;

&lt;p&gt;I’d love to get your thoughts on the performance and latency. Give it a spin at &lt;a href="https://laowanke.com/" rel="noopener noreferrer"&gt;laowanke.com&lt;/a&gt; and let me know how it handles on your machines!&lt;/p&gt;

</description>
      <category>webassembly</category>
      <category>javascript</category>
      <category>retro</category>
      <category>gaming</category>
    </item>
  </channel>
</rss>
