Krasimir Tsonev - blog http://krasimirtsonev.com/blog Blog for web development <![CDATA[Reactive UI in 10 lines of code]]> https://krasimirtsonev.com/blog/article/reactive-ui-in-10-lines-of-code Reactivity became de-factor a standard in the last couple of years. All the major frameworks have some reactivity model implemented. One of the biggest even has the name React. In this article, we'll see how to write a simple reactive UI with just a few lines of JavaScript.

]]>
Sun Feb 11 2024 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/reactive-ui-in-10-lines-of-code
<![CDATA[Write your own progress indicator with vanilla JavaScript]]> https://krasimirtsonev.com/blog/article/progress-indicator-with-vanilla-javascript Many moons ago, I was writing a lot of Flash applications. One thing was typical, and that was a progress indication of something that we were downloading. The loaded bytes of the Flash file (.swf) itself and later of some other resource the application needs. Once I started writing everything in JavaScript, this feature disappeared. In this post, we'll see how to implement it with vanilla JavaScript.

]]>
Sat Sep 16 2023 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/progress-indicator-with-vanilla-javascript
<![CDATA[A short introduction to CSS nesting]]> https://krasimirtsonev.com/blog/article/short-intro-to-css-nesting I did use Sass and Less in the past, and one of my favorite features was the nesting. Not only me but the whole community was asking about that constantly over the years. The browser vendors heard that plea, and today, we have CSS nesting.

]]>
Sat Sep 16 2023 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/short-intro-to-css-nesting
<![CDATA[I've made an Express.js based source viewer]]> https://krasimirtsonev.com/blog/article/expressjs-source-viewer It's unsurprising that we all use Express.js when we need a web server. In this article, I'll show you how I built a source viewer. It's distributed as a npm package view-source and it could render the content of a directory in a nice tree-view style.

]]>
Mon Aug 07 2023 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/expressjs-source-viewer
<![CDATA[q2m - a library for translating URL params to MongoDB query]]> https://krasimirtsonev.com/blog/article/url-query-string-to-mongodb-query I'm not open-sourcing very often anymore, but recently I finished developing a small tool called q2m that I believe is worth sharing. It's a library designed to convert URL parameters into MongoDB queries, which I needed for my latest project, a little SaaS called Lumina CMS.

]]>
Mon Jul 03 2023 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/url-query-string-to-mongodb-query
<![CDATA[AI driven open source library for measuring your web page carbon footprint]]> https://krasimirtsonev.com/blog/article/ai-driven-open-source Some people say that 2023 will be the year of AI. With tools like ChatGPT and DALL·E the world is definitely changing. There are different opinions on how such instruments will affect the everyday tasks of the professionals. My two cents (for now) are that those are just tools to achieve what we want quicker and more efficiently. Who knows, someday I may call myself a "prompt engineer". For the time being, though, I'm still writing a lot of stuff alone and occasionally ask ChatGPT for help.

]]>
Sat Jan 14 2023 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/ai-driven-open-source
<![CDATA[Anchor links pointing to a fragment fires History API's "popstate" event]]> https://krasimirtsonev.com/blog/article/anchor-links-and-popstate I hit an interesting "bug" while working on a SPA application. Clicking an anchor link that points to a fragment on the page fires the History API's popstate event. This triggers some logic on my end, which was not my intent. I fixed that with a bit of JavaScript, and I had to share the snippet.

]]>
Tue Nov 15 2022 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/anchor-links-and-popstate
<![CDATA[Using web dev skills to test web dev skills]]> https://krasimirtsonev.com/blog/article/using-web-dev-skills-to-test-web-dev-skills Last year or so, I worked on a platform where I would publish video courses. The first one is on web fundamentals (in Bulgarian), and it's almost ready. You can check it out here. But this article is not about that. It's about a platform feature I built - an in-house validator to exercise the gained HTML, CSS, and JavaScript knowledge. After each lesson, I give a task to the students, and they can work on it right in the browser. The small application became an inspiration for another project - iloveweb.dev. So, I decided to share how the validation works.

]]>
Sun Oct 30 2022 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/using-web-dev-skills-to-test-web-dev-skills
<![CDATA[Taking Wordle to the next level (case study)]]> https://krasimirtsonev.com/blog/article/taking-wordle-to-the-next-level I'm sure you know what Wordle is. The game got a lot of traction a couple of months ago when The New York Times bought it. I was playing it too, so I decided to create my version in my native language (Bulgarian). This is how duma.fun was born (in Bulgarian duma means word). And as usually happens with my "little" experiments, I didn't stop at just implementing the basics. I managed to translate the initial ~300 lines of code into a three months-long project. Here's why, what, and how.

]]>
Mon Apr 04 2022 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/taking-wordle-to-the-next-level
<![CDATA[The tiniest presentation framework]]> https://krasimirtsonev.com/blog/article/the-tiniest-presentation-framework I did roughly 50 talks over the years, and for almost all of them, I used Reveal.js. I like it because it's HTML-based. I have complete control of everything and can easily publish the slides online. However, one thing bugs me every single time - the size of my content. I want to use all the available space. This becomes very important when I'm showing code to people. That's why I wrote SimPre. It's a 10KB HTML presentation framework that properly scales and positions my content.

]]>
Sun Mar 06 2022 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/the-tiniest-presentation-framework
<![CDATA[13 Years of Blogging]]> https://krasimirtsonev.com/blog/article/13-years-of-blogging I'm committing to posting a report at the end of each year. A report about this blog. I did the last one five years ago when this place was eight years old.

]]>
Fri Dec 31 2021 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/13-years-of-blogging
<![CDATA[How I wrote and published my 5th technical book]]> https://krasimirtsonev.com/blog/article/how-to-write-a-book-on-amazon I like to write. It's not happening often, but I do. A couple of weeks ago, I finally finished my 5th book, "50 Tips on JavaScript". I decided to use Amazon as a distributing mechanism. In this article, I'm sharing my journey. From the idea, through the writing and the publishing.

]]>
Sun Dec 19 2021 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/how-to-write-a-book-on-amazon
<![CDATA[TAMO JUNTO - Animated Short Film]]> https://krasimirtsonev.com/blog/article/tamo-junto Tamo Junto is an independent animated short film by flooul animation. 2 neighbors lean on each other, turning small moments of life into great treasures. Voices by Criolo, Luciana Silveira and Emicida. Original Soundtrack By Loud+

]]>
Thu Dec 16 2021 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/tamo-junto
<![CDATA[Here is how call-to-action widgets probably work]]> https://krasimirtsonev.com/blog/article/how-widgets-probably-work Did you ever wondered how the call-to-action widgets work? You know, those little buttons for sharing content in the social networks. Very often they are distributed as iframes but sometimes we have to copy/paste script tags. And the instructions are "Place the following code where you want the button to appear". But if that's a script tag how it knows where to inject the button? The goal of this article is to give you an answer on this question.

]]>
Tue Oct 26 2021 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/how-widgets-probably-work
<![CDATA[Get to know Kent C. Dodds]]> https://krasimirtsonev.com/blog/article/get-to-know-kent-c-dodds A short movie for Kent C. Dodds.

]]>
Tue Oct 05 2021 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/get-to-know-kent-c-dodds
<![CDATA[White-labeling React apps]]> https://krasimirtsonev.com/blog/article/whitelabel-react-apps A white label app is an app that we build once and "resell" it to other people/companies. Very often we are talking about applying different themes but sometimes we have to change logic too. Such changes should be as declarative as possible so they scale well. Otherwise is more of a copy/paste exercise. In this article I want to sketch out a couple of approaches for white labeling in React applications.

]]>
Mon Aug 16 2021 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/whitelabel-react-apps
<![CDATA[Firebase/GCP: save money by cleaning up your artifacts]]> https://krasimirtsonev.com/blog/article/firebase-gcp-saving-money I'm working on a personal project and I'm using the awesome Google Cloud Platform. There are so many things that you can do. All the tools that you may need are probably there. This of course comes with a price. In this article I'll share a tip how to reduce your spendings there.

]]>
Sun Jun 06 2021 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/firebase-gcp-saving-money
<![CDATA[Using JavaScript module system for state management]]> https://krasimirtsonev.com/blog/article/javascript-module-system-for-state-management Hot topic last couple of years is state management. Especially in the front-end apps. There are lots of problems and lots of solutions. One thing thought is totally ignored in this context - the JavaScript module system. I'm very often reaching out to this approach and decided to share it here.

]]>
Mon Mar 08 2021 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/javascript-module-system-for-state-management
<![CDATA[Miss Piggy - a test runner for Puppeteer]]> https://krasimirtsonev.com/blog/article/miss-piggy-puppeteer-test-runner These days I did (again) a bunch of changes in Google tag manager. This time however was more of a refactoring exercise. So, I had to prove that the tags that were placed before the refactoring exist after the refactoring. And what we programmers do in such cases - we write tests.

]]>
Mon Feb 01 2021 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/miss-piggy-puppeteer-test-runner
<![CDATA[Configure Google domain email in Vercel with ImprovMX]]> https://krasimirtsonev.com/blog/article/configure-google-domain-email-in-vercel-with-improvmx Back in February last year I blog on topic Email not working after DNS change. Well, I had kinda similar situation but not exactly. This time I bought a domain from Google and wanted to use an email with it. The setup wasn't obvious for me so I decided to document the process.

]]>
Wed Jan 27 2021 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/configure-google-domain-email-in-vercel-with-improvmx
<![CDATA[Reinventing the routing in React apps]]> https://krasimirtsonev.com/blog/article/reinventing-routing-in-react-apps The router is the backbone of your application. Trust me, that's how it is and I can prove it. One of the fundamental ideas in Web is the URL (Uniform Resource Locator). Or the way of how we very often call it - "web address". No mather what you are building there is a web address which identifies your resource. The router is the front office that accepts the request to particular URL and wires it to a logic. Logic for generating HTML or JSON response or something else. So, the router is very important part of your system.

