<?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>Forem: Tom J.</title>
    <description>The latest articles on Forem by Tom J. (@tomj).</description>
    <link>https://forem.com/tomj</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2286323%2Ff49a42d2-8df3-4f33-9de3-9f41d1c57a38.jpg</url>
      <title>Forem: Tom J.</title>
      <link>https://forem.com/tomj</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/tomj"/>
    <language>en</language>
    <item>
      <title>We Will Have 50,000 Jiras and No Better Software</title>
      <dc:creator>Tom J.</dc:creator>
      <pubDate>Wed, 25 Mar 2026 14:53:45 +0000</pubDate>
      <link>https://forem.com/tomj/we-will-have-50000-jiras-and-no-better-software-31l</link>
      <guid>https://forem.com/tomj/we-will-have-50000-jiras-and-no-better-software-31l</guid>
      <description>&lt;p&gt;We are about four years into the new AI era and patterns of the new normal have started to emerge.&lt;/p&gt;

&lt;p&gt;We are seeing enormous amounts of copies of existing software. We are not really seeing software get better.&lt;/p&gt;

&lt;p&gt;Let me start with what could have happened - and then what I actually see happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Could Have Happened
&lt;/h2&gt;

&lt;p&gt;The optimistic version is simple. AI removes the mechanical cost of writing code. The bottleneck shifts from "can we build this" to "what should we build." Developers with real understanding of software - its weight, its tradeoffs, its failure modes - finally have the time and energy to act on that understanding. We get leaner software. Faster software. Software that does not need four layers of abstraction to render a button.&lt;/p&gt;

&lt;p&gt;The idealistic version goes further. The barrier drops low enough that people who understand problems deeply but could not previously build solutions can now build them. Domain knowledge finally beats framework knowledge. We get software shaped by the problem rather than by whatever the developer already knew how to use.&lt;/p&gt;

&lt;p&gt;Both of those versions assume that the constraint was time. That given enough of it, quality would follow.&lt;/p&gt;

&lt;p&gt;Now I don't think that assumption was ever true.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Actually See
&lt;/h2&gt;

&lt;p&gt;Two things are happening, and they look different on the surface but come from the same place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We are building frameworks. And we are building on frameworks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These feel like separate conversations but they belong under the same roof, because most developers live on frameworks - they work inside them, they think in them, they reach for them automatically. Building a new framework is the most natural thing in the world to a developer who has spent years inside existing ones. It is familiar territory expressed as output.&lt;/p&gt;

&lt;p&gt;Cloudflare built a Next.js clone. A working framework, demonstrably impressive, completely unnecessary. Next.js already exists. The world did not need a copy, nor a new framework at all - more on that lower in the article. But it made a great demo, a great blog post, a great proof of capability - and that is the reason.&lt;/p&gt;

&lt;p&gt;This is not a Cloudflare problem. &lt;strong&gt;This is the pattern.&lt;/strong&gt; AI gets aimed at things that look impressive fast, and frameworks look impressive fast because everyone already knows what they are supposed to be.&lt;/p&gt;

&lt;p&gt;Meanwhile, the rest of us are scaffolding new projects on the same foundations as before, just faster. React on Next.js on Node on a managed platform with abstractions on top of abstractions, five levels deep. AI did not make that stack lighter. It just made it faster to assemble. The weight is still there. The failure modes are still there. You just got there quicker.&lt;/p&gt;

&lt;p&gt;Frameworks exist to make writing lines faster and easier. If AI already does that - if that mechanical cost is largely gone - then building more frameworks is answering a question nobody is asking anymore. And building on them at speed is not progress. It is the same decisions, accelerated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frameworks Should Be Obsolete
&lt;/h2&gt;

&lt;p&gt;If you build on a framework, three things happen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You finish your program faster than typing from scratch with zero abstractions already in place.&lt;/li&gt;
&lt;li&gt;Your code runs through another code that calls other functions that run through other classes and methods - which is, of course, visibly slow even on today's 5.5 GHz CPUs, 7000 MT/s RAM and 7500 MB/s SSDs.&lt;/li&gt;
&lt;li&gt;The program has just received a huge amount of attack surface for hacking - which is smarter than ever.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Point one was always the justification for accepting points two and three.&lt;/strong&gt; Speed of development was the trade. You paid with performance and security and got back time.&lt;/p&gt;

&lt;p&gt;AI can change that trade. If writing from scratch is no longer the slow part - if the mechanical cost of building without a framework is largely absorbed by the tool - then you are left with the costs and not much of the benefit. The slow stack. The inherited vulnerabilities. The assumptions baked in by someone else for someone else's problem.&lt;/p&gt;

&lt;p&gt;Frameworks made sense when developer time was the constraint. It increasingly is not. Which means we should be seeing a move away from them - toward leaner, more direct software that actually uses the hardware it runs on.&lt;/p&gt;

&lt;p&gt;We are seeing the opposite. More frameworks. Faster adoption of existing ones. New frameworks built as demos of AI capability, which will themselves become foundations that the next wave of developers builds on without questioning.&lt;/p&gt;

&lt;p&gt;The abstraction compounds. The hardware keeps getting faster. The software somehow feels slower than ever.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Nothing Is Changing
&lt;/h2&gt;

&lt;p&gt;I think there are two reasons software is not getting better.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;AI is not capable of leading the improvement.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Most developers do not really understand software - they understand frameworks.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I suspect it is both, and probably more the second than the first.&lt;/p&gt;

&lt;p&gt;I work with blank slates and AI coding regularly. No framework, direct instructions, building from actual requirements. It is less immediately capable than framework-assisted development - of course it is, there is no scaffolding to lean on. But with clear direction it produces good results. &lt;strong&gt;The AI does not impose a ceiling. The understanding of what you are trying to build is the ceiling.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When that understanding is shallow, AI fills the gap with whatever is familiar and well-documented. Which is frameworks. Which is copies of existing tools. Which is the path of least resistance dressed up as productivity.&lt;/p&gt;

&lt;p&gt;The question used to be "can I build this?" or "would it be cool to try?" Now the question is "why not?" Without the constraint of difficulty forcing any real consideration of whether it should be built, or whether there is a better way to build it.&lt;/p&gt;

&lt;p&gt;The only honest reason I can find for most of what is being produced is the trend. Build it, write the article, make the video, collect the attention - or get bought by the very company creating the hype train. The output is not the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Hope Comes After
&lt;/h2&gt;

&lt;p&gt;Hype cycles end. This one will too.&lt;/p&gt;

&lt;p&gt;What I hope comes after is a quieter period where the developers who actually understand software - who can articulate what they need, who can lead AI toward something genuinely better - start doing that without the noise.&lt;/p&gt;

&lt;p&gt;I hope they are already doing that, quietly, taking time to build something in two years that would have taken them twenty before - just like we do.&lt;/p&gt;

&lt;p&gt;More software from scratch. Less inherited complexity. Stacks that are the right size for the problem rather than the default size because that is what everyone uses.&lt;/p&gt;

&lt;p&gt;Maybe, on the other side of this, a photo app on Windows that opens in under 100ms. Not because that is a hard technical problem. &lt;strong&gt;Because sub-hundred milliseconds should be normal&lt;/strong&gt; and has not been, because the stack it sits on was never questioned - just inherited and added to.&lt;/p&gt;

&lt;p&gt;That is not an AI problem to solve. It is a judgment problem. The willingness to look at something that technically works and say it is not good enough - AI does not help with that. It just removed the excuse that you did not have time.&lt;/p&gt;

&lt;p&gt;AI can help build the right thing faster. &lt;strong&gt;It cannot decide what the right thing is.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The developers who already know the difference will benefit most from this era. Everyone else will produce more, faster, and none of it will be better.&lt;/p&gt;

&lt;p&gt;50,000 Jiras. Is that exaggerated? Maybe, but not by much. Todo apps were built in numbers before - they are the default now as well.&lt;/p&gt;

&lt;p&gt;We can now build faster than ever and it can be great stuff. Please do - and if you already are, thank you. Can't wait to see your work.&lt;/p&gt;

</description>
      <category>software</category>
      <category>ai</category>
      <category>discuss</category>
      <category>programming</category>
    </item>
    <item>
      <title>What We Lose By Using Instead of Creating - as devs and agencies</title>
      <dc:creator>Tom J.</dc:creator>
      <pubDate>Sat, 03 Jan 2026 10:34:58 +0000</pubDate>
      <link>https://forem.com/tomj/what-we-lose-by-using-instead-of-creating-as-devs-and-agencies-5h53</link>
      <guid>https://forem.com/tomj/what-we-lose-by-using-instead-of-creating-as-devs-and-agencies-5h53</guid>
      <description>&lt;p&gt;I started building things when I got my first dev job at 19. Not because I was trying to be special, but because I wanted to understand. I wanted to experiment and break stuff safely. That path later turned into what became our stack - Grace Web (PHP framework), our CMS, and a set of JS classes (no HTML or CSS framework, those are usually the easy part anyway).&lt;/p&gt;

&lt;p&gt;I was uncomfortable using other people’s stuff from day one, and I still am. At 19 it wasn’t about “shipping” anything - it was about learning. I learn by building, breaking, and understanding systems from the inside. Relying on tools I didn’t fully understand felt like skipping the lesson. Only a few years later I realized it also becomes part of what you ship to clients.&lt;/p&gt;

&lt;p&gt;That discomfort aged well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before we dive
&lt;/h2&gt;

&lt;p&gt;Sometimes it’s the right call to use existing stuff. But over time we moved from “small sharp tools” to “whole stacks you live inside”, and many people ship things they don’t really understand anymore.&lt;/p&gt;

&lt;p&gt;I’m writing this now because AI makes that trend obvious. AI is a power user, not a creator. It can generate output without understanding the system behind it - and that’s the same failure mode you get when you build on top of huge frameworks you can’t reason about.&lt;/p&gt;

&lt;p&gt;We’re not at “AI replaces engineers”. But if replacement happens, it starts with tool users decades before it touches expert creators.&lt;/p&gt;

&lt;h2&gt;
  
  
  The “Use This, It’s Faster” Trap
&lt;/h2&gt;

&lt;p&gt;Early in web dev I was told the usual stuff: wrap everything into jQuery objects, chain &lt;code&gt;.find()&lt;/code&gt; everywhere, use whatever plugins you can find. It looked productive. It also felt like programming with oven mitts on.&lt;/p&gt;

&lt;p&gt;Later, the same pattern kept repeating: the website starts lagging, UI stutters, mobile gets weird, and suddenly the fix isn’t “optimize a line” - it’s “unwind a whole approach”.&lt;/p&gt;

&lt;p&gt;Meanwhile, native browser APIs like &lt;code&gt;querySelector&lt;/code&gt; and &lt;code&gt;querySelectorAll&lt;/code&gt; are fast, predictable, and implemented in highly optimized native code. The browser is already your engine. If you keep stacking engines on top of engines, you get overhead, complexity, and mystery bugs as a bonus prize.&lt;/p&gt;

&lt;p&gt;Performance is one part of it. But the bigger problem is this: people keep adopting abstraction without understanding what it abstracts.&lt;/p&gt;

&lt;p&gt;To be fair, jQuery existed for real reasons: browsers were a mess and APIs weren’t consistent (hello Internet Explorer 6). But that doesn’t justify turning the whole front-end into a dependency pile, especially when the platform eventually grew up.&lt;/p&gt;

&lt;h2&gt;
  
  
  You Can’t Guarantee What You Don’t Understand
&lt;/h2&gt;

&lt;p&gt;This is the part that actually &lt;strong&gt;matters in business&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;How can a developer guarantee quality if they don’t know the system they’re shipping?&lt;/p&gt;

&lt;p&gt;And I don’t mean “they didn’t read React source code”. I mean basic stuff like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What exactly happens on the client vs the server&lt;/li&gt;
&lt;li&gt;What runs on every request vs what’s cached&lt;/li&gt;
&lt;li&gt;What code executes on scroll, resize, input, render&lt;/li&gt;
&lt;li&gt;What you can safely change without collapsing the whole thing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you don’t understand your own stack, you can’t confidently promise:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Yes, we can fix that quickly.”&lt;/li&gt;
&lt;li&gt;“Yes, we can make it faster.”&lt;/li&gt;
&lt;li&gt;“Yes, we can make it secure.”&lt;/li&gt;
&lt;li&gt;“Yes, we can adapt it when your business changes.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can only promise “we’ll try, unless the tool says no”.&lt;/p&gt;

&lt;p&gt;That’s not engineering. That’s renting complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Big Frameworks Make It Easy To Ship Blind
&lt;/h2&gt;

&lt;p&gt;Something weird happened over time.&lt;/p&gt;

&lt;p&gt;At first (before my career started), small libraries popped up and that was great. A tiny focused tool that does one thing well can genuinely save time and reduce risk. OpenSSL is a perfect example. You &lt;em&gt;do not&lt;/em&gt; want to DIY cryptography. FFmpeg is another. Use them if you need crypto or video. They’re obsessively optimized and everywhere.&lt;/p&gt;

&lt;p&gt;But then the industry drifted from “small sharp tools” into “entire castles you move into”.&lt;/p&gt;

&lt;p&gt;And castles come with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hidden rooms (behavior you didn’t expect)&lt;/li&gt;
&lt;li&gt;fragile walls (one upgrade breaks four things)&lt;/li&gt;
&lt;li&gt;and a landlord (you wait for someone else to fix critical bugs)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So now we get people shipping products where they don’t really know what happens under the hood. Some don’t even properly understand client-server anymore, which is… wild. That’s like being a mechanic who doesn’t know what an engine does, but has strong opinions about paint color.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security Isn’t A Checkbox, It’s A Relationship
&lt;/h2&gt;

&lt;p&gt;If you build it, you can inspect it. You can reason about it. You can patch it right now.&lt;/p&gt;

&lt;p&gt;If you download it, you inherit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;unknown code quality&lt;/li&gt;
&lt;li&gt;unknown security posture&lt;/li&gt;
&lt;li&gt;unknown update discipline&lt;/li&gt;
&lt;li&gt;unknown long-term compatibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And even if the third-party project is good, the real risk is the ecosystem around it: dependencies, plugins, integrations, random abandoned packages that are still installed because “it works”.&lt;/p&gt;

&lt;p&gt;A lot of attacks don’t happen because someone wrote genius malware. They happen because your stack is a Jenga tower and someone removed a block.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Teaches You The Stuff You Can’t Fake
&lt;/h2&gt;

&lt;p&gt;The most underrated part of building your own things is learning and life lasting effect.&lt;/p&gt;

&lt;p&gt;When you replace libraries piece by piece, class by class, function by function - you’re forced to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how the platform actually behaves&lt;/li&gt;
&lt;li&gt;how networks and systems fail&lt;/li&gt;
&lt;li&gt;what “slow” really means (and where it comes from)&lt;/li&gt;
&lt;li&gt;what matters to users (and what doesn’t)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That knowledge sticks. It becomes an imprinted understanding, your nature, you will see the Matrix.&lt;/p&gt;

&lt;p&gt;And in a post-AI age, that imprint is the real value. AI can output code. It can’t give you judgement for free. The people who stay relevant are the ones who can look at AI output and instantly spot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what’s unnecessary&lt;/li&gt;
&lt;li&gt;what’s risky&lt;/li&gt;
&lt;li&gt;what will break under load&lt;/li&gt;
&lt;li&gt;what will become unmaintainable in 6 months&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You only get that by building and owning systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ownership: Mental, Legal, Practical
&lt;/h2&gt;

&lt;p&gt;Ownership isn’t just “we have the source”.&lt;/p&gt;

&lt;p&gt;It’s also mental ownership - you &lt;em&gt;know&lt;/em&gt; how the system works, so you can confidently change it without fear.&lt;/p&gt;

&lt;p&gt;And it’s practical ownership - when something breaks, you don’t wait for “next patch”. You fix it. You ship. You’re in control.&lt;/p&gt;

&lt;p&gt;This is also why I love custom stacks for client work. With our approach, I basically never had to tell a client:&lt;/p&gt;

&lt;p&gt;“No, we can’t do this, the software doesn’t allow it.”&lt;/p&gt;

&lt;p&gt;We talk about needs. Then we talk about cost and viability. That’s it. No artificial limitations imposed by someone else’s design decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  “But Maintenance…”
&lt;/h2&gt;

&lt;p&gt;This is the classic objection and honestly, it’s overstated.&lt;/p&gt;

&lt;p&gt;With your own code, maintenance is usually:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fix what’s buggy&lt;/li&gt;
&lt;li&gt;expand what you actually need&lt;/li&gt;
&lt;li&gt;improve what you want to improve&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s it. It’s incremental. It follows reality. It’s very rarely as time consuming as people imagine.&lt;/p&gt;

&lt;p&gt;Yes, it’s work. But it’s also compounding value, because every improvement becomes part of your permanent toolset - in technical sense and understanding.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Simple Rule That Actually Works
&lt;/h2&gt;

&lt;p&gt;I’m not saying “never use anything”.&lt;/p&gt;

&lt;p&gt;I’m saying: be intentional.&lt;/p&gt;

&lt;p&gt;Use external tools when they are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;proven and battle-tested&lt;/li&gt;
&lt;li&gt;narrow in scope&lt;/li&gt;
&lt;li&gt;hard to do correctly yourself&lt;/li&gt;
&lt;li&gt;stable in behavior (not opinionated magic)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OpenSSL, FFmpeg, maybe a database engine, some image codecs, sure.&lt;/p&gt;

&lt;p&gt;But if the “tool” is basically a whole worldview that replaces your understanding of the platform… that’s where you start losing things.&lt;/p&gt;

&lt;p&gt;And eventually you lose the ability to say “yes” to a client with confidence.&lt;/p&gt;

&lt;p&gt;That’s a brutal trade.&lt;/p&gt;

&lt;p&gt;So yeah - creating is slower at the start. But it buys you something most developers don’t have anymore: control.&lt;/p&gt;

&lt;p&gt;And control is the foundation of quality.&lt;/p&gt;

&lt;p&gt;If you keep building, even gradually, you don’t just ship software. You become the kind of person who can stand behind it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final words
&lt;/h2&gt;

&lt;p&gt;I’m not saying “people who use tools are bad”. Some developers go deep in whatever they use. They understand trade-offs, strip what they don’t need, and treat a framework as a starting point, not a religion. That’s great engineering.&lt;/p&gt;

&lt;p&gt;What worries me is cargo-cult development: copying stacks because they’re popular, shipping black boxes, and hoping performance and security will magically work out, or not thinking about them at all.&lt;/p&gt;

&lt;p&gt;For us, building our own stack has been the opposite: high performance, predictable behavior, and the ability to say “yes” to client needs without being blocked by someone else’s constraints. That’s the approach I’m sticking with, because it’s the only one I can actually stand behind.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>architecture</category>
      <category>learning</category>
    </item>
    <item>
      <title>Should web browser let you control CTRL/CMD + W?</title>
      <dc:creator>Tom J.</dc:creator>
      <pubDate>Thu, 29 May 2025 16:16:08 +0000</pubDate>
      <link>https://forem.com/tomj/should-web-browser-let-you-control-ctrlcmd-w-59c8</link>
      <guid>https://forem.com/tomj/should-web-browser-let-you-control-ctrlcmd-w-59c8</guid>
      <description>&lt;p&gt;We are building a web app for web developers. For pros. For power users. For you. And it has tabs.&lt;/p&gt;

&lt;p&gt;Instinctively, I want to close them with CTRL + W. Not just want - I did several times. Yeah, I was annoyed!&lt;/p&gt;

&lt;p&gt;Well, it’s easy, right?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keydown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ctrlKey&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metaKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;w&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nc"&gt;CloseComponentTab&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Were you as naive as me?&lt;/p&gt;

&lt;p&gt;You can not take away control from the browser acting on these basic UI shortcuts and other events.&lt;/p&gt;

&lt;p&gt;So - why? And should you be able to?&lt;/p&gt;

&lt;h2&gt;
  
  
  Can I prevent web browser closing tab on CTRL/CMD + W?
&lt;/h2&gt;

&lt;p&gt;No, you can not. Try the code above and you’ll see 😉&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%2Ff7o05fw6kcsmsvpxvyu4.png" 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%2Ff7o05fw6kcsmsvpxvyu4.png" alt="SEO accomplished" width="800" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The argument against taking control over UI shortcuts
&lt;/h2&gt;

&lt;p&gt;The low hanging fruit is &lt;strong&gt;safety of users&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The internet is an open space (who else does not believe it?), therefore there is a huge amount of bad actors.&lt;/p&gt;

&lt;p&gt;Do you know that in the past, you could not close a browser tab while there was an alert hanging there? And do you know why it changed? Because there were websites putting on alerts in loop just to keep you looking at the ads or other offers. Or they thought they are just funny - and it was the first 3 alerts the first time ever, then it was just abusive.&lt;/p&gt;