At the end of last year I rewrote one of my favorite projects - a vanilla JS router called Navigo. I was procrastinating this work for years. Finally I did it in TypeScript and wrote 100+ unit tests along the way. This refactoring opens the door for new features and more importantly, for integrating the library into other places. Like React for example.

]]>
Mon Jan 18 2021 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/reinventing-routing-in-react-apps
<![CDATA[Transpile to ES modules with Babel]]> https://krasimirtsonev.com/blog/article/transpile-to-esm-with-babel While I was working on Navigo an issue popped out. It was about using the library in the context of Web Dev Server where we have everything in TypeScript. And something was not ok with Navigo. The npm package wasn't exported properly and we were keep getting a does not provide an export named 'default' error. It turned out the problem is that Navigo is not exported properly as ES module (also known as ESM).

]]>
Thu Jan 14 2021 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/transpile-to-esm-with-babel
<![CDATA[Mocking console methods with Jest]]> https://krasimirtsonev.com/blog/article/jest-mock-console-methods I'm recently working on two OS libraries. Both I'm unit testing with Jest. There is some logic that leads to a warning which I'm doing with console.warn. In the unit tests this is happening quite often so I want to suppress it. Also I want to verify that it happens on the right place.

]]>
Fri Jan 01 2021 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/jest-mock-console-methods
<![CDATA[Copy files and directories from and to Kubernetes pods]]> https://krasimirtsonev.com/blog/article/copy-from-and-to-k8s-pods At work we have a project that uses node:10-jessie image as a base for its docker container. That image has no vi inside so I wondered how to check the content of a file. Luckily kubectl has a neat command to copy files from and to a pod.

]]>
Fri Dec 11 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/copy-from-and-to-k8s-pods
<![CDATA[Replacing code for production with Babel transformation]]> https://krasimirtsonev.com/blog/article/replacing-code-for-production-with-babel-transformation If you are building some sort of an app, Babel is probably part of your build system. It is that thing which converts our fancy code to valid, working in a browser, JavaScript. Just recently at work I had to design a solution that swaps a class based on the environment. Or in another words, we have logic that should not reach our users. The file should be available locally and on our staging environment but not in production. A tiny Babel plugin was the cheapest solution for me so I decided to share the result.

]]>
Sun Nov 29 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/replacing-code-for-production-with-babel-transformation
<![CDATA[iPhone stuck on the Apple logo]]> https://krasimirtsonev.com/blog/article/iphone-wont-start Last weekend I was helping a friend to deal with his "broken" iPhone XR. It was stuck on the Apple logo. No mather what we do the phone was just black and the apple shows up.

]]>
Fri Nov 27 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/iphone-wont-start
<![CDATA[Transfer MP3 file from Mac OS Catalina to iPhone iOS 14.0]]> https://krasimirtsonev.com/blog/article/mp3-mac-catalina-to-iphone-ios14 I did transfer MP3 files from my mac to my iPhone three times and every time I'm forgetting how it actually works. So I decided to document the process into a blog post.

]]>
Fri Sep 18 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/mp3-mac-catalina-to-iphone-ios14
<![CDATA[What the heck is Google Tag Manager and what it has to do with Google Analytics]]> https://krasimirtsonev.com/blog/article/google-tag-manager-and-google-analytics Just recently I had to do changes in Google Tag Manager at work. It's interesting how I keep forgetting how everything works. So I finally decided to sit down and write an article about these things. If nothing else I will have a good memory snapshot to remind me what is what.

]]>
Sun Sep 13 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/google-tag-manager-and-google-analytics
<![CDATA[You Really Don't Need All That JavaScript, I Promise by Stuart Langridge]]> https://krasimirtsonev.com/blog/article/you-really-dont-need-all-that-javascript JavaScript is your behavior layer; the way to add interactivity to your sites, to provide a slick and delightful user experience, to make everything fast and easy and clean. But at some point everything changed: the tail started to wag the dog instead and development became JavaScript-first.

]]>
Sat Sep 12 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/you-really-dont-need-all-that-javascript
<![CDATA[ReactNative: using SVG as a button]]> https://krasimirtsonev.com/blog/article/react-native-svg-as-button Just recently I started using ReactNative. I've been using React for years but this thing is a whole new world. There are tons of basic stuff which I don't know how to do. Using an SVG as a button is one of them. Find my solution below and expect more short #reactnative blog post soon.

]]>
Mon Sep 07 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/react-native-svg-as-button
<![CDATA[React: 50 shades of state]]> https://krasimirtsonev.com/blog/article/react-50-shades-of-state We all know that one of the most challenging task in software development is state management. This is especially true for the JavaScript world. There are thousands of articles on this topic and so I decided to write another one 😁. I wanted to share my current thoughts on the different state types. I found that answering "What lives where?" question is far more important than the actual state management. Which more or less is an implementation detail.

]]>
Tue Jul 21 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/react-50-shades-of-state
<![CDATA[Recreating Facebook's Recoil library]]> https://krasimirtsonev.com/blog/article/recreating-facebooks-recoil This weekend I decided to play with the new kid on the block - Facebook's Recoil library for managing state. I did the trivial counter example to see how it works. It's pretty simple idea so I wondered how much it takes to replicate its features. I found the exact answer - 70 lines of code. Obviously, my implementation didn't cover everything but it was fun so I decided to share my findings.

(A side note: I did not look at the code of Recoil. I didn't want to be bias on how to write my version.)

]]>
Sun Jul 12 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/recreating-facebooks-recoil
<![CDATA[A journey into software development with Lea Verou]]> https://krasimirtsonev.com/blog/article/lea-verou Lea Verou, known in the community as the "Queen of CSS", shares her personal story about how she became a web developer. She discusses how her passion for computers began in her childhood and her dream of living outside Greece.

]]>
Fri Jun 05 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/lea-verou
<![CDATA[The simplest HTTP proxy with custom headers]]> https://krasimirtsonev.com/blog/article/http-proxy-headers-with-node These days I had an interesting problem to solve. At work, on our staging environment, we have basic authorization. It works really well but for some older versions of Chrome we experienced a weird issue. The browser did not pass the authorization header. The app runs fine but as soon as it does a fetch request to a local endpoint the request fails with 401 not-authorized error. In the modern browsers that's not happening because the browser kinda knows that we came here with basic auth and automatically includes authorization: basic ... header.

]]>
Wed May 06 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/http-proxy-headers-with-node
<![CDATA[Smart placeholders in your markdown]]> https://krasimirtsonev.com/blog/article/markdown-smart-placeholders I ❤️ markdown. I like its simplicity and minimalistic API which is good enough to cover most of needed HTML markup. At least for textual content. At work we have a small node based microservice that delivers data from Contentful in exactly markdown format. It's all working well but we started having cases where part of the text is in Contentful and the other part is in that microservice. For example when we have a button with a catchy design. We want to content manage the label of the button but the actual markup to be on our side.

]]>
Wed May 06 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/markdown-smart-placeholders
<![CDATA[How Open Source Changed My Life with Max Stoiber]]> https://krasimirtsonev.com/blog/article/max-stoiber We spent a day with Open Source-“Wunderkind” Max Stoiber in Vienna. Despite his young age of only 23, Max has achieved incredible things: he's created react-boilerplate and styled-components, his start-up, Spectrum, was recently acquired by GitHub and he gives talks all over the world. Learn more about his journey - and how he dropped out of university (twice!) - in this mini-doc.

]]>
Tue Apr 28 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/max-stoiber
<![CDATA[Create your own Covid-19 data tracker]]> https://krasimirtsonev.com/blog/article/how-to-create-your-own-covid-19-data-tracker I'm continuing to experiment with React and TypeScript. The weekend-long project this time was a Covid-19 data tracker. In this blog post I will share how I built c19stats.now.sh. I exposed the data as a public API at the same URL. I guess you, as many other people, follow the situation so you may want to glue your fingers on the keyboard and create something useful around the data. I got lots of fun playing with the diagrams.

]]>
Mon Mar 30 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/how-to-create-your-own-covid-19-data-tracker
<![CDATA[NADCAST.24 с Радо Станков]]> https://krasimirtsonev.com/blog/article/nadcast-24-rado-stankov В тези смутни времена се чуваме online с Радо Станков за да си поговорим за remote working. Не че по принцип не се чуваме така, но сега е малко по-различно. В този 24-ти епизод споделяме нашия опит в работа от разстояние. Приятно слушане.

]]>
Thu Mar 26 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/nadcast-24-rado-stankov
<![CDATA[My top 3 tips for working remotely]]> https://krasimirtsonev.com/blog/article/working-remotely-3-top-advices These days working from home is a norm. We all know why. This f.cking virus is all over the globe. I bet there are tons of articles on how to work remotely efficiently but I wanted to give my two cents.

]]>
Fri Mar 20 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/working-remotely-3-top-advices
<![CDATA[Pairify - how to match balanced string pairs]]> https://krasimirtsonev.com/blog/article/pairify-finding-balanced-matches I'm now actively working on a VSCode extension. I started it as a theme but then decided to add some more features. Like for example a tin line on the left side of the editor marking the current function scope. In order to do that I had to analyze the current file's code and find the lines that are included in that scope. The obvious approach will be to translate the code to AST and then traverse the tree finding the information that I need. This however will require the usage of a language server which now I don't want to deal with. So I decided to explore a brute force approach. Looping over the string characters and finding balanced matches. I quickly wrapped it into a library. I called it Pairify. It consumes text and returns an array of pairs. This blog post will show you how it works.

]]>
Wed Mar 11 2020 00:00:00 GMT+0000 (Coordinated Universal Time) https://krasimirtsonev.com/blog/article/pairify-finding-balanced-matches