&lt;p&gt;And we can talk about other practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;making invisible Facebook buttons under mouse cursor;&lt;/li&gt;
&lt;li&gt;making automated clicks to subscribe buttons;&lt;/li&gt;
&lt;li&gt;pushing unrelated, “real” content through iframes;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I guarantee you that before you find a legitimate use, all these are going to be preventing users close the tab window easily for months.&lt;/p&gt;

&lt;h2&gt;
  
  
  One more - consistency of UI
&lt;/h2&gt;

&lt;p&gt;Imagine your own frustration - you are used to work with browser in a certain way, the keyboard way, ctrl+W, ctrl+T etc. Suddenly - nothing happens.&lt;/p&gt;

&lt;p&gt;WTF is this?&lt;br&gt;
What broke?&lt;br&gt;
It works on other tabs fine.&lt;br&gt;
Ooooooh it’s this shit!&lt;/p&gt;

&lt;p&gt;I feel like this is enough to say 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do we want to control CTRL/CMD + W?
&lt;/h2&gt;

&lt;p&gt;Web apps &amp;amp; web games - those are the primary applicants for controlling the basic UI shortcuts.&lt;/p&gt;

&lt;p&gt;Your web app can have its own tabs.&lt;/p&gt;

&lt;p&gt;Your web game wants to likely have a combination of CTRL (often for crouch) and W (usually moving forward or up).&lt;/p&gt;

&lt;p&gt;For &lt;a href="https://engine.grace.link" rel="noopener noreferrer"&gt;Grace Engine&lt;/a&gt;, it would do sooooo much - the ease of control, more consistent control with other tools utilizing tabs. CTRL+W to close a Data structure tab, CTRL + TAB for moving among the tabs, sounds perfect!&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%2Fcscuacpyviarvudt1htt.gif" 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%2Fcscuacpyviarvudt1htt.gif" alt="Closing browser's tab instead of web app's tab" width="720" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dare we dream about such future?
&lt;/h2&gt;

&lt;p&gt;I think so. There is a lot to figure out to keep the web safe and I am sure it’s not too high priority, but it’s not an unsolvable problem.&lt;/p&gt;

&lt;p&gt;We may end up with some confirmation dialog, which would be a cool solution. Your web app asks for a permission to control basic UI web browser shortcuts and after user confirms - let’s you e.preventDefault();&lt;/p&gt;

&lt;p&gt;Other option could be to allow capturing these shortcuts in installed PWAs. Oooh, man, PWAs, I still don’t know how to feel about those…&lt;/p&gt;

&lt;p&gt;I was focusing on CTRL/CMD + W - it’s one that comes to mind most often, but it’s about all like CTRL/CMD + T, CTRL/CMD + N, CTRL/CMD + TAB and others.&lt;/p&gt;

&lt;h2&gt;
  
  
  In conclusion
&lt;/h2&gt;

&lt;p&gt;In certain situations, I’d love to see it. But in most others - I am veeeery glad we don’t have this option. I am sure web browser makers will get to this one day and figure out a beautiful solution accommodating web apps and games without allowing spammers causing problems. When the day comes, who knows. But until then, I am sure we can live without it - we do and &lt;a href="https://engine.grace.link" rel="noopener noreferrer"&gt;Grace Engine&lt;/a&gt; prospers.&lt;/p&gt;

&lt;p&gt;If a young developer reads this - yes, it’s a desktop thing, they are still highly relevant 😊&lt;/p&gt;

&lt;p&gt;Good luck with your web apps!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>ux</category>
      <category>browser</category>
    </item>
    <item>
      <title>New WebDev Tool – Try it | Beta Test Coming</title>
      <dc:creator>Tom J.</dc:creator>
      <pubDate>Sat, 05 Apr 2025 21:58:02 +0000</pubDate>
      <link>https://forem.com/tomj/new-webdev-tool-try-it-beta-test-coming-gm1</link>
      <guid>https://forem.com/tomj/new-webdev-tool-try-it-beta-test-coming-gm1</guid>
      <description>&lt;p&gt;Hi web devs,&lt;/p&gt;

&lt;p&gt;I'd like to invite you to test our new dev tool we call &lt;a href="https://grace.engine.link" rel="noopener noreferrer"&gt;&lt;strong&gt;Grace Engine&lt;/strong&gt;&lt;/a&gt; - a web dev creation environment &lt;strong&gt;inspired by game engines&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Grace Engine has been in development for almost a year now. During the process, it evolved into a version, that sets a basis for next continuous development and growth, that is envisioned and planned in our roadmap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beta testing
&lt;/h2&gt;

&lt;p&gt;We are now looking for developers interested in testing this new way of making websites and helping us find bugs and opportunities.&lt;br&gt;
In exchange, &lt;strong&gt;we offer 2 years of free use&lt;/strong&gt; to all beta testers receiving a testing invitation. And, of course, any project you create during beta testing will persist into the full future release.&lt;/p&gt;

&lt;p&gt;During beta testing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;any project created can be fully used - no artificial limitations;&lt;/li&gt;
&lt;li&gt;you can use all functions of the Engine;&lt;/li&gt;
&lt;li&gt;any rendering runs on limited 32 MB RAM and 10 seconds time limit per render;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://engine.grace.link" rel="noopener noreferrer"&gt;Want to Join Beta?&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What to expect?
&lt;/h2&gt;

&lt;p&gt;We are nearing MVP - the very first released version. It means the current version isn't living to its full potential.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;there are bugs we haven't discovered, yet;&lt;/li&gt;
&lt;li&gt;some features are simpler and you still may need to use helper tools (like your IDE for coding);&lt;/li&gt;
&lt;li&gt;yet we've already made full production websites and you can, too;&lt;/li&gt;
&lt;li&gt;no real documentation is made just yet, but you get a definition file of classes and properties of the framework for some orientation;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where we are heading
&lt;/h2&gt;

&lt;p&gt;I have a huge vision behind Grace Engine and this first version is only a start.&lt;/p&gt;

&lt;p&gt;Even through these days of debugging and polishing, new features are being made in separate branches.&lt;/p&gt;

&lt;p&gt;In a near future, new features and set ups will start to pop in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;framework independence;&lt;/li&gt;
&lt;li&gt;option of your saved assets;&lt;/li&gt;
&lt;li&gt;addons to the Engine itself;&lt;/li&gt;
&lt;li&gt;downloadable assets;&lt;/li&gt;
&lt;li&gt;export performance auto optimization;&lt;/li&gt;
&lt;li&gt;app development and runtime independance;&lt;/li&gt;
&lt;li&gt;locally running instead of web-based;&lt;/li&gt;
&lt;li&gt;more and more and more and mooooore.... to create a real platform for developers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://engine.grace.link" rel="noopener noreferrer"&gt;Check out Grace Engine&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's behind the idea
&lt;/h2&gt;

&lt;p&gt;You know, software in general is getting more complex. Even websites. Many then comes to solutions like open-source, existing frameworks, plugins, no-code. Every single one of those solutions have their limitations - usually it's performance or limitations.&lt;/p&gt;

&lt;p&gt;I want websites, apps and software in general to be peak performance, to comply with devices and requirements of a platform, but also to not add a ton of work to every project you create.&lt;/p&gt;

&lt;p&gt;The Engine started as an idea to mitigate routine developer work. Those set ups of scripts with bunch of work around it, the work to prepare new blank project, all these that quickly add up in time and sometimes frustration and others.&lt;/p&gt;

&lt;p&gt;But it transformed quickly into a full platform, that is going to help in achieving this goal with each upcoming update and polish.&lt;/p&gt;




&lt;p&gt;I thank you to all of supporters and soon to be beta testers. Thank you, guys and I wish you the best whether it’s with this version or some future one.&lt;/p&gt;

&lt;p&gt;What's that classic line? &lt;strong&gt;Made By Developers For Developers&lt;/strong&gt; ;)&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>tooling</category>
    </item>
    <item>
      <title>#3 Custom Code Instead of Plugins/Libraries - Showcase of Simplicity</title>
      <dc:creator>Tom J.</dc:creator>
      <pubDate>Tue, 10 Dec 2024 14:58:51 +0000</pubDate>
      <link>https://forem.com/tomj/3-custom-code-instead-of-pluginslibraries-showcase-of-simplicity-2e8o</link>
      <guid>https://forem.com/tomj/3-custom-code-instead-of-pluginslibraries-showcase-of-simplicity-2e8o</guid>
      <description>&lt;p&gt;This is the third in a little trio of articles where I’m showing how quickly and easily you can implement common web features without relying on heavy libraries or complicated frameworks. This time, I worked on a "read more" button for clipped content - with maximal automation.&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%2Fmrxi7hqnmmazd52iwabk.gif" 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%2Fmrxi7hqnmmazd52iwabk.gif" alt="Image description" width="1024" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Feel Free to Use the Code
&lt;/h2&gt;

&lt;p&gt;The code is straightforward, just vanilla JavaScript—no libraries, no magic. It's super lightweight and easy to integrate. It uses &lt;code&gt;IntersectionObserver&lt;/code&gt; so it doesn't even run on elements until they're visible, saving performance overhead (though you may want to remove this optimization for smaller webpages).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/TomJPro/39e96d2cd6cbfcf908ad99273b2211a5" rel="noopener noreferrer"&gt;https://gist.github.com/TomJPro/39e96d2cd6cbfcf908ad99273b2211a5&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Discover a Whole New World of Simplicity
&lt;/h2&gt;

&lt;p&gt;I assumed libraries existed for this because the problem seemed complex. But when I tried writing it myself, my head was stuck in the idea that it needed a complicated solution—my mind lied to me! Now I’m convinced these libraries exist because other developers also overthink the problem or try to solve every possible scenario with one huge solution. That can never truly work in a world where we count milliseconds.&lt;/p&gt;

&lt;p&gt;When I wrote my first simple piece of code that did the job, it was just 20 lines compared to 100kb of a library, and it was even easier to customize for each project. It honestly felt like discovering a new world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Want to See How I Built It?
&lt;/h2&gt;

&lt;p&gt;I'm having fun with live streams. Come chat with me next time!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtube.com/live/xF8FJfIVa_w" rel="noopener noreferrer"&gt;Watch the Live Stream&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;After seeing three common features (like a &lt;a href="https://dev.to/tomj/found-simplicity-elegance-building-a-simple-carousel-with-javascript-132j"&gt;carousel&lt;/a&gt;, &lt;a href="https://dev.to/tomj/custom-read-more-to-clipped-lines-of-text-with-javascript-and-full-custom-code-for-you-593g"&gt;line clipping with a "read more"&lt;/a&gt;, and similar scripts) coded in just a few minutes (including JS, HTML, and CSS), I hope it's clear that you often don't need heavy libraries. Sometimes, plain old JavaScript and a dash of CSS is all it takes to achieve slick, performant results.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>learning</category>
    </item>
    <item>
      <title>Found Simplicity &amp; Elegance – Building a Simple Carousel with JavaScript</title>
      <dc:creator>Tom J.</dc:creator>
      <pubDate>Thu, 05 Dec 2024 18:29:57 +0000</pubDate>
      <link>https://forem.com/tomj/found-simplicity-elegance-building-a-simple-carousel-with-javascript-132j</link>
      <guid>https://forem.com/tomj/found-simplicity-elegance-building-a-simple-carousel-with-javascript-132j</guid>
      <description>&lt;p&gt;Hey everyone!&lt;/p&gt;

&lt;p&gt;I recently worked on a simple carousel for a client project. I'm absolutely enjoying this project—I didn't need to work on it myself, but I chose to dive in anyway because it's just so thrilling. I finally managed to find the best way to manage a project for its speedy and quality growth.&lt;/p&gt;

&lt;p&gt;Alongside that, I also finally discovered the value in simplicity that accomplishes the goal &lt;strong&gt;perfectly&lt;/strong&gt; without projecting a dev's (aka past me) need to prove themselves.&lt;/p&gt;

&lt;p&gt;I've uploaded the code to GitHub Gist, and in this article, I'll walk you through how it works. You can also watch the uploaded live stream on YouTube.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Goal
&lt;/h2&gt;

&lt;p&gt;Create a responsive, smooth-scrolling carousel that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allows horizontal scrolling through items.&lt;/li&gt;
&lt;li&gt;Has left and right arrow controls.&lt;/li&gt;
&lt;li&gt;Hides the arrows appropriately when scrolling reaches the start or end.&lt;/li&gt;
&lt;li&gt;Is &lt;strong&gt;SIMPLE&lt;/strong&gt;, &lt;strong&gt;LIGHTWEIGHT&lt;/strong&gt;, and &lt;strong&gt;EASY&lt;/strong&gt; to integrate.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Embracing Simplicity
&lt;/h2&gt;

&lt;p&gt;In the world of development in general, it's easy to get caught up in complex solutions, over-engineering features to showcase our skills. But usually, the simplest solutions are the way to go. This carousel is a testament to that philosophy.&lt;/p&gt;

&lt;p&gt;I could download a library or use margins, or sometimes I even saw absolute positioning—but I didn't; all those solutions are too heavy without providing any meaningful gain.&lt;/p&gt;

&lt;p&gt;I focused on using vanilla JavaScript and CSS to achieve the desired functionality. The result is a lightweight carousel that's easy to understand, maintain, and integrate into any project (yeah, I actually put it in place—or rather, all 6 places with specific design from Figma—in 30 minutes).&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The carousel's &lt;strong&gt;HTML&lt;/strong&gt; is dead simple. I'll just mention one thing—classes are for UI devs, data- attributes are for JS devs—this separation is awesome for team development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSS&lt;/strong&gt; takes care of all the animations for performance and ease of use and later changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JS is the real worker&lt;/strong&gt; here; it performs super simple logic to achieve a fantastic (not just a “good enough”) job in making the simple move and calculation. It’s simple code as it is, and it even has performance optimization included.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Approach Works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Less code and no external dependencies mean faster load times and better performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: Simplicity makes it easier to understand and modify the code in the future.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customization&lt;/strong&gt;: It's easy to tweak and style according to different projects' needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Watch the Live Stream
&lt;/h2&gt;

&lt;p&gt;If you're interested in seeing how I built this carousel step by step, check out the live stream on YouTube:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtube.com/live/OMeMvpbX6XQ" rel="noopener noreferrer"&gt;Watch the Live Stream&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts – Let's Keep Learning
&lt;/h2&gt;

&lt;p&gt;First, I used some 250kb carousel jQuery library. It had so many different transition effects and implementations, and it was awesome!... It wasn't... Every time a client asked for something, this thing just couldn't do it.&lt;/p&gt;

&lt;p&gt;Next, I created our own using the jQuery framework. It had 500 lines plus CSS, and it was universally used for any project and design. It was awesome!... It wasn't... Any kind of bending for any project took literally 2 hours, and any project needed to be bent to it.&lt;/p&gt;

&lt;p&gt;Then, I made a carousel for each project separately based on the same logic—margins and some effects on top and changing behavior on several responsive steps. It also wasn't awesome.&lt;/p&gt;

&lt;p&gt;Finally—this thing now takes me 10 minutes and is perfectly suited for a given project and perfectly performant.&lt;/p&gt;

&lt;p&gt;Of course, this requires collaboration with the graphics designer—if they want it simple, I can provide simple. But also, every other solution was unnecessarily bloated and large and just horrible, and even in the craziest carousels anyone can think of, the solution and code would be quite simple.&lt;/p&gt;

&lt;p&gt;Do you have your own experiences seeing yourself change over the years?&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Custom “Read More” to Clipped Lines of Text with JavaScript – And Full Custom Code for You</title>
      <dc:creator>Tom J.</dc:creator>
      <pubDate>Tue, 03 Dec 2024 23:37:13 +0000</pubDate>
      <link>https://forem.com/tomj/custom-read-more-to-clipped-lines-of-text-with-javascript-and-full-custom-code-for-you-593g</link>
      <guid>https://forem.com/tomj/custom-read-more-to-clipped-lines-of-text-with-javascript-and-full-custom-code-for-you-593g</guid>
      <description>&lt;p&gt;Hi everybody!&lt;/p&gt;

&lt;p&gt;I wanted to share a neat little JavaScript snippet I worked on during my first YouTube live stream. The goal was to clip a block of text to a specific number of lines and add a "Read More" link (or anything else, as the current project requires) at the end if the text exceeds that limit—in the same block, not as a separate button.&lt;/p&gt;

&lt;h2&gt;
  
  
  The History
&lt;/h2&gt;

&lt;p&gt;The project, which I can’t name just yet, used a previous version of this function. How did it work?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It split the text into separate characters.&lt;/li&gt;
&lt;li&gt;Placed each and every single one into a &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Used &lt;code&gt;forEach&lt;/code&gt; on the spans and checked if the &lt;code&gt;offsetTop&lt;/code&gt; of that span changed—if it did, it’s a new line.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I don’t know where my head was when coding this—not on my shoulders, that’s for sure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Amazing New Solution!
&lt;/h2&gt;

&lt;p&gt;Frankly, it’s nothing that hasn’t been done before.&lt;/p&gt;

&lt;p&gt;But it works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And it’s Elegant!&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;p&gt;In short, it checks added characters in a loop, starting with a single character plus the appendage, and if the block’s height is higher than before, it’s a new line.&lt;/p&gt;

&lt;p&gt;As I said, elegant! I love this new solution.&lt;/p&gt;

&lt;p&gt;And I kept that Observer, because why not, right?&lt;/p&gt;

&lt;h3&gt;
  
  
  Fun Fact
&lt;/h3&gt;

&lt;p&gt;I asked ChatGPT to write a dark sci-fi story. Haven't read it, yet. Honestly - I can't wait to get to that!&lt;/p&gt;

&lt;h2&gt;
  
  
  Come Hang Out Next Time
&lt;/h2&gt;

&lt;p&gt;The YouTube live stream was an interesting experience. I liked it a lot!&lt;/p&gt;

&lt;p&gt;Check the stream here: &lt;a href="https://youtube.com/live/FBpU7P3o5ME" rel="noopener noreferrer"&gt;https://youtube.com/live/FBpU7P3o5ME&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Utilize Multi-Thread in Javascript - Not About WebWorkers nor WebAssembly</title>
      <dc:creator>Tom J.</dc:creator>
      <pubDate>Mon, 02 Dec 2024 13:13:23 +0000</pubDate>
      <link>https://forem.com/tomj/utilize-multi-thread-in-javascript-not-about-webworkers-nor-webassembly-2okk</link>
      <guid>https://forem.com/tomj/utilize-multi-thread-in-javascript-not-about-webworkers-nor-webassembly-2okk</guid>
      <description>&lt;p&gt;It's well known that JavaScript runs on a single thread. This concept is so integral that we often refer to it by name - the &lt;strong&gt;Main Thread&lt;/strong&gt;. So, does that mean your multi-core CPU is useless when running JavaScript?&lt;/p&gt;

&lt;p&gt;Not quite.&lt;/p&gt;

&lt;p&gt;JavaScript can be a bit cheeky, sending mixed messages about its threads.&lt;/p&gt;

&lt;p&gt;But even without delving into more complex features like Web Workers and WebAssembly, basic JavaScript can utilize multi-threaded workflows.&lt;/p&gt;

&lt;p&gt;To be clear, this article focuses on web browser-based JavaScript. Other environments, like Node.js, may handle things differently.&lt;/p&gt;

&lt;p&gt;We're going to explore options for multi-thread and multi-thread-like operations in JavaScript. The reality is - you can and should utilize multi-threaded workflows in basic, pure vanilla JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Explain!"
&lt;/h2&gt;

&lt;p&gt;Happy to.&lt;/p&gt;

&lt;p&gt;JavaScript is a single-threaded language, but it's interpreted by web browsers - and browsers are multi-threaded software.&lt;/p&gt;

&lt;p&gt;There are several methods to simulate and utilize multi-threading, and you might be using them without even realizing it.&lt;/p&gt;

&lt;p&gt;Additionally, JavaScript often behaves in ways that seem multi-threaded without actually being so. It might sound like cheating, but it effectively delivers the benefits we expect from multi-threaded behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Event-Based Programming Feels Multi-Threaded
&lt;/h2&gt;

&lt;p&gt;JavaScript is an event-based system. When the browser processes a JavaScript file, it runs all the code inside. It's entirely possible to write code that doesn't stop running - though that's generally a bad idea because it can crash the browser.&lt;/p&gt;

&lt;p&gt;What we usually do is set up event listeners and wait for something to happen. At this point, JavaScript is &lt;strong&gt;completely idle&lt;/strong&gt;. This idle waiting wouldn't be possible without offloading some work from the Main Thread.&lt;/p&gt;

&lt;p&gt;Events themselves aren't multi-threaded, but the waiting and checking for events is handled by the browser, not by JavaScript. This process is offloaded from the Main Thread.&lt;/p&gt;

&lt;h2&gt;
  
  
  Asynchronous Functions and Multi-Threading
&lt;/h2&gt;

&lt;p&gt;Functions like &lt;code&gt;setTimeout&lt;/code&gt; and &lt;code&gt;setInterval&lt;/code&gt; have been with us for many years. They offload the waiting time from the Main Thread.&lt;/p&gt;

&lt;p&gt;Let's simplify how this works. In lower-level languages, timers and waiting are often implemented by constantly checking, "Is it time already?" Imagine a &lt;code&gt;while()&lt;/code&gt; loop that checks the elapsed time and proceeds when the time is right. Modern approaches might use CPU interrupts to avoid clogging the CPU thread.&lt;/p&gt;

&lt;p&gt;However, when you use &lt;code&gt;setTimeout&lt;/code&gt; or &lt;code&gt;setInterval&lt;/code&gt; in JavaScript, the language is completely idle during the wait, which, again, means the waiting is processed somehow out the Main Thread.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fetch and Other Asynchronous APIs
&lt;/h3&gt;

&lt;p&gt;These days, we're getting more and more asynchronous functions and APIs from browsers. The &lt;code&gt;fetch&lt;/code&gt; API is a well-known example. Even newer APIs, like the Clipboard API, are asynchronous.&lt;/p&gt;

&lt;p&gt;This means you ask the browser to perform an action, and it frees up JavaScript's Main Thread (or allows it to process other stuff - more on that later) and notifies you (by processing the following code) when it's done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Asynchronous vs. Multi-Threaded
&lt;/h2&gt;

&lt;p&gt;Asynchronous doesn't necessarily mean multi-threaded - not always, not directly. Simply putting the word &lt;code&gt;async&lt;/code&gt; in front of a function doesn't do a shit for you.&lt;/p&gt;

&lt;p&gt;There are two key components to how JavaScript handles asynchronous behaviors:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Callback Queue and Event Loop
&lt;/h3&gt;

&lt;p&gt;Think of the callback queue as a line of functions waiting to run. These functions execute one by one in the Main Thread. When an asynchronous operation completes - be it an event, a timeout, or a completed &lt;code&gt;fetch&lt;/code&gt; - its callback is placed in this queue.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;event loop&lt;/strong&gt; is responsible for moving callbacks from the queue to the call stack when the call stack is empty.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Browser-Processed Functions
&lt;/h3&gt;

&lt;p&gt;The web browser takes control of certain operations and may spin up new threads for them—this includes actions like &lt;code&gt;fetch&lt;/code&gt; or &lt;code&gt;setTimeout&lt;/code&gt;. JavaScript doesn't need to manage these threads. When the asynchronous operation is complete, the browser places the corresponding callback into the callback queue, and JavaScript continues execution from there.&lt;/p&gt;

&lt;p&gt;Consider this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This is asynchronous&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;End&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Start
End
This is asynchronous
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;'Start'&lt;/code&gt; is logged.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setTimeout&lt;/code&gt; is called without a timeout parameter, so it defaults to 0 milliseconds. The callback is sent to the browser to execute after the current call stack is clear.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;'End'&lt;/code&gt; is logged.&lt;/li&gt;
&lt;li&gt;The Main Thread is now free, and the event loop checks the callback queue.&lt;/li&gt;
&lt;li&gt;The callback function from &lt;code&gt;setTimeout&lt;/code&gt; is moved to the call stack.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;'This is asynchronous'&lt;/code&gt; is logged.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice that &lt;code&gt;setTimeout&lt;/code&gt; is missing the timeout parameter. This is a common technique to defer lower-priority code execution - first process all else, after that’s done, do the “lower priority” thing.&lt;/p&gt;

&lt;p&gt;What this does is place the function inside &lt;code&gt;setTimeout&lt;/code&gt; into the callback queue immediately, and it runs at the first opportunity when the Main Thread is idle.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Special Case of &lt;code&gt;requestAnimationFrame&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;requestAnimationFrame&lt;/code&gt; is a browser API that tells the browser you want to execute some code just before it calculates and updates the view (think of it as frames per second in video games).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;For some reason, web developers do not think in repaints and FPS, but that’s how it works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It's inherently asynchronous (though not multithreaded).&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;setTimeout&lt;/code&gt; without a specified time was often used for similar purposes before &lt;code&gt;requestAnimationFrame&lt;/code&gt; was introduced, though it was far from being as useful (just better than nothing).&lt;/p&gt;

&lt;p&gt;This function queues your code into a special stack. Just before rendering a new frame (the repaint), the browser runs this queued code. It's perfect for making changes to the DOM, HTML, or CSS (and only those, please, I forbid you making calculations there!).&lt;/p&gt;

&lt;h2&gt;
  
  
  True Multi-Threading Options
&lt;/h2&gt;

&lt;p&gt;While this article isn't about them, it's worth mentioning that you can achieve true(er) multi-threaded operations by utilizing &lt;strong&gt;Web Workers&lt;/strong&gt; and &lt;strong&gt;WebAssembly&lt;/strong&gt;. These allow you to run scripts in background threads. They cannot directly manipulate the DOM, but they're invaluable for processing heavy tasks (matrix calculations, anyone?). This approach is often used in HTML5-based games - the more complex ones, not just tic-tac-toe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Last Words
&lt;/h2&gt;

&lt;p&gt;JavaScript, when isolated, remains single-threaded. But in the real world, it's an interpreted language running within multi-threaded environments of web browsers. If your interpreter offers you a helping hand, take it and use it.&lt;/p&gt;

&lt;p&gt;This article covers a lot - basic knowledge, low-level explanations, and more. But that's often how development is - all interconnected. That's why I like to look at the broader picture; sometimes, a detailed focus isn't the solution to a problem.&lt;/p&gt;




&lt;p&gt;Has &lt;code&gt;async&lt;/code&gt; ever caused you debugging nightmares?&lt;br&gt;
I certainly have -  some years ago, getting stacks with errors wasn’t much of a thing.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>How &lt;canvas&gt; Saved the Day - Handling Large Images in the Browser</title>
      <dc:creator>Tom J.</dc:creator>
      <pubDate>Thu, 28 Nov 2024 17:19:40 +0000</pubDate>
      <link>https://forem.com/tomj/how-saved-the-day-handling-large-images-in-the-browser-7e6</link>
      <guid>https://forem.com/tomj/how-saved-the-day-handling-large-images-in-the-browser-7e6</guid>
      <description>&lt;p&gt;A client uploaded 28 images, each around &lt;strong&gt;5800 x 9500 pixels&lt;/strong&gt; and &lt;strong&gt;28 MB&lt;/strong&gt; in size. When attempting to display these images in the browser, the entire tab froze - even refusing to close - for a solid &lt;strong&gt;10 minutes&lt;/strong&gt;. And this was on a high-end machine with a Ryzen 9 CPU and an RTX 4080 GPU, not a tiny laptop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Here’s The Situation
&lt;/h2&gt;

&lt;p&gt;In our CMS (Grace Web), when an admin uploads a file - be it a picture or a video - we display it immediately after the upload finishes. It's great for UX - it confirms the upload was successful, they uploaded what they intended to, and it shows responsiveness of the UI for better feel.&lt;/p&gt;

&lt;p&gt;But with these massive images, the browser could barely display them and froze up.&lt;/p&gt;

&lt;p&gt;It's important to note that the issue wasn't with the upload itself but with &lt;strong&gt;displaying these large images&lt;/strong&gt;. Rendering 28 huge images simultaneously and one by one was just too much. Even on a blank page, it's just... nope.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Did This Happen (Deep Dive)?
&lt;/h3&gt;

&lt;p&gt;Anytime you display a picture in an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag, the browser goes through an entire process that employs the CPU, RAM, GPU, and sometimes the drive - sometimes even cycling through this process multiple times before the picture is displayed during image loading and layout recalculations. It goes through calculating pixels, transferring data among hardware, interpolating algorithms, etc. For a browser, it’s a significant process.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Brainstormed Solutions
&lt;/h2&gt;

&lt;p&gt;We considered several options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Resize Immediately After Upload and Display Thumbnail&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Issue&lt;/strong&gt;: Resizing could take too long and isn't guaranteed to be instantaneous, especially if the resizing queue isn't empty - results in not-a-responsive system.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check File Sizes and Display Only Their Names for Large Files&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Issue&lt;/strong&gt;: This would detract from the user experience, especially for those who require greater control and checks of any media material (incidentally, those are often the same ones with large files).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Neither of these solutions felt usable. We didn't want to limit our admins' ability to upload whatever they needed, nor did we want to compromise on the user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lightbulb! Using &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I recalled that the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element utilizes the GPU much more effectively to render content. I recently saw someone building quiet complex game using JavaScript and &lt;code&gt;&amp;lt;canvas&amp;gt;,&lt;/code&gt; so it should theoretically handle large images more efficiently than &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing the Theory
&lt;/h3&gt;

&lt;p&gt;We decided to replace the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; elements with &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; for displaying the uploaded images. Here's the code snippet we used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// img.src = URL.createObjectURL(file); // Use this if you're working with uploaded files&lt;/span&gt;
&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;filesroot&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Our existing file path&lt;/span&gt;
&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Resize canvas to desired size (for preview)&lt;/span&gt;
  &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Adjust scaling as needed&lt;/span&gt;
  &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Draw the image onto the canvas, resizing it in the process&lt;/span&gt;
  &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;file_div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Prepared &amp;lt;div&amp;gt; in UI to display the thumbnail&lt;/span&gt;
  &lt;span class="nx"&gt;file_div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Results
&lt;/h3&gt;

&lt;p&gt;The improvement was immediate and dramatic! Not only did the browser handle the 28 large images without any hiccups, but we also pushed it further by loading &lt;strong&gt;120 MB images&lt;/strong&gt; measuring &lt;strong&gt;28,000 x 17,000 pixels&lt;/strong&gt;, and it still worked as if it was a tiny icon.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where Is the Difference?
&lt;/h3&gt;

&lt;p&gt;Using the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element, the drawing is entirely in the hands of the GPU, and those chips are literally made for this task.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; still attempts to render 28,000 * 17,000 = 476,000,000 pixels.&lt;/li&gt;
&lt;li&gt;This &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; draws only 80 * 80 = 6,400 pixels.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By resizing the image within the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; to a small preview size, we're drastically reducing the amount of data the browser needs to process - send hundreds of millions of pixels to GPU and get back thousands, a great deal, right?&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Given this success, we're now considering replacing &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; with &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; in other parts of our application, particularly in admin screens that display around 250 images at once. While these images are already properly resized, we're curious to see if using &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; can offer even better performance.&lt;/p&gt;

&lt;p&gt;We'll be conducting testing and benchmarking to measure any performance gains. I'll be sure to share our findings in a future article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important Caveats
&lt;/h2&gt;

&lt;p&gt;While using &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; worked wonders for our specific use case, I must note that you &lt;strong&gt;should not use &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; for displaying images on public-facing parts of websites&lt;/strong&gt;. Here's why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility&lt;/strong&gt;: &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; elements are readable by screen readers, aiding visually impaired users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SEO&lt;/strong&gt;: Search engines index images from &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags, which can improve your site's visibility. (In the same way, AI-training scrapers "index" the images, too. Well, what can you do...)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; with &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; can be used to automatically detect pixel density and show bigger or smaller pictures for a perfect fit—&lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; can’t. I wrote an article on &lt;a href="https://dev.to/tomj/web-images-resize-and-convert-perfectly-and-automatically-1adp"&gt;how to build your &lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For public websites, it's best to properly resize images on the server side before serving them to users. If you're interested in how to automate image resizing and optimization, I wrote an &lt;a href="https://dev.to/tomj/web-images-resize-and-convert-perfectly-and-automatically-1adp"&gt;article on that topic&lt;/a&gt; you might find useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;I love optimization!&lt;/strong&gt; Even though we are moving towards local high-performance hardware each day, by optimizing - even when "it's good, but can be better" - we could prevent issues like this from the beginning.&lt;/p&gt;

&lt;p&gt;This approach is not standard. And I don’t care for standards very much. They are often treated as hard rules, but they are just guidelines. This solution fits. We do not have clients with ancient devices without solid &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; support. So, even though now we have more code to manage, multiple ways of displaying pictures, it’s a perfect fit, and that’s what matters!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do you have some similar experiences? How did you handle it? Feel free to share your experiences or ask questions in the comments below!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>html</category>
      <category>performance</category>
    </item>
    <item>
      <title>A Comprehensive Guide to Starting and Maintaining Customer Support for Small Businesses and Freelancers</title>
      <dc:creator>Tom J.</dc:creator>
      <pubDate>Mon, 25 Nov 2024 22:06:53 +0000</pubDate>
      <link>https://forem.com/tomj/a-comprehensive-guide-to-starting-and-maintaining-customer-support-for-small-businesses-and-3ekl</link>
      <guid>https://forem.com/tomj/a-comprehensive-guide-to-starting-and-maintaining-customer-support-for-small-businesses-and-3ekl</guid>
      <description>&lt;p&gt;&lt;strong&gt;Exceptional customer support isn't just a luxury - it's a necessity for small businesses and freelancers alike.&lt;/strong&gt; After launching your product or service, customer support becomes the backbone that holds your customer relationships together, fosters loyalty, and sets you apart from the competition.&lt;/p&gt;

&lt;p&gt;While resource limitations may make customer support seem like a non-essential part of a business, it can play a pivotal role in your business's long-term growth. This guide will show you how to start and maintain customer support even with very limited resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  How This Article Will Help You
&lt;/h2&gt;

&lt;p&gt;At &lt;a href="https://link-v.pro/" rel="noopener noreferrer"&gt;LINK-V&lt;/a&gt;, we closely collaborate with our clients on maintaining and improving their projects through our &lt;a href="https://link-v.pro/timeless/" rel="noopener noreferrer"&gt;Timeless programs&lt;/a&gt;. We have firsthand experience in how our clients handle customer support for digital products, the types of inquiries they receive, and the pain points they encounter. We also manage customer support for some of our clients.&lt;/p&gt;

&lt;p&gt;We've created this guide to help you understand the importance of proper customer support, why it's often neglected, and how to build and maintain it even on a budget.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Customer Support Is Necessary
&lt;/h2&gt;

&lt;p&gt;There will always be a certain percentage of issues with every product or service. The volume and type of customer inquiries are often dictated by the nature of your offering. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;E-commerce Websites:&lt;/strong&gt; May have around 5% of customers asking for order status or help with product selection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscription-Based Services:&lt;/strong&gt; Could see 5-10% of customers seeking more value for their ongoing payments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Building Trust and Loyalty
&lt;/h3&gt;

&lt;p&gt;Good customer support fosters long-term relationships. When customers know they can rely on you for help and answers, they're more likely to return and recommend your services to others. Transparent customer support also attracts new customers, as they often unconsciously consider "what ifs" before making a purchase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Competitive Advantage
&lt;/h3&gt;

&lt;p&gt;Superior customer service can be your unique selling proposition. In markets saturated with similar products or services, exceptional support distinguishes you from competitors. &lt;strong&gt;At the very least, providing standard customer support brings you on par with other businesses in your space.&lt;/strong&gt; Without it, you risk falling behind. By offering not just standard but exceptional support, you can set yourself apart and gain a significant competitive edge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Legal Obligations
&lt;/h3&gt;

&lt;p&gt;Depending on your industry and how transactions are conducted, some countries have regulations requiring businesses to provide adequate customer support. It's essential to understand these obligations to remain compliant and build customer trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We'll Cover
&lt;/h2&gt;

&lt;p&gt;This guide focuses on the unique challenges and solutions for providing customer support in the realm of virtual, digital, and online products - areas we specialize in and understand thoroughly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resource Limitations
&lt;/h3&gt;

&lt;p&gt;We'll explore how to manage support with limited staff and budget, ensuring you provide quality service without overextending your resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  Underestimation of Support Needs
&lt;/h3&gt;

&lt;p&gt;Discover what customer inquiries typically involve and how to handle them effectively, even if you're a one-person operation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technology Hurdles
&lt;/h3&gt;

&lt;p&gt;Learn about adopting the right tools and options without getting overwhelmed by the vast array of technologies available.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Misconceptions
&lt;/h3&gt;

&lt;p&gt;We'll debunk some myths about customer support that can hinder your progress.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting Your Customer Support System
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Who Will Answer the Customers?
&lt;/h3&gt;

&lt;p&gt;You have several options, and you can start small:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Handle Support Yourself:&lt;/strong&gt; As a freelancer or small business owner, you can allocate time each day to check and respond to customer inquiries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hire a Part-Time Assistant:&lt;/strong&gt; Employ a student or part-time worker to check your chosen communication channels once a day and handle questions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Employ a Dedicated Support Person:&lt;/strong&gt; If possible, hire someone who can manage emails, social media, phone calls, or live chats as inquiries come in - ideal for remote workers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outsource to Professionals:&lt;/strong&gt; Hire a professional or a company specializing in customer support for multiple clients.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Choosing the Right Channels
&lt;/h3&gt;

&lt;p&gt;Offering multiple support channels shows you're accessible and reliable while keeping control in your hands. Consider a combination of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Email Support:&lt;/strong&gt; Easy to manage and organize; a staple for any business.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live Chat:&lt;/strong&gt; Provides real-time assistance, increasing customer satisfaction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Social Media Platforms:&lt;/strong&gt; Engage with customers where they already spend time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phone Lines:&lt;/strong&gt; Offers a personal touch but requires consistent availability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Caution:&lt;/strong&gt; Be careful with phone lines and live chat. If you can't offer consistent availability (e.g., 8 hours a day) at the times customers expect it, it's better to exclude them to avoid damaging trust.&lt;/p&gt;

&lt;h3&gt;
  
  
  Selecting the Right Tools
&lt;/h3&gt;

&lt;p&gt;Start with basic communication tools and a manual or common FAQs at hand. As your business and the number of customer inquiries grow, consider implementing a Customer Relationship Management (CRM) or ticketing system to enhance your efficiency and response times, such as our &lt;a href="https://link-v.pro/grace/manager/" rel="noopener noreferrer"&gt;Grace Manager&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Preparing Your Support Team
&lt;/h3&gt;

&lt;p&gt;The person responsible for customer support must understand the product or service thoroughly. Ideally, they should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Experience the Product Firsthand:&lt;/strong&gt; Personally explore every aspect of the live product to gain deep understanding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access Documentation:&lt;/strong&gt; Have written or video manuals readily available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Focus on Essential Skills:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Active listening&lt;/li&gt;
&lt;li&gt;Clear communication&lt;/li&gt;
&lt;li&gt;Empathy and patience&lt;/li&gt;
&lt;li&gt;Basic problem-solving abilities&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Adhere to Guiding Principles:&lt;/strong&gt;
Provide your support team with overarching instructions on how to deal with customers, such as:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Make Customers Happy at Any Reasonable Cost":&lt;/strong&gt; Empower them to go the extra mile to ensure customer satisfaction within reasonable limits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Be Transparent in How Things Work":&lt;/strong&gt; Encourage honesty and openness to build trust with customers.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Maintaining Customer Support
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Regular Updates
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Update FAQs:&lt;/strong&gt; Keep your Frequently Asked Questions current by adding common inquiries and updates on changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refresh Internal Manuals:&lt;/strong&gt; Ensure that any technical or design changes are reflected in your internal documentation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inform Your Team:&lt;/strong&gt; Keep support personnel in the loop about what's new in the business.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Feedback Loops
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Encourage Feedback:&lt;/strong&gt; Invite customers to share their thoughts through surveys or follow-up emails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implement Improvements:&lt;/strong&gt; Use feedback to enhance your products or services.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Understanding Customer Inquiries
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Categorizing Customer Issues and How to Address Them
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Product or Service Inquiries
&lt;/h3&gt;

&lt;p&gt;These often stem from misunderstandings or different expectations about how your product or service works. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Applying a Voucher:&lt;/strong&gt; Customers may not know where or how to apply discount codes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscription Processes:&lt;/strong&gt; They might struggle to find how to subscribe or manage their account.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Understand the core issue and provide clear, detailed information. Pre-prepared answers or a well-organized FAQ can save time and ensure consistency and fast answers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Billing and Account Questions
&lt;/h3&gt;

&lt;p&gt;Handle these with transparency and prioritize them. Financial concerns can heighten customer sensitivity, so prompt resolutions are essential.&lt;/p&gt;

&lt;h3&gt;
  
  
  Troubleshooting Issues
&lt;/h3&gt;

&lt;p&gt;When technical problems arise:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Acknowledge Quickly:&lt;/strong&gt; Respond promptly and inform the customer that you're investigating.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set Expectations:&lt;/strong&gt; Provide an estimated time frame for a resolution or at least for the next follow-up message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offer Alternatives:&lt;/strong&gt; If possible, guide the customer to an alternative way to achieve their goal in the least time possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Understanding the Customer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Decipher Messages:&lt;/strong&gt; Some inquiries may be vague or misleading. It's up to you to identify the core issue. Your customers do not know where the issue lies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adapt Communication:&lt;/strong&gt; Recognize that customers have different communication styles and skill levels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stay Patient:&lt;/strong&gt; An angry-sounding message might just be a customer's natural tone.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Advanced Steps: Proactive Engagement
&lt;/h2&gt;

&lt;p&gt;If you're ready to take your customer support to the next level, consider these proactive strategies. While not essential from the start, they can significantly enhance your customer engagement over time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Monitor Online Mentions:&lt;/strong&gt; Regularly check forums, review sites, and social media for mentions of your business.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Search Engines and their AI:&lt;/strong&gt; Employ tools to track what's being said about you online.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solicit Feedback:&lt;/strong&gt; Proactively ask for customer satisfaction feedback to identify areas for improvement.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tips for Effective Customer Support
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Personalization
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Names:&lt;/strong&gt; Address customers by their names.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Acknowledge History:&lt;/strong&gt; Refer to their past interactions or purchases - for example by thanking them for long-term support.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add Personal Touches:&lt;/strong&gt; Make professional messages feel more human.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Proactive Engagement
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reach Out First:&lt;/strong&gt; If you notice a potential issue, contact the customer before they reach out to you.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Consistency
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Uniform Quality:&lt;/strong&gt; Ensure all customers receive the same high-quality and professional support, regardless of the channel, who handles the inquiry or what is the customer’s tone.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Empathy and Patience
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Understand Frustrations:&lt;/strong&gt; Respond kindly, even if customers repeat themselves or seem impatient.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reassure Them:&lt;/strong&gt; Let customers know you're there to help, which can encourage future business.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Managing Emotional Aspects
&lt;/h3&gt;

&lt;p&gt;Handling customer support personally can be emotionally taxing, especially when dealing with criticism about your product or service - your "darling." Here are some tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Manage Personal Feelings:&lt;/strong&gt; Recognize that feedback isn't a personal attack but an opportunity for growth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stay Professional:&lt;/strong&gt; Keep interactions courteous, even when faced with misunderstandings or repeated questions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Beware the Loud Minority:&lt;/strong&gt; Avoid making drastic changes based solely on feedback from a few vocal customers. Use data and trends to guide significant decisions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where to Be Careful
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Chatbots
&lt;/h3&gt;

&lt;p&gt;While popular and tempting, chatbots may not be effective unless backed by robust technical systems (like real-time order status updates). If you're not equipped to implement them properly, it might be best to hold off.&lt;/p&gt;

&lt;h3&gt;
  
  
  Live Chat Availability
&lt;/h3&gt;

&lt;p&gt;A live chat feature that appears "online" but functions only as a contact form can be misleading. Similarly, a live chat that's frequently offline during peak customer hours can damage trust. Ensure consistent availability before implementing this feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sensitive Information in Communication
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Protect Customer Data:&lt;/strong&gt; Never ask for or accept sensitive information like passwords or payment details through insecure channels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Secure Methods:&lt;/strong&gt; Direct customers to secure forms or portals designed for handling sensitive data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Educate Customers:&lt;/strong&gt; Inform them about the importance of keeping their personal information safe if they offer to send you their access details.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Number of Inquiries and Service Quality
&lt;/h3&gt;

&lt;p&gt;It's a common misconception that as the quality of your service improves, the number of customer inquiries will decrease. &lt;strong&gt;Your customers come from diverse backgrounds and experiences. Even the best product or design cannot accommodate every person (or all mental states) who may be interested in your offering.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Often, a higher number of messages to respond to may actually indicate increased interest and rising sales. &lt;strong&gt;An uptick in inquiries can mean that more customers are engaging with your product or service, which is a positive sign for your business.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points to Consider:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Embrace Customer Engagement:&lt;/strong&gt; View each inquiry as an opportunity to connect with your customers and build stronger relationships.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid Misinterpretation:&lt;/strong&gt; Don't assume that more questions mean your product is lacking; it might simply reflect a growing customer base.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stay Responsive:&lt;/strong&gt; Maintain high-quality support even as the volume of inquiries increases to ensure customer satisfaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Role of Customer Support in Business Growth
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Customer Retention
&lt;/h3&gt;

&lt;p&gt;Excellent support encourages repeat business. Satisfied customers are more likely to stick around and continue using your services.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reputation Management
&lt;/h3&gt;

&lt;p&gt;Positive interactions lead to good reviews and word-of-mouth referrals, which are invaluable for growth.&lt;/p&gt;

&lt;h3&gt;
  
  
  Insights for Improvement
&lt;/h3&gt;

&lt;p&gt;Use customer interactions to refine your products or services. Feedback highlights what you're doing well and where you can improve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Customer support is more than just answering questions - it's about building relationships, trust, and loyalty. By implementing the strategies outlined in this guide, small businesses and freelancers can provide exceptional support that drives success.&lt;/p&gt;

&lt;p&gt;Remember, the nature of customer support is always evolving. Stay adaptable, keep learning, and your efforts will pay off.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contact Us
&lt;/h3&gt;

&lt;p&gt;Have questions or need assistance setting up your customer support system? &lt;a href="https://link-v.pro" rel="noopener noreferrer"&gt;**Reach out to LINK-V&lt;/a&gt; -** we're here to help you succeed.&lt;/p&gt;

</description>
      <category>management</category>
      <category>leadership</category>
      <category>startup</category>
      <category>freelance</category>
    </item>
    <item>
      <title>My Solution to Help with Growing Web/App Dev Complexity</title>
      <dc:creator>Tom J.</dc:creator>
      <pubDate>Sat, 23 Nov 2024 14:51:46 +0000</pubDate>
      <link>https://forem.com/tomj/my-solution-to-help-with-growing-webapp-dev-complexity-1n6a</link>
      <guid>https://forem.com/tomj/my-solution-to-help-with-growing-webapp-dev-complexity-1n6a</guid>
      <description>&lt;p&gt;A website or an app is a complex piece of software. All the things necessary to do for a solid website—the difficulty to create—is now closer to a video game than to a website from 25 years ago. And the complexity keeps growing.&lt;/p&gt;

&lt;p&gt;I think there is a solution to this.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Rising Complexity in Development
&lt;/h2&gt;

&lt;p&gt;It used to be (for all the amazing young blood reading this article) that you had a very limited amount of HTML tags while &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; was the only way of creating any layout whatsoever, barely any CSS, and definitely no JavaScript nor serverside code. 256-color GIFs were common, and centering content with its static width was considered made by a skilled developer. Also, no phones—you could count on a very standardized display size.&lt;/p&gt;

&lt;p&gt;In contrast to today's needs, if you want a successful website, the demands are huge. Consider what you need to do or keep in mind and work with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All the base technologies—HTML &amp;amp; CSS with JavaScript for front-end and your favorite programming language for back-end (PHP, Python, C#, whatever you love or tolerate).&lt;/li&gt;
&lt;li&gt;Database of some sort&lt;/li&gt;
&lt;li&gt;Server—because two minutes of downtime can cause significant losses&lt;/li&gt;
&lt;li&gt;Graphics &amp;amp; UI &amp;amp; UX so high-standard users can even understand the website/app and not be disgusted.&lt;/li&gt;
&lt;li&gt;So many different devices with different control schemes and display sizes and densities.&lt;/li&gt;
&lt;li&gt;Copywriting &amp;amp; photography&lt;/li&gt;
&lt;li&gt;SEO&lt;/li&gt;
&lt;li&gt;Analytics&lt;/li&gt;
&lt;li&gt;Testing, QA&lt;/li&gt;
&lt;li&gt;While apps are very similar, they are even more difficult in most of the points&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are creating bespoke projects, it’s highly unlikely you are working alone on it, and so the next point is teamwork and communication and team management, etc.&lt;/p&gt;

&lt;p&gt;Making a list is easy. But even if some of those items look like nothing’s changed... it has—all of that is massively more complicated to do.&lt;/p&gt;

&lt;h3&gt;
  
  
  In Example
&lt;/h3&gt;

&lt;p&gt;Let’s say you have a button. &lt;code&gt;&amp;lt;button&amp;gt;Submit!&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the past, this was enough. Now you need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Style it&lt;/li&gt;
&lt;li&gt;Account for states for different user interactions—hover, active, focus&lt;/li&gt;
&lt;li&gt;Disable it for double-click since it’s usually sending some data to the server, which is not immediate&lt;/li&gt;
&lt;li&gt;A loading or wait state in regards to the previous point&lt;/li&gt;
&lt;li&gt;And all that should be animated for the user's understanding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And this is only for basic function; you or your designer may want something special.&lt;/p&gt;

&lt;h2&gt;
  
  
  Options for Lowering Complexity and Difficulty
&lt;/h2&gt;

&lt;p&gt;There are options commonly used these days, such as using frameworks, pre-made plugins, etc.&lt;/p&gt;

&lt;p&gt;All those are a way to help you out to finish a project faster, cheaper, but also they limit you, and more often than not, they are used not as a help, but as an avoidance of what should be done, like designing for the client’s needs.&lt;/p&gt;

&lt;p&gt;I am sure many of you disagree with me. Of course, there are many ways of seeing this. From my point of view, as a head of a company specializing in bespoke high-quality products, these things are not helpful. But let’s talk in the comments; please share your opinion.&lt;/p&gt;

&lt;h2&gt;
  
  
  No-Code Is Not the Solution
&lt;/h2&gt;

&lt;p&gt;If a framework limits your ability, no-code is not a solution to the complexity due to their even more limiting factors, plus, added to that, they usually have highly non-performant code. Also, they are even more used with no thought to desired results.&lt;/p&gt;

&lt;p&gt;I don’t want to dunk on it. No-code is just for a different kind of customer, even though it’s sometimes used with the word “development” in marketing materials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing Development of Website &amp;amp; App with Video Games Dev
&lt;/h2&gt;

&lt;p&gt;In the introduction, I said modern websites are closer to video game development than to themselves from 25 years ago.&lt;/p&gt;

&lt;p&gt;I am a gamer. I love to watch game development videos. With this realization and living in the field of web development for 20+ years, I started to see the resemblances in the software and the development process and needs.&lt;/p&gt;

&lt;p&gt;Both product types are highly saturated in the market.&lt;/p&gt;

&lt;p&gt;Both have so many competing developers.&lt;/p&gt;

&lt;p&gt;In both, you can make something basic very quickly. In both, this won’t be very good or usable.&lt;/p&gt;

&lt;p&gt;Unlike games, websites and apps are a bit more limited due to what the platforms allow, websites more than apps.&lt;/p&gt;

&lt;p&gt;Some aspects are different, like server-client architecture in websites is mandatory or SEO necessities to keep in mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Solution Is a Hybrid Approach—Grace Engine
&lt;/h2&gt;

&lt;p&gt;If those two are this similar, why don’t we have similar tools? This question prompted further thinking and now, after about a year of development, we are nearing the first public version of such a tool.&lt;/p&gt;

&lt;p&gt;It’s already helping us develop real projects. Server and JavaScript code is still code, but the visualization of the projects is amazing, such a help!&lt;/p&gt;

&lt;p&gt;Let me tell you about some of the most helpful features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visual front-end coding while kept visible unfiltered HTML tags tree&lt;/li&gt;
&lt;li&gt;Faster prototyping and much easier idea and options testing&lt;/li&gt;
&lt;li&gt;Compartmentalized code for switching on/off, duplicating, attaching&lt;/li&gt;
&lt;li&gt;Use of external IDEs for hardcore developers&lt;/li&gt;
&lt;li&gt;Notes and comments directly in the Engine and other collaboration&lt;/li&gt;
&lt;li&gt;Front-end person doesn’t need nearly as much help from the programmer so the work is smoother and faster while coding directly on functioning website rather than static template&lt;/li&gt;
&lt;li&gt;Auto-optimizes front-end code for legacy vs. modern browsers&lt;/li&gt;
&lt;li&gt;Fine-tuning visuals with a client on the spot without looking too intimidating to them with classic IDE (yes, that is a real thing)&lt;/li&gt;
&lt;li&gt;Using built-in website hosting or export for custom web hosting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The benefits are so visible by now and all over the place; they are very often in small details.&lt;/p&gt;

&lt;p&gt;I truly believe that if you try it, you will see almost immediately the difference.&lt;/p&gt;

&lt;p&gt;I invite you to check out our &lt;a href="https://link-v.pro/grace/engine/" rel="noopener noreferrer"&gt;web page about this project&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next Steps
&lt;/h3&gt;

&lt;p&gt;As of now, our priority is to get the first version in the hands of web developers.&lt;/p&gt;

&lt;p&gt;Soon after, mobile apps are in our roadmap.&lt;/p&gt;

&lt;p&gt;Marketplace with community selling assets and features, graphics, themes, etc.&lt;/p&gt;

&lt;p&gt;Visually animating&lt;/p&gt;

&lt;p&gt;SEO tools&lt;/p&gt;

&lt;p&gt;Direct channel to your Figma projects with auto-coding&lt;/p&gt;

&lt;p&gt;There is a lot in our plans.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Yeah, this is a promotion of a product we are working on. BUT I genuinely believe it’s another step in web/app development. Or at least another option to how to create projects. I am using it for prototyping; we are using it for some clients' projects already. It’s not even a beta yet, and it’s changing how we create projects.&lt;/p&gt;

&lt;p&gt;If you leave your e-mail on the webpage, we’ll be selecting developers to try the beta.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>development</category>
      <category>mobile</category>
      <category>tooling</category>
    </item>
    <item>
      <title>15 + 2 Instant Graphics Improvements For Web Programmers - For Easier Work Or For Your Single-Person Project</title>
      <dc:creator>Tom J.</dc:creator>
      <pubDate>Wed, 20 Nov 2024 14:20:32 +0000</pubDate>
      <link>https://forem.com/tomj/15-2-instant-graphics-improvements-for-web-programmers-for-easier-work-or-for-your-26c</link>
      <guid>https://forem.com/tomj/15-2-instant-graphics-improvements-for-web-programmers-for-easier-work-or-for-your-26c</guid>
      <description>&lt;p&gt;You are outputting something into a browser and you are lost in it because it looks horrible. &lt;br&gt;
Even you need to look hard for what you are searching &lt;strong&gt;for&lt;/strong&gt; in that page. Now imagine you are collaborating with someone else or you want to show your work to someone—they are lost; therefore, you didn’t do a good job. We are visual creatures; you hear that all the time. If it doesn’t look okay, then it’s not okay.&lt;/p&gt;

&lt;p&gt;I am about to give you 15 + 2 tips to add to your CSS &amp;amp; HTML that won’t make your output in the browser amazing and artistic, but it will look fine, accessible and presentable.&lt;/p&gt;



&lt;p&gt;I will list these in order from the easiest to implement with the largest amount of improvement at the top.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Set Line Height for Text
&lt;/h2&gt;

&lt;p&gt;The #1 thing that separates Pro design from Amateurish one. This is the thing we all hate but can’t pinpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;150%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes your page much nicer looking, makes it easier to navigate, scan, read… I can’t sell this enough!&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Limit Maximum Width of Text Blocks
&lt;/h2&gt;

&lt;p&gt;In combination with line-height, you just achieved nice looking readable text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h6&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;dl&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;600px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Short lines of text are easy for people to follow, easier to read, don’t get lost and confused.&lt;/p&gt;

&lt;p&gt;No “looks good” mention? Well, when you prevent confusion, it’s instantly perceived as looking much better.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Pick Three Colors: Background, Text, Accent
&lt;/h2&gt;

&lt;p&gt;Stick to a simple color scheme.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#f9f9f9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#333333&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#007BFF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or reverse for dark theme.&lt;/p&gt;

&lt;p&gt;Generally, choose two contrasting colors for your background and text (e.g., dark text on a light background), and a third accent color, which must be much closer to the body background color than text color, for buttons and links.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Apply Consistent Spacing
&lt;/h2&gt;

&lt;p&gt;Create visual rhythm by standardizing the spacing between elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;dl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;table&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h6&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;40px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Reset top margins */&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Browser defaults are archaic and really look terrible to the modern eye.&lt;/p&gt;

&lt;p&gt;And for the love of … cancel out that margin-top&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Set Font Sizes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Universal for desktop and mobile */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;h6&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h5&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;18px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;h4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;24px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;h5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or choose your own scale (e.g., increase by 2px for each level as I do) that makes you comfortable.&lt;/p&gt;

&lt;p&gt;You have to scale instead of random numbers, looks soooo much better. And you can skip a level if you think it looks better. The issue usually is when thinking about text in terms of separate entities (paragraph, heading, …), because if you set standard font-size to 14px (because schools taught us it’s standard, hm?) and h1 to 58px, it looks like Optimus Prime stomping a mouse.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Use a Single Font
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;textarea&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Multiple fonts easily make your site look cluttered and ugly. A single font ensures cohesiveness.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Use Sans-Serif Fonts
&lt;/h2&gt;

&lt;p&gt;I know there are a lot of fonts that look interesting, fun, intriguing, but as we are going for certainty of OK design, then stay with common sans-serifs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;textarea&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'Open Sans'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're willing to include a custom font, try 'Open Sans'. If not, Arial is a safe, universally available choice.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Add Border Radius to Buttons
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Slightly rounded corners make buttons just feel modern and look nicer.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Create Larger Buttons with Adequate Padding
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, just looks modern and nicer.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. Align Text to the Left
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don’t center, please.&lt;/p&gt;

&lt;p&gt;Or use the default option for non-English languages. Isn’t Japanese top-down? Don’t center that either!&lt;/p&gt;




&lt;h2&gt;
  
  
  11. Avoid Using Shadows
&lt;/h2&gt;

&lt;p&gt;Just don't.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;box-shadow&lt;/code&gt; and &lt;code&gt;text-shadow&lt;/code&gt; can easily be overdone and make your UI look cluttered and ugly. They're tricky to get right, so it's best to avoid them.&lt;/p&gt;




&lt;h2&gt;
  
  
  12. Add Padding from Sides
&lt;/h2&gt;

&lt;p&gt;Prevent your content from touching the edges of the viewport.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Alternative:&lt;/strong&gt; If you haven't reset the body's margins, you might already have default spacing.&lt;/p&gt;

&lt;p&gt;Adding horizontal padding ensures your content isn't crammed against the screen edges, which is one of the ultimately horrifying views.&lt;/p&gt;




&lt;h2&gt;
  
  
  13. Add Hover and Active States to Links and Buttons
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.btn&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:active&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.btn&lt;/span&gt;&lt;span class="nd"&gt;:active&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;70%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Provide feedback when users interact with elements.&lt;/p&gt;




&lt;h2&gt;
  
  
  14. Use &lt;code&gt;cursor: pointer&lt;/code&gt; on Clickable Elements
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make it clear what can be clicked on mouse hover. &lt;a&gt; have this by default, for some reason, buttons don’t.&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  15. Set Maximum Width for Content Containers
&lt;/h2&gt;

&lt;p&gt;Limit width of all the content. On a large monitor, it’s a fantastic improvement. The only reason for it being this low is it’s not as simple to implement as all the others - we need to change HTML.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- All content here --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1200px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Bonus Tips
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Ensure Images and Videos are Responsive
&lt;/h3&gt;

&lt;p&gt;Make media elements adjust to different screen sizes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;img&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;video&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;iframe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you place a video or image in text or that container or whatever, they tend to overflow. With this CSS, they won’t.&lt;/p&gt;




&lt;h3&gt;
  
  
  Keep Everything Left-Aligned
&lt;/h3&gt;

&lt;p&gt;Consistency in alignment creates a clean, organized look. You know how you love your alignments in IDE? Use it in the output, too.&lt;/p&gt;




&lt;h2&gt;
  
  
  Central Theme To All The Points
&lt;/h2&gt;

&lt;p&gt;All we're doing here is setting some basic rules that are pleasant to the eye - consistency, alignment, simplicity. These are simple to implement with instant results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; Seriously, just set the &lt;code&gt;line-height&lt;/code&gt; as the first thing you do. It's an instant and massive improvement. By just doing that, you're already ahead of many designers who get paid for their work. I’ve seen too much in my career.&lt;/p&gt;




&lt;p&gt;By applying these simple CSS tweaks, you'll see a significant improvement in your project's design without needing extensive design knowledge. These tips are all about making your content more readable, your layout more consistent, and your user interface more intuitive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use-Cases
&lt;/h2&gt;

&lt;p&gt;This section is usually at the beginning of articles. But I am sure many can see where I am coming from. There are two main use-cases.&lt;/p&gt;

&lt;p&gt;First is where you are a programmer having an idea for an awesome project, but you are not really a designer. Your project doesn’t need to be a piece of art, it only has to be OK to read, view and understand.&lt;/p&gt;

&lt;p&gt;Second one is that you are a part of a development team and you need to program and output something. If you set up simple rules from this article, everybody will have way easier time understanding what the output is and how to work with it further.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Do you have any go-to design tips for developers?&lt;br&gt;
How do you, as programmer, approach UI design in your projects?&lt;br&gt;
Do you have your own experiences with those full-of-something pages?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programmers</category>
      <category>basic</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
