Jump to content

Blogger

Blog Bot
  • Joined

  • Last visited

    Never

Blog Entries posted by Blogger

  1. by: Chris Coyier
    Mon, 09 Jun 2025 16:37:09 +0000

    I love weird design ideas. Probably because so much of what we need to do as web designers is, appropriately, somewhat serious. We want things to be simple, clear, professional, so that people understand them and in many cases pay for them. So when the constraints relax, so can we. It’s unlikely that Taylor’s homepage would “perform well” in any sort of UX testing, but who cares? It’s not impossible to use, it’s just unusual. And crucially, it’s fun and memorable, which is likely a leg up on the last “dashboard” you saw.
    It’s cool of Blackle Mori to have documented The Lost CSS Tricks of Cohost.org, a social network ultimately too cool for this world. I sort of suspect a lot of this trickery is available in advanced email clients too, where you definitely don’t have JavaScript, but do have access to more-modern-than-you’d-think HTML and CSS.
    And high on the tranfixingly-weird scale is Amit Sheen’s CSS Spotlight Effect. Don’t write it off as a black page with a transparent circle moving with the mouse. I mean, it kinda is, but the filtering and scaling affects that come along for the ride are extremely cool. I actually just got to hang with Amit a bit at CSS Day in Amsterdam this past week. His talk was about building logic gates in CSS was pretty wild, and the whole thing end with him just showing off random amazing Pens of his on stage.
    Sometimes design can feel impressive because of the extreme constraints of where you’re seeing it. I’m at an airport lounge right now where I’ve seen an exhibit of sculptures carved into the lead tips of pencils. It’s that same kind of feeling I get when I see art happen in the terminal, a place usually not regarded for it’s beauty. Like seeing a daisy grow from the cracks of a busted up sidewalk.
    I like serious design as well. Certainly there is more money in it. I’m allowed to like them both, just like I enjoy both fine dining and fast food. I’ll just hit you with some quicker links though as I bet you’re tired of my going on.
    Chris Nager weighs in on Design Engineering from his experience with that title at Carta. “The most important skill design engineers possess is the ability to communicate with both designers and frontend engineers. They’re able to give feedback to both sides, and can act as translators between the two worlds through prototypes.” Emphasis mine, naturally. Lea Verou looks critically at a design change at GitHub in Minimalist Affordances: Making the right tradeoffs. Not only was it interesting, it showcases the power of blogging and making coherent points: GitHub noticed, talked with her, and improved the design. Grant Slatton on How to write a good design document. “Think of a design document like a proof in mathematics. The goal of a proof is to convince the reader that the theorem is true. The goal of a design document is to convince the reader the design is optimal given the situation.”
  2. by: Preethi
    Mon, 09 Jun 2025 12:58:37 +0000

    The HTML popover attribute transforms elements into top-layer elements that can be opened and closed with a button or JavaScript. Most popovers can be light-dismissed, closing when the user clicks or taps outside the popup. Currently, HTML popover lacks built-in auto-close functionality, but it’s easy to add. Auto closing popups are useful for user interfaces like banner notifications — the new-message alerts in phones, for instance.
    A picture demo, is worth a thousand words, right? Click on the “Add to my bookmarks” button in the following example. It triggers a notification that dismisses itself after a set amount of time.
    CodePen Embed Fallback Let’s start with the popover
    The HTML popover attribute is remarkably trivial to use. Slap it on a div, specify the type of popover you need, and you’re done.
    <div popover="manual" id="pop">Bookmarked!</div> A manual popover simply means it cannot be light-dismissed by clicking outside the element. As a result, we have to hide, show, or toggle the popover’s visibility ourselves explicitly with either buttons or JavaScript. Let’s use a semantic HTML button.
    <button popovertarget="pop" popovertargetaction="show"> Add to my bookmarks </button> <div popover="manual" id="pop">Bookmarked!</div> The popovertarget and popovertargetaction attributes are the final two ingredients, where popovertarget links the button to the popover element and popovertargetaction ensures that the popover is show-n when the button is clicked.
    Hiding the popover with a CSS transition
    OK, so the challenge is that we have a popover that is shown when a certain button is clicked, but it cannot be dismissed. The button is only wired up to show the popover, but it does not hide or toggle the popover (since we are not explicitly declaring it). We want the popover to show when the button is clicked, then dismiss itself after a certain amount of time.
    The HTML popover can’t be closed with CSS, but it can be hidden from the page. Adding animation to that creates a visual effect. In our example, we will hide the popover by eliminating its CSS height property. You’ll learn in a moment why we’re using height, and that there are other ways you can go about it.
    We can indeed select the popover attribute using an attribute selector:
    [popover] { height: 0; transition: height cubic-bezier(0.6, -0.28, 0.735, 0.045) .3s .6s; @starting-style { height: 1lh; } } When the popover is triggered by the button, its height value is the one declared in the @starting-style ruleset (1lh). After the transition-delay (which is .6s in the example), the height goes from 1lh to 0 in .3s, effectively hiding the popover.
    Once again, this is only hiding the popover, not closing it properly. That’s the next challenge and we’ll need JavaScript for that level of interaction.
    Closing the popover with JavaScript
    We can start by setting a variable that selects the popover:
    const POPOVER = document.querySelector('[popover]'); Next, we can establish a ResizeObserver that monitors the popover’s size:
    const POPOVER = document.querySelector('[popover]'); const OBSERVER = new ResizeObserver((entries) => { if(entries[0].contentBoxSize[0].blockSize == 0) OBSERVER.unobserve((POPOVER.hidePopover(), POPOVER)); }); And we can fire that off starting when the button to show the popover is clicked:
    const POPOVER = document.querySelector('[popover]'); const OBSERVER = new ResizeObserver((entries) => { if(entries[0].contentBoxSize[0].blockSize == 0) OBSERVER.unobserve((POPOVER.hidePopover(), POPOVER)); }); document.querySelector('button').onclick = () => OBSERVER.observe(POPOVER); The observer will know when the popover’s CSS height reaches zero at the end of the transition, and, at that point, the popover is closed with hidePopover(). From there, the observer is stopped with unobserve().
    In our example, height and ResizeObserver are used to auto-close the notification. You can try any other CSS property and JavaScript observer combination that might work with your preference. Learning about ResizeObserver and MutationObserver can help you find some options.
    Setting an HTML fallback
    When JavaScript is disabled in the browser, if the popover type is set to any of the light-dismissible types, it acts as a fallback. Keep the popover visible by overriding the style rules that hide it. The user can dismiss it by clicking or tapping anywhere outside the element.
    If the popover needs to be light-dismissible only when JavaScript is disabled, then include that popover inside a <noscript> element before the manual popover. It’s the same process as before, where you override CSS styles as needed.
    <noscript> <div popover="auto" id="pop">Bookmarked!</div> </noscript> <div popover="manual" id="pop">Bookmarked!</div> <!-- goes where <head> element's descendants go --> <noscript> <style> [popover] { transition: none; height: 1lh; } </style> </noscript> When to use this method?
    Another way to implement all of this would be to use setTimeout() to create a delay before closing the popover in JavaScript when the button is clicked, then adding a class to the popover element to trigger the transition effect. That way, no observer is needed.
    With the method covered in this post, the delay can be set and triggered in CSS itself, thanks to @starting-style and transition-delay — no extra class required! If you prefer to implement the delay through CSS itself, then this method works best. The JavaScript will catch up to the change CSS makes at the time CSS defines, not the other way around.
    Creating an Auto-Closing Notification With an HTML Popover originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
  3. by: Abhishek Prakash
    Sat, 07 Jun 2025 15:36:14 GMT

    The bare Raspberry Pi board has a different appeal but I prefer keeping my Pis under cover, in protective cases.
    Now, there are tons of interesting cases available. You can also build your own with a 3D printer.
    The official Raspberry Pi 5 case and other small box design cases are okay for protection and they don't cost much.
    Raspberry Pi 5 official case beside Pironman 5However, lately, I have been fascinated with the tower cases. With the semi-transparent design and RGB lightings, they look dope. Like those customized gaming rigs people spend hundreds of dollars on.
    Thankfully, the Raspberry Pi is a small device so their tower cases are also not that expensive.
    Let me share a few of such beautiful mini tower PC like protective cases you can get for your Raspberry Pi 5 in the buyer's guide.
    Pironman 5: Full mini PC experience
    Pironman 5 is the ultimate case that got me into the tower PC fetish. It's my prized Pi accessory, beautifully sitting there on my secondary work desk.
    The Pironman 5 case transforms your Raspberry Pi 5 into a sleek aluminum mini-tower with advanced cooling, NVMe M.2 SSD support, customizable RGB lighting, dual standard HDMI ports, and a secure power switch.
    Yes, you read that right. It upgrades your Pi 5's mini HDMI ports into full HDMI ports and also allows you to use NVMe M.2 SSD. Do check the list of supported SSDs.
    Key Features:
    Adds a NVMe M.2 slot for SSD Tower cooler Dual RGB fans with dust filters 0.96" OLED display showing real-time system metrics Safe shutdown functionality and IR receiver Dual full-size HDMI ports and external GPIO access Active support and community US duties and EU VAT included in the pricing 💸 Price: $79.99
    Get Pironman 5 from official websiteGet Pironman 5 from AmazonTom's Hardware found it could handle overclocked Pi 5s at 3GHz while maintaining excellent temperatures. I didn't do such extensive testing but you can still read my full experience of Pironman 5 in the review I did earlier.
    Pironman 5 Review: Best Raspberry Pi 5 Case You Can getIt’s a cooling case with RGB lighting but it turns your Raspberry Pi into a mini PC.It's FOSSAbhishek PrakashPironman 5 Max: NAS/AI option
    Pironman 5 Max is a slight upgrade to the previous entry. What's different here? Well, it primarily adds an additional NVMe M.2 slot so that you can use it as NAS RAID 0/1 setup or add Hailo-8L AI accelerator.
    There might be a few small differences, like the OLED screen has the tap to wake feature, but the main difference is that Pironman 5 Max has an additional NVMe slot. Oh, the black design gives it a more badass look.
    Key Features:
    Dual expandable NVMe M.2 slots with RAID 0/1 support AI accelerator compatibility (e.g., Hailo-8L) for advanced edge AI applications Smart OLED display with vibration wake-up and tap-to-wake functionality Advanced cooling with tower cooler and dual RGB fans Sleeker black aluminum chassis with semi-transparent panels Dual full-size HDMI ports and external GPIO access Active support and community Safe shutdown functionality and IR receiver 💸 Price: $94.99 (Early bird: $71.24 for first 500 units)
    Clearly, it is suitable for NAS builds, AI edge computing, and Home Assistant hubs.
    💡 And at the moment, the pre-order discount makes it cheaper than its predecessor. Grab it before the pricing goes back to normal.
    Get Pironman 5 Max from official websiteGeeekPi Tower Kit: Classic Pi plus M.2 NVMe
    The GeeekPi Tower kit comes into two variants: with and without N07 M.2 NVMe SSD PCIe peripheral.
    The design is not a lot different from Pironman cases, at least from the outside. But here, you DO NOT get full HDMI slots. You access the usual Pi 5 ports. That makes it cheaper than Pironman cases.
    You have one Ice tower cooler with RGB lights to keep the Pi cool.
    Key Features:
    ICE Tower Cooler with LED fan for effective temperature control 0.96" OLED screen for displaying system status information Two acrylic panels offering clear view of internal components N07 M.2 NVMe support in the upgraded model RGB lighting that cycles through colors Regular Pi 5 ports, no full HDMI slots 💸 Price: $49 for the basic model
    Get GeeekPi Tower Kit from AmazonYahboom CUBE Pi: Boxed Tower
    Ignore the quirky Yahboom brand name ;)
    The CUBE Pi features a boxy aluminum alloy construction with 270° panoramic view that clearly displays internal components.
    There is only one fan with blue light at the top but it has ducts at top and bottom for better ventilation. The top is covered by a magnetic mesh.
    You also get programmable RGB lighting to add the oomph factor. The mini-HDMI ports are converted into full HDMI, so that's a good thing.
    There is an OLED display to show you the system stats hidden inside the case instead of being on the exterior.
    The case has enough space for adding an active radiator or M.2 SSD, you have to make those purchases separately.
    Key Features:
    Metal chassis with three highly transparent acrylic side plates offering 270° panoramic view Blue light cooling fan with dual cooling ducts Full HDMI ports Dust-proof magnetic nets to effectively block dust intrusion RGB lighting OLED display inside the case Scope for NVMe M.2 SSD slot (sold separately) 💸 Price: ~$49
    Get CUBE PI from AmazonElectroCookie: The Minimalist Champion
    Sometimes less is more. ElectroCookie's aluminum mini tower combines a large heat dissipation structure with an RGB-lit PWM fan that automatically adjusts speed based on CPU temperature.
    There is scope for the NVMe SSD HAT but you have to purchase it separately. There is a separate model that comes with the HAT.
    And that's it. It's just a case and doesn't add extra ports or slots to it. There is no OLED display, either.
    However, the case comes in five different colors to choose from. Now that's something, right?
    Key Features:
    Large active cooler with RGB PWM fan Compatible M.2 HAT NVMe SSD support (sold separately) Easy access to GPIO pins, SD card slot, and all ports Soft-touch power button Available in silver, black, red, blue and pink colors0-40 (M.2 HAT sold separately) Price: ~$32
    Get ElectroCookie from AmazonWhich one to choose?
    Pick Pironman 5 if you want the complete package with professional features and don't mind paying premium pricing.
    Pick Pironman 5 Max if you need extra storage slot for a NAS or AI options to an overall mini PC build and don't mind the price tag.
    GeeekPi if you want a cool looking mini tower PC with focus on tower cooling and not focused on additional slots.
    Pick Yahboom if you don't necessarily want extra features but agree to pay a premium price for just a beautiful RGB lit tower case.
    Pick ElectroCookie if you want a tower case in your choice of color and don't need fancy features to keep the pricing in check.
    All these cases transform your Pi 5 from exposed board to desktop-class computer. Well, a miniature desktop computer.
    The cooling performance across all options is pretty good - you cannot function a Raspberry Pi as a desktop computer without proper thermal management.
    I am a fan of the Pironman cases. They are on the expensive side when compared to the rest but they also provide more features than the rest of the lot.
  4. by: Abhishek Prakash
    Fri, 06 Jun 2025 20:40:46 +0530

    /* Catppuccin Mocha Dark Theme Colors */ :root { --ctp-base: #1e1e2e; --ctp-mantle: #181825; --ctp-crust: #11111b; --ctp-surface0: #313244; --ctp-surface1: #45475a; --ctp-surface2: #585b70; --ctp-overlay0: #6c7086; --ctp-overlay1: #7f849c; --ctp-overlay2: #9399b2; --ctp-text: #cdd6f4; --ctp-subtext0: #a6adc8; --ctp-subtext1: #bac2de; --ctp-blue: #89b4fa; --ctp-green: #a6e3a1; --ctp-red: #f38ba8; --ctp-mauve: #cba6f7; --ctp-peach: #fab387; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; background-color: var(--ctp-base); color: var(--ctp-text); line-height: 1.6; min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 20px; } .container { width: 100%; max-width: 1200px; background-color: var(--ctp-mantle); border-radius: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5); overflow: hidden; } .header { background-color: var(--ctp-crust); padding: 20px; text-align: center; border-bottom: 1px solid var(--ctp-surface0); } h1 { font-size: 24px; font-weight: 600; color: var(--ctp-mauve); display: flex; align-items: center; justify-content: center; gap: 10px; } .arrow { color: var(--ctp-blue); font-size: 20px; } .controls { display: flex; justify-content: center; gap: 20px; padding: 20px; background-color: var(--ctp-mantle); border-bottom: 1px solid var(--ctp-surface0); } button { background-color: var(--ctp-surface0); color: var(--ctp-text); border: none; padding: 10px 24px; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.3s ease; display: flex; align-items: center; gap: 8px; } button:hover { background-color: var(--ctp-surface1); transform: translateY(-1px); } button:active { transform: translateY(0); } button.primary { background-color: var(--ctp-blue); color: var(--ctp-crust); } button.primary:hover { background-color: #7aa2f7; } button.secondary { background-color: var(--ctp-green); color: var(--ctp-crust); } button.secondary:hover { background-color: #94e089; } .editor-container { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; padding: 20px; min-height: 400px; } .editor-section { display: flex; flex-direction: column; gap: 10px; } .editor-header { display: flex; justify-content: space-between; align-items: center; padding: 10px 15px; background-color: var(--ctp-surface0); border-radius: 8px 8px 0 0; } .editor-title { font-size: 14px; font-weight: 600; color: var(--ctp-subtext1); text-transform: uppercase; letter-spacing: 0.5px; } .copy-btn { background-color: transparent; padding: 6px 12px; font-size: 12px; color: var(--ctp-overlay2); border: 1px solid var(--ctp-surface1); } .copy-btn:hover { background-color: var(--ctp-surface1); color: var(--ctp-text); border-color: var(--ctp-surface2); } .copy-btn.copied { color: var(--ctp-green); border-color: var(--ctp-green); } textarea { flex: 1; background-color: var(--ctp-crust); color: var(--ctp-text); border: 1px solid var(--ctp-surface0); border-radius: 0 0 8px 8px; padding: 15px; font-family: 'Fira Code', 'Courier New', monospace; font-size: 14px; line-height: 1.5; resize: none; outline: none; transition: border-color 0.3s ease; } textarea:focus { border-color: var(--ctp-blue); } .error { position: fixed; bottom: 20px; right: 20px; background-color: var(--ctp-red); color: var(--ctp-crust); padding: 12px 20px; border-radius: 8px; font-size: 14px; font-weight: 500; box-shadow: 0 4px 12px rgba(243, 139, 168, 0.3); animation: slideIn 0.3s ease; z-index: 1000; } @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } @media (max-width: 768px) { .editor-container { grid-template-columns: 1fr; } .controls { flex-wrap: wrap; } button { font-size: 13px; padding: 8px 16px; } } /* Custom scrollbar */ textarea::-webkit-scrollbar { width: 8px; } textarea::-webkit-scrollbar-track { background: var(--ctp-crust); } textarea::-webkit-scrollbar-thumb { background: var(--ctp-surface1); border-radius: 4px; } textarea::-webkit-scrollbar-thumb:hover { background: var(--ctp-surface2); } YAML ↔ JSON Converter
    → YAML to JSON ← JSON to YAML ✕ Clear All YAML Copy JSON Copy
  5. by: Temani Afif
    Fri, 06 Jun 2025 13:52:42 +0000

    If you’re following along, this is the third post in a series about the new CSS shape() function. We’ve learned how to draw lines and arcs and, in this third part, I will introduce the curve command — the missing command you need to know to have full control over the shape() function. In reality, there are more commands, but you will rarely need them and you can easily learn about them later by checking the documentation.
    Better CSS Shapes Using shape()
    Lines and Arcs More on Arcs Curves (you are here!) The curve command
    This command adds a Bézier curve between two points by specifying control points. We can either have one control point and create a Quadratic curve or two control points and create a Cubic curve.
    For many of you, that definition is simply unclear, or even useless! You can spend a few minutes reading about Bézier curves but is it really worth it? Probably not, unless your job is to create shapes all the day and you have a solid background in geometry.
    We already have cubic-bezier() as an easing function for animations but, honestly, who really understands how it works? We either rely on a generator to get the code or we read a “boring” explanation that we forget in two minutes. (I have one right here by the way!)
    Don’t worry, this article will not be boring as I will mostly focus on practical examples and more precisely the use case of rounding the corners of irregular shapes. Here is a figure to illustrate a few examples of Bézier curves.
    The blue dots are the starting and ending points (let’s call them A and B) and the black dots are the control points. And notice how the curve is tangent to the dashed lines illustrated in red.
    In this article, I will consider only one control point. The syntax will follow this pattern:
    clip-path: shape( from Xa Ya, curve to Xb Yb with Xc Yc ); arc command vs. curve command
    We already saw in Part 1 and Part 2 that the arc command is useful establishing rounded edges and corners, but it will not cover all the cases. That’s why you will need the curve command. The tricky part is to know when to use each one and the answer is “it depends.” There is no generic rule but my advice is to first see if it’s possible (and easy) using arc. If not, then you have to use curve.
    For some shapes, we can have the same result using both commands and this is a good starting point for us to understand the curve command and compare it with arc.
    Take the following example:
    CodePen Embed Fallback This is the code for the first shape:
    .shape { clip-path: shape(from 0 0, arc to 100% 100% of 100% cw, line to 0 100%) } And for the second one, we have this:
    .shape { clip-path: shape(from 0 0, curve to 100% 100% with 100% 0, line to 0 100%) } The arc command needs a radius (100% in this case), but the curve command needs a control point (which is 100% 0 in this example).
    Now, if you look closely, you will notice that both results aren’t exactly the same. The first shape using the arc command is creating a quarter of a circle, whereas the shape using the curve command is slightly different. If you place both of them above each other, you can clearly see the difference.
    CodePen Embed Fallback This is interesting because it means we can round some corners using either an arc or a curve, but with slightly different results. Which one is better, you ask? I would say it depends on your visual preference and the shape you are creating.
    In Part 1, we created rounded tabs using the arc command, but we can also create them with curve.
    CodePen Embed Fallback Can you spot the difference? It’s barely visible but it’s there.
    Notice how I am using the by directive the same way I am doing with arc, but this time we have the control point, which is also relative. This part can be confusing, so pay close attention to this next bit.
    Consider the following:
    shape(from Xa Ya, curve by Xb Yb with Xc Yc) It means that both (Xb,Yb) and (Xc,Yc) are relative coordinates calculated from the coordinate of the starting point. The equivalent of the above using a to directive is this:
    shape(from Xa Ya, curve to (Xa + Xb) (Ya + Yb) with (Xa + Xc) (Yb + Yc)) We can change the reference of the control point by adding a from directive. We can either use start (the default value), end, or origin.
    shape(from Xa Ya, curve by Xb Yb with Xc Yc from end) The above means that the control point will now consider the ending point instead of the starting point. The result is similar to:
    shape(from Xa Ya, curve to (Xa + Xb) (Ya + Yb) with (Xa + Xb + Xc) (Ya + Yb + Yc)) If you use origin, the reference will be the origin, hence the coordinate of the control point becomes absolute instead of relative.
    The from directive may add some complexity to the code and the calculation, so don’t bother yourself with it. Simply know it exists in case you face it, but keep using the default value.
    I think it’s time for your first homework! Similar to the rounded tab exercise, try to create the inverted radius shape we covered in the Part 1 using curve instead of arc. Here are both versions for you to reference, but try to do it without peeking first, if you can.
    CodePen Embed Fallback Let’s draw more shapes!
    Now that we have a good overview of the curve command, let’s consider more complex shapes where arc won’t help us round the corners and the only solution is to draw curves instead. Considering that each shape is unique, so I will focus on the technique rather than the code itself.
    Slanted edge
    Let’s start with a rectangular shape with a slanted edge.
    Getting the shape on the left is quite simple, but the shape on the right is a bit tricky. We can round two corners with a simple border-radius, but for the slanted edge, we will use shape() and two curve commands.
    The first step is to write the code of the shape without rounded corners (the left one) which is pretty straightforward since we’re only working with the line command:
    .shape { --s: 90px; /* slant size */ clip-path: shape(from 0 0, line to calc(100% - var(--s)) 0, line to 100% 100%, line to 0 100% ); } Then we take each corner and try to round it by modifying the code. Here is a figure to illustrate the technique I am going to use for each corner.
    We define a distance, R, that controls the radius. From each side of the corner point, I move by that distance to create two new points, which are illustrated above in red. Then, I draw my curve using the new points as starting and ending points. The corner point will be the control point.
    The code becomes:
    .shape { --s: 90px; /* slant size */ clip-path: shape(from 0 0, Line to Xa Ya, curve to Xb Yb with calc(100% - var(--s)) 0, line to 100% 100%, line to 0 100% ); } Notice how the curve is using the coordinates of the corner point in the with directive, and we have two new points, A and B.
    Until now, the technique is not that complex. For each corner point, you replace the line command with line + curve commands where the curve command reuses the old point in its with directive.
    If we apply the same logic to the other corner, we get the following:
    .shape { --s: 90px; /* slant size */ clip-path: shape(from 0 0, line to Xa Ya, curve to Xb Yb with calc(100% - var(--s)) 0, line to Xc Yc, curve to Xd Yd with 100% 100%, line to 0 100% ); } Now we need to calculate the coordinates of the new points. And here comes the tricky part because it’s not always simple and it may require some complex calculation. Even if I detail this case, the logic won’t be the same for the other shapes we’re making, so I will skip the math part and give you the final code:
    .box { --h: 200px; /* element height */ --s: 90px; /* slant size */ --r: 20px; /* radius */ height: var(--h); border-radius: var(--r) 0 0 var(--r); --_a: atan2(var(--s), var(--h)); clip-path: shape(from 0 0, line to calc(100% - var(--s) - var(--r)) 0, curve by calc(var(--r) * (1 + sin(var(--_a)))) calc(var(--r) * cos(var(--_a))) with var(--r) 0, line to calc(100% - var(--r) * sin(var(--_a))) calc(100% - var(--r) * cos(var(--_a))), curve to calc(100% - var(--r)) 100% with 100% 100%, line to 0 100% ); } I know the code looks a bit scary, but the good news is that the code is also really easy to control using CSS variables. So, even if the math is not easy to grasp, you don’t have to deal with it. It should be noted that I need to know the height to be able to calculate the coordinates which means the solution isn’t perfect because the height is a fixed value.
    CodePen Embed Fallback Arrow-shaped box
    Here’s a similar shape, but this time we have three corners to round using the curve command.
    CodePen Embed Fallback The final code is still complex but I followed the same steps. I started with this:
    .shape { --s: 90px; clip-path: shape(from 0 0, /* corner #1 */ line to calc(100% - var(--s)) 0, /* corner #2 */ line to 100% 50%, /* corner #3 */ line to calc(100% - var(--s)) 100%, line to 0 100% ); } Then, I modified it into this:
    .shape { --s: 90px; clip-path: shape(from 0 0, /* corner #1 */ line to Xa Ya curve to Xb Yb with calc(100% - var(--s)) 0, /* corner #2 */ line to Xa Ya curve to Xb Yb with 100% 50%, /* corner #3 */ line to Xa Yb curve to Xb Yb with calc(100% - var(--s)) 100%, line to 0 100% ); } Lastly, I use a pen and paper to do all the calculations.
    You might think this technique is useless if you are not good with math and geometry, right? Not really, because you can still grab the code and use it easily since it’s optimized using CSS variables. Plus, you aren’t obligated to be super accurate and precise. You can rely on the above technique and use trial and error to approximate the coordinates. It will probably take you less time than doing all the math.
    Rounded polygons
    I know you are waiting for this, right? Thanks to the new shape() and the curve command, we can now have rounded polygon shapes!
    Here is my implementation using Sass where you can control the radius, number of sides and the rotation of the shape:
    CodePen Embed Fallback If we omit the complex geometry part, the loop is quite simple as it relies on the same technique with a line + curve per corner.
    $n: 9; /* number of sides*/ $r: .2; /* control the radius [0 1] */ $a: 15deg; /* control the rotation */ .poly { aspect-ratio: 1; $m: (); @for $i from 0 through ($n - 1) { $m: append($m, line to Xai Yai, comma); $m: append($m, curve to Xbi Ybi with Xci Yci, comma); } clip-path: shape(#{$m}); } Here is another implementation where I define the variables in CSS instead of Sass:
    CodePen Embed Fallback Having the variables in CSS is pretty handy especially if you want to have some animations. Here is an example of a cool hover effect applied to hexagon shapes:
    CodePen Embed Fallback I have also updated my online generator to add the radius parameter. If you are not familiar with Sass, you can easily copy the CSS code from there. You will also find the border-only and cut-out versions!
    Conclusion
    Are we done with the curve command? Probably not, but we have a good overview of its potential and all the complex shapes we can build with it. As for the code, I know that we have reached a level that is not easy for everyone. I could have extended the explanation by explicitly breaking down the math, but then this article would be overly complex and make it seem like using shape() is harder than it is.
    This said, most of the shapes I code are available within my online collection that I constantly update and optimize so you can easily grab the code of any shape!
    If you want a good follow-up to this article, I wrote an article for Frontend Masters where you can create blob shapes using the curve command.
    Better CSS Shapes Using shape()
    Lines and Arcs More on Arcs Curves (you are here!) Better CSS Shapes Using shape() — Part 3: Curves originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
  6. by: Abhishek Prakash
    Fri, 06 Jun 2025 17:33:26 +0530

    Lesser known... that's the theme of this week's newsletter. Hope you like it 😄
    Here are the highlights of this edition :
    Lesser known mouse mode in Vim Lesser known dir command in Linux Lesser known special file permissions And your regular dose of better known memes, tips and news ;) 🚀 Level up your coding skills and build your own bots
    Harness the power of machine learning to create digital agents and more with hot courses like Learning LangChain, The Developer's Playbook for Large Language Model Security, Designing Large Language Model Applications, and more.
    Part of the purchase goes to Code for America! Check out the ebook bundle here.
    Humble Tech Book Bundle: Machine Learning, AI, and Bots by O’Reilly 2025Master machine learning with this comprehensive library of coding and programming courses from the pros at O’Reilly.Humble Bundle  
     
      This post is for subscribers only
    Subscribe now Already have an account? Sign in
  7. By: Linux.com Editorial Staff
    Fri, 06 Jun 2025 10:53:28 +0000

    This article was contributed by Vedrana Vidulin, Head of Responsible AI Unit at Intellias (LinkedIn).
    As AI becomes central to smart devices, embedded systems, and edge computing, the ability to run language models locally — without relying on the cloud — is essential. Whether it’s for reducing latency, improving data privacy, or enabling offline functionality, local AI inference opens up new opportunities across industries. LiteLLM offers a practical solution for bringing large language models to resource-constrained devices, bridging the gap between powerful AI tools and the limitations of embedded hardware.
    Deploying LiteLLM, an open source LLM gateway, on embedded Linux unlocks the ability to run lightweight AI models in resource-constrained environments. Acting as a flexible proxy server, LiteLLM provides a unified API interface that accepts OpenAI-style requests — allowing you to interact with local or remote models using a consistent developer-friendly format. This guide walks you through everything from installation to performance tuning, helping you build a reliable, lightweight AI system on embedded Linux distribution.
    Setup checklist
    Before you start, here’s what’s required:
    A device running a Linux-based operating system (Debian) with sufficient computational resources to handle LLM operations.​ Python 3.7 or higher installed on the device.​ Access to the internet for downloading necessary packages and models. Step-by-Step Installation
    Step 1: Install LiteLLM
    First, we make sure the device is up to date and ready for installation. Then we install LiteLLM in a clean and safe environment.

    Update the package lists to ensure access to the latest software versions:
    sudo apt-get update Check if pip (Python Package Installer) is installed:
    pip –version If not, install it using:
    sudo apt-get install python3-pip It is recommended to use a virtual environment. Check if venv is installed:
    dpkg -s python3-venv | grep “Status: install ok installed” If venv is intalled the output would be “Status: install ok installed”. If not installed:
    sudo apt install python3-venv -y Create and activate virtual environment:
    python3 -m venv litellm_envsource litellm_env/bin/activate Use pip to install LiteLLM along with its proxy server component:
    pip install ‘litellm[proxy]’ Use LiteLLM within this environment. To deactivate the virtual environment type deactivate.
    Step 2: Configure LiteLLM
    With LiteLLM installed, the next step is to define how it should operate. This is done through a configuration file, which specifies the language models to be used and the endpoints through which they’ll be served.

    Navigate to a suitable directory and create a configuration file named config.yaml:
    mkdir ~/litellm_configcd ~/litellm_confignano config.yaml In config.yaml specify the models you intend to use. For example, to configure LiteLLM to interface with a model served by Ollama:
    model_list:  – model_name: codegemma litellm_params:   model: ollama/codegemma:2b   api_base: http://localhost:11434 This configuration maps the model name codegemma to the codegemma:2b model served by Ollama at http://localhost:11434.
    Step 3: Serve models with Ollama
    To run your AI model locally, you’ll use a tool called Ollama. It’s designed specifically for hosting large language models (LLMs) directly on your device — without relying on cloud services.

    To get started, install Ollama using the following command:
    curl -fsSL https://ollama.com/install.sh | sh This command downloads and runs the official installation script, which automatically starts the Ollama server.

    Once installed, you’re ready to load the AI model you want to use. In this example, we’ll pull a compact model called codegemma:2b.
    ollama pull codegemma:2b After the model is downloaded, the Ollama server will begin listening for requests — ready to generate responses from your local setup.
    Step 4: Launch the LiteLLM proxy server
    With both the model and configuration ready, it’s time to start the LiteLLM proxy server — the component that makes your local AI model accessible to applications.
    To launch the server, use the command below:
    litellm –config ~/litellm_config/config.yaml The proxy server will initialize and expose endpoints defined in your configuration, allowing applications to interact with the specified models through a consistent API.
    Step 5: Test the deployment
    Let’s confirm if everything works as expected. Write a simple Python script that sends a test request to the LiteLLM server and save it as test_script.py:
    import openai client = openai.OpenAI(api_key=“anything”, base_url=“http://localhost:4000“)response = client.chat.completions.create(    model=“codegemma”,    messages=[{“role”: “user”, “content”: “Write me a Python function to calculate the nth Fibonacci number.”}])print(response)  Finally, run the script using this command:
    python3 ./test_script.py If the setup is correct, you’ll receive a response from the local model — confirming that LiteLLM is up and running.

    Optimize LiteLLM performance on embedded devices

    To ensure fast, reliable performance on embedded systems, it’s important to choose the right language model and adjust LiteLLM’s settings to match your device’s limitations.
    Choosing the Right Language Model
    Not every AI model is built for devices with limited resources — some are just too heavy. That’s why it’s crucial to go with compact, optimized models designed specifically for such environments:​
    DistilBERT – a distilled version of BERT, retaining over 95% of BERT’s performance with 66 million parameters. It’s suitable for tasks like text classification, sentiment analysis, and named entity recognition. TinyBERT – with approximately 14.5 million parameters, TinyBERT is designed for mobile and edge devices, excelling in tasks such as question answering and sentiment classification. MobileBERT – optimized for on-device computations, MobileBERT has 25 million parameters and achieves nearly 99% of BERT’s accuracy. It’s ideal for mobile applications requiring real-time processing. TinyLlama – a compact model with approximately 1.1 billion parameters, TinyLlama balances capability and efficiency, making it suitable for real-time natural language processing in resource-constrained environments. MiniLM – a compact transformer model with approximately 33 million parameters, MiniLM is effective for tasks like semantic similarity and question answering, particularly in scenarios requiring rapid processing on limited hardware. Selecting a model that fits your setup isn’t just about saving space — it’s about ensuring smooth performance, fast responses, and efficient use of your device’s limited resources.
    Configure settings for better performance
    A few small adjustments can go a long way when you’re working with limited hardware. By fine-tuning key LiteLLM settings, you can boost performance and keep things running smoothly.
    Restrict the number of tokens

    Shorter responses mean faster results. Limiting the maximum number of tokens in response can reduce memory and computational load. In LiteLLM, this can be achieved by setting the max_tokens parameter when making API calls. For example:​
    import openai client = openai.OpenAI(api_key=“anything”, base_url=“http://localhost:4000“)response = client.chat.completions.create(    model=“codegemma”,    messages=[{“role”: “user”, “content”: “Write me a Python function to calculate the nth Fibonacci number.”}],    max_tokens=500 # Limits the response to 500 tokens)print(response)  Adjusting max_tokens helps keep replies concise and reduces the load on your device.
    Managing simultaneous requests
    If too many requests hit the server at once, even the best-optimized model can get bogged down. That’s why LiteLLM includes an option to limit how many queries it processes at the same time. For instance, you can restrict LiteLLM to handle up to 5 concurrent requests by setting max_parallel_requests as follows:
    litellm –config ~/litellm_config/config.yaml –num_requests 5 This setting helps distribute the load evenly and ensures your device stays stable — even during periods of high demand.
    A Few More Smart Moves

    Before going live with your setup, here are two additional best practices worth considering:
    Secure your setup – implement appropriate security measures, such as firewalls and authentication mechanisms, to protect the server from unauthorized access. Monitor performance – use LiteLLM’s logging capabilities to track usage, performance, and potential issues. LiteLLM makes it possible to run language models locally, even on low-resource devices. By acting as a lightweight proxy with a unified API, it simplifies integration while reducing overhead. With the right setup and lightweight models, you can deploy responsive, efficient AI solutions on embedded systems — whether for a prototype or a production-ready solution.
    Summary 
    Running LLMs on embedded devices doesn’t necessarily require heavy infrastructure or proprietary services. LiteLLM offers a streamlined, open-source solution for deploying language models with ease, flexibility, and performance — even on devices with limited resources. With the right model and configuration, you can power real-time AI features at the edge, supporting everything from smart assistants to secure local processing.
    Join Our Community
    We’re continuously exploring the future of tech, innovation, and digital transformation at Intellias — and we invite you to be part of the journey.
    Visit our Intellias Blog and dive deeper into industry insights, trends, and expert perspectives. This article was written by Vedrana Vidulin, Head of Responsible AI Unit at Intellias. Connect with Vedrana through her LinkedIn page.  The post How to Deploy Lightweight Language Models on Embedded Linux with LiteLLM appeared first on Linux.com.
  8. by: Abhishek Prakash
    Fri, 06 Jun 2025 16:15:07 +0530

    Think of Vim tabs like browser tabs for your code editor - each tab holds one or more windows, letting you organize multiple files into logical workspaces.
    Unlike window splits that divide your screen, tabs stack contexts you can flip between instantly.
    Three files opened in separate tabs in VimLet's see how you can use tabs in Vim.
    Essential Vim tab commands at a glance
    Here are the most common actions you can use while dealing with tabs in Vim.
    Command Action Memory Hook vim -p file1 file2 Opens files in tabs Vim in pages :tabnew filename Open file in new tab Tab new :tabedit filename Open file for editing in new tab Tab edit gt Next tab Go to next gT Previous tab Go to previous {n}gt Jump to tab number n Go to specific :tabfirst Jump to first tab Self-explanatory :tabclast Jump to last tab Self-explanatory :tabclose Close current tab Self-explanatory :tabonly Close all other tabs Keep only this :tabs List all tabs Show tabs Interesting, right? Let's see it in details.
    Opening files in tabs in Vim
    Let's start by opening files in tabs first.
    Start Vim with multiple files opened in tabs
    Launch Vim with multiple tabs instantly:
    vim -p file1.py file2.py file3.py 0:00 /0:13 1× Open two existing files in tabs while starting Vim
    How can you open just one file in tab? Well... if it's one file, what's the point of tab, right?
    📋Vim tabs aren't file containers - they're viewport organizers. Each tab can hold multiple split windows, making tabs perfect for grouping related files by project, feature, or context. It's like having separate desks for different projects.Open a file in a new tab in the current Vim session
    When you are already inside Vim and want to open a file in a new tab, switch to normal mode by pressing Esc key and use the command:
    :tabnew filenameThis will load the file in a new tab. If the file doesn't exist, it will create a new one.
    Filename is optional. If you don't provide it, it will open a new file without any name:
    :tabnew 0:00 /0:11 1× Opening existing or new files in tabs from existing Vim session
    💡If you use tabedit instead of tabnew, it open the file in Edit mode (insert mode) in the new tab.Search for files and open them in tabs
    Search the current directory for filename matching the given pattern and open it in a new tab:
    :tabf filename*This only works if the search results into a single file. If there are more than one file matched, it will throw an error:
    E77: Too many file names💡While you can open as many tabs as you want, only 10 tabs are shown by default. You can change this by setting tabpagemax in your vimrc to something like set tabpagemax=12Navigating between tabs
    You can move between opened tabs using:
    :tabn: for next tab :tabp: for previous tab Typing the commands could be tedious, so you can use the following key combinations in the nomral mode:
    gt: To go to the next tab gT (i.e. press g and shift and t keys together) To go to the previous tab If there are too many tabs opened, you can use:
    :tabfirst: Jump to first tab :tablast: Jump to last tab 💡You can enable mouse mode in Vim and that makes navigating between tabs easier with mouse clicks.In many distributions these days, Vim is preconfigured to show the tab labels on the top. If that's not the case, add this to your vimrc:
    set showtabline=2You can list all the opened tabs with:
    :tabs💡If you are particular about putting the opened tabs in specific order, you can move the current tab to Nth position with :tabm N. This tabm is short for tabmove. Note that Vim starts numbering at 0.Closing tabs
    How do you close a tab? If the tab has a single filed opened, the regular save/exit Vim commands work.
    But it will be an issue if you have multiple split windows opened in a tab.
    :tabclose: Close current tab :tabonly: Only keep the current tab opened, close all others 0:00 /0:14 1× Tab closing operation in Vim
    💡Accidentally closed a tab? :tabnew | u creates a new tab and undoes in one motion - your file returns.Bulk tab operations
    With :tabdo command, you can run the same operations in all the tabs.
    For example, :tabdo w will save file changes in all tabs, :tabdo normal! gg=G auto-indents every file.
    Similarly, tabdo %s/oldvar/newvar/g executes search-replace across every tab simultaneously. Parallel processing for repetitive changes.
    You get the idea. tabdo is the key here.
    💡You can save your meticulously crafted tab layout. :mksession project.vim then vim -S project.vim restores exact tab layout.Conclusion
    While it is good to enjoy tabs in Vim, don't create dozens of them - they become harder to navigate than helpful. Use buffers for file switching and tabs for context switching.
    As you can see, with the tab feature, you get one inch closer to having the IDE like experience in Vim.
  9. by: Daniel Schwarz
    Thu, 05 Jun 2025 13:45:56 +0000

    In many countries, web accessibility is a human right and the law, and there can be heavy fines for non-compliance. Naturally, this means that text and icons and such must have optimal color contrast in accordance with the benchmarks set by the Web Content Accessibility Guidelines (WCAG). Now, there are quite a few color contrast checkers out there (Figma even has one built-in now), but the upcoming contrast-color() function doesn’t check color contrast, it outright resolves to either black or white (whichever one contrasts the most with your chosen color).
    Right off the bat, you should know that we’ve sorta looked at this feature before. Back then, however, it was called color-contrast() instead of contrast-color() and had a much more convoluted way of going about things. It was only released in Safari Technology Preview 122 back in 2021, and that’s still the case at the time I’m writing this (now at version 220).
    You’d use it like this:
    button { --background-color: darkblue; background-color: var(--background-color); color: contrast-color(var(--background-color)); } CodePen Embed Fallback Here, contrast-color() has determined that white contrasts with darkblue better than black does, which is why contrast-color() resolves to white. Pretty simple, really, but there are a few shortcomings, which includes a lack of browser support (again, it’s only in Safari Technology Preview at the moment).
    We can use contrast-color() conditionally, though:
    @supports (color: contrast-color(red)) { /* contrast-color() supported */ } @supports not (color: contrast-color(red)) { /* contrast-color() not supported */ } The shortcomings of contrast-color()
    First, let me just say that improvements are already being considered, so here I’ll explain the shortcomings as well as any improvements that I’ve heard about.
    Undoubtedly, the number one shortcoming is that contrast-color() only resolves to either black or white. If you don’t want black or white, well… that sucks. However, the draft spec itself alludes to more control over the resolved color in the future.
    But there’s one other thing that’s surprisingly easy to overlook. What happens when neither black nor white is actually accessible against the chosen color? That’s right, it’s possible for contrast-color() to just… not provide a contrasting color. Ideally, I think we’d want contrast-color() to resolve to the closest accessible variant of a preferred color. Until then, contrast-color() isn’t really usable.
    Another shortcoming of contrast-color() is that it only accepts arguments of the <color> data type, so it’s just not going to work with images or anything like that. I did, however, manage to make it “work” with a gradient (basically, two instances of contrast-color() for two color stops/one linear gradient):
    CodePen Embed Fallback <button> <span>A button</span> </button> button { background: linear-gradient(to right, red, blue); span { background: linear-gradient(to right, contrast-color(red), contrast-color(blue)); color: transparent; background-clip: text; } } The reason this looks so horrid is that, as mentioned before, contrast-color() only resolves to black or white, so in the middle of the gradient we essentially have 50% grey on purple. This problem would also get solved by contrast-color() resolving to a wider spectrum of colors.
    But what about the font size? As you might know already, the criteria for color contrast depends on the font size, so how does that work? Well, at the moment it doesn’t, but I think it’s safe to assume that it’ll eventually take the font-size into account when determining the resolved color. Which brings us to APCA.
    APCA (Accessible Perceptual Contrast Algorithm) is a new algorithm for measuring color contrast reliably. Andrew Somers, creator of APCA, conducted studies (alongside many other independent studies) and learned that 23% of WCAG 2 “Fails” are actually accessible. In addition, an insane 47% of “Passes” are inaccessible.
    Not only should APCA do a better job, but the APCA Readability Criterion (ARC) is far more nuanced, taking into account a much wider spectrum of font sizes and weights (hooray for me, as I’m very partial to 600 as a standard font weight). While the criterion is expectedly complex and unnecessarily confusing, the APCA Contrast Calculator does a decent-enough job of explaining how it all works visually, for now.
    contrast-color() doesn’t use APCA, but the draft spec does allude to offering more algorithms in the future. This wording is odd as it suggests that we’ll be able to choose between the APCA and WCAG algorithms. Then again, we have to remember that the laws of some countries will require WCAG 2 compliance while others require WCAG 3 compliance (when it becomes a standard).
    That’s right, we’re a long way off of APCA becoming a part of WCAG 3, let alone contrast-color(). In fact, it might not even be a part of it initially (or at all), and there are many more hurdles after that, but hopefully this sheds some light on the whole thing. For now, contrast-color() is using WCAG 2 only.
    Using contrast-color()
    Here’s a simple example (the same one from earlier) of a darkblue-colored button with accessibly-colored text chosen by contrast-color(). I’ve put this darkblue color into a CSS variable so that we can define it once but reference it as many times as is necessary (which is just twice for now).
    button { --background-color: darkblue; background-color: var(--background-color); /* Resolves to white */ color: contrast-color(var(--background-color)); } And the same thing but with lightblue:
    button { --background-color: lightblue; background-color: var(--background-color); /* Resolves to black */ color: contrast-color(var(--background-color)); } First of all, we can absolutely switch this up and use contrast-color() on the background-color property instead (or in-place of any <color>, in fact, like on a border):
    button { --color: darkblue; color: var(--color); /* Resolves to white */ background-color: contrast-color(var(--color)); } Any valid <color> will work (named, HEX, RGB, HSL, HWB, etc.):
    button { /* HSL this time */ --background-color: hsl(0 0% 0%); background-color: var(--background-color); /* Resolves to white */ color: contrast-color(var(--background-color)); } Need to change the base color on the fly (e.g., on hover)? Easy:
    button { --background-color: hsl(0 0% 0%); background-color: var(--background-color); /* Starts off white, becomes black on hover */ color: contrast-color(var(--background-color)); &:hover { /* 50% lighter */ --background-color: hsl(0 0% 50%); } } CodePen Embed Fallback Similarly, we could use contrast-color() with the light-dark() function to ensure accessible color contrast across light and dark modes:
    :root { /* Dark mode if checked */ &:has(input[type="checkbox"]:checked) { color-scheme: dark; } /* Light mode if not checked */ &:not(:has(input[type="checkbox"]:checked)) { color-scheme: light; } body { /* Different background for each mode */ background: light-dark(hsl(0 0% 50%), hsl(0 0% 0%)); /* Different contrasted color for each mode */ color: light-dark(contrast-color(hsl(0 0% 50%)), contrast-color(hsl(0 0% 0%)); } } CodePen Embed Fallback The interesting thing about APCA is that it accounts for the discrepancies between light mode and dark mode contrast, whereas the current WCAG algorithm often evaluates dark mode contrast inaccurately. This one nuance of many is why we need not only a new color contrast algorithm but also the contrast-color() CSS function to handle all of these nuances (font size, font weight, etc.) for us.
    This doesn’t mean that contrast-color() has to ensure accessibility at the expense of our “designed” colors, though. Instead, we can use contrast-color() within the prefers-contrast: more media query only:
    button { --background-color: hsl(270 100% 50%); background-color: var(--background-color); /* Almost white (WCAG AA: Fail) */ color: hsl(270 100% 90%); @media (prefers-contrast: more) { /* Resolves to white (WCAG AA: Pass) */ color: contrast-color(var(--background-color)); } } Personally, I’m not keen on prefers-contrast: more as a progressive enhancement. Great color contrast benefits everyone, and besides, we can’t be sure that those who need more contrast are actually set up for it. Perhaps they’re using a brand new computer, or they just don’t know how to customize accessibility settings.
    Closing thoughts
    So, contrast-color() obviously isn’t useful in its current form as it only resolves to black or white, which might not be accessible. However, if it were improved to resolve to a wider spectrum of colors, that’d be awesome. Even better, if it were to upgrade colors to a certain standard (e.g., WCAG AA) if they don’t already meet it, but let them be if they do. Sort of like a failsafe approach? This means that web browsers would have to take the font size, font weight, element, and so on into account.
    To throw another option out there, there’s also the approach that Windows takes for its High Contrast Mode. This mode triggers web browsers to overwrite colors using the forced-colors: active media query, which we can also use to make further customizations. However, this effect is quite extreme (even though we can opt out of it using the forced-colors-adjust CSS property and use our own colors instead) and macOS’s version of the feature doesn’t extend to the web.
    I think that forced colors is an incredible idea as long as users can set their contrast preferences when they set up their computer or browser (the browser would be more enforceable), and there are a wider range of contrast options. And then if you, as a designer or developer, don’t like the enforced colors, then you have the option to meet accessibility standards so that they don’t get enforced. In my opinion, this approach is the most user-friendly and the most developer-friendly (assuming that you care about accessibility). For complete flexibility, there could be a CSS property for opting out, or something. Just color contrast by default, but you can keep the colors you’ve chosen as long as they’re accessible.
    What do you think? Is contrast-color() the right approach, or should the user agent bear some or all of the responsibility? Or perhaps you’re happy for color contrast to be considered manually?

    Exploring the CSS contrast-color() Function… a Second Time originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
  10. by: Juan Diego Rodríguez
    Thu, 05 Jun 2025 11:13:00 +0000

    The State of CSS 2025 Survey dropped a few days ago, and besides waiting for the results, it’s exciting to see a lot of the new things shipped to CSS over the past year reflected in the questions. To be specific, the next survey covers the following features:
    calc-size() shape() Scroll-driven animations Container scroll-state queries CSS Carousels text-box-edge and text-box-trim field-sizing ::target-text @function display: contents Advanced attr() if() sibling-index() and sibling-count() Again, a lot!
    However, I think the most important questions (regarding CSS) are asked at the end of each section. I am talking about the “What are your top CSS pain points related to ______?” questions. These sections are optional, but help user agents and the CSS Working Group know what they should focus on next.
    By nature of comments, those respondents with strong opinions are most likely to fill them in, skewing data towards issues that maybe the majority doesn’t have. So, even if you don’t have a hard-set view on a CSS pain point, I encourage you to fill them — even with your mild annoyances.
    The State of CSS 2025 Survey is out! originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
  11. by: Abhishek Prakash
    Thu, 05 Jun 2025 04:30:10 GMT

    There is some interesting news from this month's desktop Linux market share update.
    Linux has reached an all-time high market share of 2.69% in the latest Steam Survey. Also, CachyOS has found itself a spot in Linux-specific desktop market share in Steam Survey.
    💬 Let's see what else you get in this edition
    Ubuntu keyboard shortcuts. The World Bank open sourcing a tool. Swiss privacy debacle. Obsidian plugins suggestion. And other Linux news, tips, and, of course, memes! This edition of FOSS Weekly is supported by ANY.RUN. 🌟 OtterCookie: New Malware from North Korea Targets Tech and Finance Professionals
    Lazarus Group is currently distributing a stealer malware in fake job offer attacks. Here's how it goes:
    Lure via LinkedIn: Attackers offer freelance work to fix a minor DApp bug. Triggered Failure: An intentional app error fetches and executes malicious code from external API Malware Execution: OtterCookie infects the system, stealing victims' browser data and crypto wallets. Read detailed analysis on ANY.RUN's blog.
    OtterCookie: Analysis of New Lazarus Group MalwareExplore in-depth technical analysis of OtterCookie, a new North Korean Lazarus APT malware that steals victims’ crypto and credentials.ANY.RUN's Cybersecurity BlogMauro Eldritch📰 Linux and Open Source News
    The World Bank has open sourced Metadata Editor. KDE is getting its own GNOME Boxes counterpart. Ubuntu is adopting the monthly snapshots approach. Organic Maps has been forked over governance concerns. PeerTube is raising funds for further development of its mobile app. /e/OS 3.0 has debuted with refined parental controls and new privacy tools. A recent kernel drama sees Linus Torvalds catch a string of suspicious pull requests. Arch Linux is working on a way to handle sponsorships.
    Sponsorships Seem to Be Coming to Arch Linux!A proposal looks to introduce a transparent sponsorship process to Arch Linux.It's FOSS NewsSourav Rudra🧠 What We’re Thinking About
    Switzerland is going down a very dystopian path. I hope the law doesn't pass.
    No More Safe Haven for Privacy? Switzerland Drifts Toward a Surveillance State Due to New Controversial LawsProposed privacy law changes, if passed in parliament, threaten Switzerland’s reputation as a privacy haven.It's FOSS NewsGourav Patnaik🧮 Linux Tips, Tutorials and More
    You can easily run JavaScript in VS Code. Here are 13 tips and tweaks to get more out of Konsole. Tweaks to get more out of Nautilus file manager. Plugins to enhance your Obsidian knowledge base. If you are up for an experiment, then you could try running macOS on Linux. I Installed macOS on Linux in a VM (for fun sake)Installing macOS as a virtual machine in a Linux system? Well, let’s do it for the sake of some ‘virtual fun’It's FOSSPranav Krishna Desktop Linux is mostly neglected by the industry but loved by the community. For the past 12 years, It's FOSS has been helping people use Linux on their personal computers. And we are now facing the existential threat from AI models stealing our content.
    If you like what we do and would love to support our work, please become It's FOSS Plus member. It costs $24 a year (less than the cost of a burger meal each month) and you get an ad-free reading experience with the satisfaction of helping the desktop Linux community.
    Join It's FOSS Plus 👷 Homelab and Maker's Corner
    Looks like a cyberdeck. Works like a classroom. The CrowPi 3 surprised me with its versatility.
    CrowPi 3: An All-in-one AI Learning Kit With Cyberdeck FeelA Swiss Army knife for coding education as this kit transforms the programming concepts into tangible experiences. Learn from more than a hundred interactive projects.It's FOSSAbhishek Prakash✨ Project Highlight
    Markdown meets the power of LaTeX in this modern typesetting system with Quarkdown.
    GitHub - iamgio/quarkdown: 🪐 Markdown with superpowers — from ideas to presentations, articles and books.🪐 Markdown with superpowers — from ideas to presentations, articles and books. - iamgio/quarkdownGitHubiamgioHelwan Linux is a distro out of Egypt that feels quite nice.
    Helwan Linux: A Made-in-Egypt Linux DistributionCheck out what this distro out of Egypt has to offer.It's FOSS NewsGourav Patnaik📽️ Videos I am Creating for You
    Essential Ubuntu keyboard shortcuts in action in this week's video.
    Subscribe to It's FOSS YouTube Channel🧩 Quiz Time
    This time, we have a puzzle for deciphering scrambled application names.
    Decipher The Scrambled WordsCan you guess the scrambled words? Give it a try!It's FOSSAnkush Das💡 Quick Handy Tip
    In VirtualBox, you can send keyboard shortcuts like CTRL+ALT+DEL to logout, and a bunch of other keyboard shortcuts to the guest (the virtual machine), without affecting the host (your computer).
    To send CTRL+ALT+DEL, use Host+Delete. The Host key is usually the Right CTRL key on a keyboard. In the top menu, go to Input ⇾ Keyboard → Keyboard Settings to view and customize additional keyboard shortcuts for interacting with the virtual machine.
    If you need more input options, you can use the Input ⇾ Keyboard → Soft Keyboard menu to open a virtual keyboard for the guest VM.
    🤣 Meme of the Week
    Linux users, together, strong! 🤜🤛
    🗓️ Tech Trivia
    Before Spotify or iTunes, there was Napster. Launched on June 1, 1999, by 18-year-old Shawn Fanning, who built it in his college dorm room, Napster quickly attracted over 20 million users (and viruses).
    🧑‍🤝‍🧑 FOSSverse Corner
    One of our regular FOSSers, Laura, is looking to compare notes on building Linux and open source software from source.
    Building Linux and FLOSS programs from source codeStarting a thread on discussion of building parts of Linux, LFS and various packages from source code. This is a spot to compare notes on building from source. We can also discuss pros and cons of various packages/projects to figure out which might be most useful to build from source and which might have less dependencies.It's FOSS CommunityLaura_Michaels❤️ With love
    Please share it with your Linux-using friends and encourage them to subscribe (hint: it's here).
    Share the articles in Linux Subreddits and community forums.
    Follow us on Google News and stay updated in your News feed.
    Opt for It's FOSS Plus membership and support us 🙏
    Enjoy FOSS 😄
  12. SSH Config Generator

    by: Abhishek Prakash
    Wed, 04 Jun 2025 20:37:04 +0530

    This tool lets you generate the SSH config entries quickly. Fill the fields and hit the generate button and copy the entries to your SSH config file.
    /* Catppuccin Mocha Color Palette */ :root { --ctp-base: #1e1e2e; --ctp-mantle: #181825; --ctp-surface0: #313244; --ctp-surface1: #45475a; --ctp-surface2: #585b70; --ctp-overlay0: #6c7086; --ctp-overlay1: #7f849c; --ctp-text: #cdd6f4; --ctp-subtext1: #bac2de; --ctp-subtext0: #a6adc8; --ctp-blue: #89b4fa; --ctp-lavender: #b4befe; --ctp-mauve: #cba6f7; --ctp-red: #f38ba8; --ctp-green: #a6e3a1; --ctp-yellow: #f9e2af; } * { margin: 0; padding: 0; box-sizing: border-box; } .ssh-config-widget { background: var(--ctp-base); color: var(--ctp-text); font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; border-radius: 12px; border: 1px solid var(--ctp-surface1); max-width: 600px; width: 100%; padding: 24px; margin: 0 auto; } .widget-header { margin-bottom: 24px; } .widget-header h2 { font-size: 1.25rem; font-weight: 600; color: var(--ctp-lavender); margin-bottom: 4px; } .widget-header p { font-size: 0.875rem; color: var(--ctp-subtext0); } .form-group { margin-bottom: 16px; } .form-group label { display: block; font-size: 0.875rem; font-weight: 500; color: var(--ctp-text); margin-bottom: 6px; } .required { color: var(--ctp-red); } .form-group input { width: 100%; padding: 10px 12px; background: var(--ctp-surface0); border: 1px solid var(--ctp-surface1); border-radius: 8px; color: var(--ctp-text); font-size: 0.875rem; transition: all 0.2s ease; } .form-group input:focus { outline: none; border-color: var(--ctp-blue); box-shadow: 0 0 0 2px rgba(137, 180, 250, 0.2); } .form-group input::placeholder { color: var(--ctp-overlay0); } .form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; } .help-text { font-size: 0.75rem; color: var(--ctp-subtext0); margin-top: 4px; } .error-message { color: var(--ctp-red); font-size: 0.75rem; margin-top: 4px; display: none; } .error-message.show { display: block; } .form-group input.error { border-color: var(--ctp-red); box-shadow: 0 0 0 2px rgba(243, 139, 168, 0.2); } .advanced-section { margin-top: 20px; border: 1px solid var(--ctp-surface1); border-radius: 8px; overflow: hidden; } .advanced-toggle { background: var(--ctp-surface0); padding: 12px 16px; cursor: pointer; display: flex; align-items: center; gap: 8px; font-size: 0.875rem; font-weight: 500; color: var(--ctp-text); transition: background 0.2s ease; user-select: none; } .advanced-toggle:hover { background: var(--ctp-surface1); } .toggle-icon { font-size: 0.75rem; transition: transform 0.2s ease; color: var(--ctp-overlay1); } .toggle-icon.expanded { transform: rotate(90deg); } .advanced-content { padding: 20px; background: var(--ctp-mantle); border-top: 1px solid var(--ctp-surface1); } .checkbox-group { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-top: 12px; } .checkbox-item { display: flex; align-items: center; gap: 8px; } .checkbox-item input[type="checkbox"] { width: 16px; height: 16px; background: var(--ctp-surface0); border: 1px solid var(--ctp-surface2); border-radius: 4px; accent-color: var(--ctp-blue); } .checkbox-item label { font-size: 0.875rem; color: var(--ctp-text); cursor: pointer; margin: 0; } .generate-btn { width: 100%; background: var(--ctp-blue); color: var(--ctp-base); border: none; padding: 12px 16px; font-size: 0.875rem; font-weight: 600; border-radius: 8px; cursor: pointer; transition: all 0.2s ease; margin-top: 24px; } .generate-btn:hover { background: var(--ctp-lavender); } .generate-btn:active { transform: translateY(1px); } .output-section { margin-top: 24px; border: 1px solid var(--ctp-surface1); border-radius: 8px; overflow: hidden; } .output-header { background: var(--ctp-surface0); padding: 12px 16px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--ctp-surface1); } .output-header h3 { font-size: 0.875rem; font-weight: 600; color: var(--ctp-text); } .copy-btn { background: var(--ctp-green); color: var(--ctp-base); border: none; padding: 6px 12px; border-radius: 6px; cursor: pointer; font-size: 0.75rem; font-weight: 500; transition: background 0.2s ease; } .copy-btn:hover { background: var(--ctp-yellow); } .copy-btn.copied { background: var(--ctp-mauve); } .config-output { background: var(--ctp-mantle); color: var(--ctp-text); padding: 16px; font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace; font-size: 0.8rem; line-height: 1.5; white-space: pre-wrap; overflow-x: auto; } .output-footer { padding: 12px 16px; background: var(--ctp-surface0); font-size: 0.75rem; color: var(--ctp-subtext0); } .output-footer code { background: var(--ctp-surface1); padding: 2px 6px; border-radius: 4px; font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace; color: var(--ctp-blue); } @media (max-width: 640px) { .form-row { grid-template-columns: 1fr; } .checkbox-group { grid-template-columns: 1fr; } } Generate SSH config file entries
    Generate valid ~/.ssh/config entries
    Host Alias * Connection nickname Hostname/IP * Server address Username Leave empty for current user Port Default: 22 (use 1-65535) Identity File If you have multiple keys ▶ Advanced Options Proxy Jump Host Jump through this host first Local Forward local:remote:port Remote Forward remote:local:port Additional Options Forward X11 Forward SSH Agent Strict Host Key Checking Keep Alive Generate Config Generated Config
    Copy Add to ~/.ssh/config then connect with: ssh myserver
  13. Using Mouse Mode in Vim

    by: Abhishek Prakash
    Wed, 04 Jun 2025 12:11:12 +0530

    I hope I am not committing blasphemy but you can use the mouse in Vim.
    Press Esc to go to command mode in Vim and use:
    :set mouse=a It will enable mouse mode immediately in all Vim modes, i.e. normal, insert and visual. To disable the mouse mode, use this:
    :set mouse=If you want to use mouse mode all the time, I am not judging you, add this entry to your ~/.vimrc file:
    set mouse=aSave, restart Vim, and your mouse now works for clicking, scrolling, and selecting text.
    What does mouse mode do in Vim?
    First thing first, the mouse mode has limited usage in Vim. Don't expect to get a notepad like experience just because you enabled mouse mode.
    It does add some functionality and ease of use like:
    Jump to exact locations without counting lines or using search Wheel scrolling while dealing with long files Easy text selection: double click to select a word, triple click to select an entire line, use mouse click and drag for the desired text selection Click between panes and resize them easily while using split windows in Vim While using tabs, click on other tabs to switch, click on X (should be visible at top right in mouse mode) to close a tab, double click on tab bar to create new empty files in new tabs Use middle click to paste from system clipboard The video below shows some of the above discussed featured in action:
    0:00 /0:21 1× Vim Mouse Mode demonstration
    Mouse mode doesn't replace Vim's keyboard efficiency - it complements it. Think of it as having both a sports car's manual controls and cruise control available.
    📋Mouse mode behavior varies by terminal and some terminal emulators may require specific settings. If you are using tmux, ensure both Vim and tmux have mouse mode enabled for proper interaction.Understanding mouse mode Options
    Vim's mouse configuration works like a permission system:
    set mouse=a " All modes (normal, visual, insert, command) set mouse=n " Normal mode only set mouse=v " Visual mode only set mouse=i " Insert mode only set mouse=c " Command mode only set mouse=nv " Normal and visual modesMostly, you would want mouse=a - which is like having universal access rather than mode-specific restrictions.
    💡You can refer to Vim's official mouse documentation: :help mouse-usingConclusion
    I am not a Vim purist and I won't judge you if you use mouse in Vim, which is known for its keyboard-centric approach to productivity.
    Mouse mode doesn't diminish Vim's keyboard efficiency - it provides additional options for specific scenarios.
    If you feel too uncomfortable with Vim at the beginning, opt for the hybrid approach where you use mouse for navigation and positioning, keyboard for editing operations.
    I welcome your comments.
  14. by: Adnan Shabbir
    Wed, 04 Jun 2025 04:44:46 +0000

    Windows Subsystem for Linux (WSL) allows you to run Linux distros within the Windows operating system. WSL is available in multiple versions: WSL1 (older but still supported) and WSL2 (newer with continuous development support).
    Recently, on May 19, 2025, Microsoft conducted a 2025 Build Conference where they announced the open-source nature of WSL for Windows, which is huge news for Linux users and the open-source community.
    In today’s guide, I will elaborate on the recent development in the WSL project, the open-source nature of the WSL, how mature its open-source nature is, and Microsoft’s journey towards open-source. So, let’s get started:
    Windows Subsystem for Linux (WSL) is now Open Source Road to Open Source WSL How can I Contribute to Open-Source WSL? Basic Understanding of the WSL Architecture Bonus: Keep Your WSL Updated Conclusion Windows Subsystem for Linux (WSL) is now Open Source
    Yes, you heard that right, Microsoft has recently declared WSL as an open-source component of Windows. Microsoft has officially released the source code of WSL on May 19, 2025, at the Microsoft Build 2025 Conference.
    As per the announcement of Microsoft, the WSL is completely open-sourced except for the following three components:
    “Lxcore.sys”: Kernel-side driver that powers WSL1, i.e., component that translates Linux commands for Windows in WSL1. “P9rdr.sys” and “p9n9.dll”: These 9P protocol components refer to the filesystem redirection from Windows to Linux. The above three components are tightly integrated with Windows core processes. For instance, the “Lxcore.sys” has to interact with the Windows kernel. Similarly, the 9P protocol components handle Windows files and directories. These deep integrations of WSL’s components with Windows might be the reasons behind keeping them closed-source.
    This was about Microsoft’s recent announcement. Now, let me take you through Microsoft’s path towards open-source WSL.
    Road to Open Source WSL
    In 2019, Microsoft started maintaining its own Linux Kernel specifically for WSL, and it was declared an open-source component.
    Since then, the WSL community has started growing and contributing to the WSL project. Later on, the WSLg component became open source, which provides the graphical applications support for the Linux applications in the WSL.
    Microsoft gradually moved WSL to an open-source project. In 2021, Microsoft separated the Windows code base from the WSL code base. The newly released WSL was then available on the Microsoft Store for Windows 11 users. However, in 2022, it was made available for Windows 10 users too.
    Apart from that, the development and upgradation of WSL keep going, i.e., the latest available WSL is “2.5.7.0”.
    How can I Contribute to Open-Source WSL?
    Microsoft has provided the source code Git Repo of WSL, where you can contribute to reporting the bugs/issues or developing the source code from scratch. A Linux enthusiast may love to look into the source code and contribute according to their interest.
    If you are facing any technical issues relevant to WSL, you can ask for assistance on WSL’s Git repo. Similarly, if you are a regular user, you must keep on visiting the WSL repo and contribute to any other issues of the users in the comments.
    Basic Understanding of the WSL Architecture
    Since two different operating systems are collaborating, the component functionalities would differ in both environments. Let’s have a bird’s eye view of the WSL architecture:

    Windows Host: The components hosted on the Windows side are the entry points to interact with the WSL.
    wsl.exe: Command line utility to launch or manage the WSL. wslconfig.exe: This mostly belongs to WSL 1 and is used to configure WSL 1. wslg.exe: Launch and manage the GUI apps from Windows. wslservice.exe: This is the background process, i.e., launch the VM, start/stop the distros attached, mount the filesystem, etc. WSL VM Service: These components work inside the WSL VM and are triggered when the user executes Windows components.
    init: The initial process that starts in the Linux environment. It initializes the necessary processes and manages the distribution at the WSL end. gns (Networking): Manages DNS and network integration with Windows. localhost (port forwarding): The localhost running inside the Linux VM is the port forwarding. Plan9 Server: The server is responsible for file sharing from Windows to Linux. Bonus: Keep Your WSL Updated
    When you install WSL from the command line, it might fetch and install a bit lower version. Or even if it is up to date as per your installation, you must check for updates and get the latest available version:
    Before updating:
    wsl -v
    Updating WSL:
    wsl --update
    Both the Linux Kernel and WSL versions are updated:
    wsl -v
    That’s all from this post.
    Conclusion
    On May 19, 2025, Microsoft announced the WSL as an open-source project. Not 100% open-source, yet a major advancement in the open-source world. Microsoft has long been working on this. Microsoft has held three components closed-source because of their deep integration with the Windows core processes.
    In today’s post, I have talked about the open-source nature of WSL and Microsoft’s path to open-source WSL development.
    FAQs:
    Q1: Is WSL completely open source now?
    Yes, except for only three components, which are “Lxcore.sys”, “P9rdr.sys”, and “p9n9.dll”.
    Q2: How can I contribute to WSL?
    Microsoft has provided the source code Git Repo of WSL, where you can contribute to reporting the bugs/issues or developing the source code from scratch.
    Q3: Is WSL a replacement for Linux?
    WSL cannot be referred to as a full replacement for Linux. WSL is just a subsystem within Windows.
    Q4: Can WSL open a GUI?
    Yes, WSL can open a Linux GUI application with the help of WSLg, i.e., introduced in 2021 for Windows 11 and in 2022 for Windows 10.
  15. by: Andy Clarke
    Tue, 03 Jun 2025 14:39:04 +0000

    Like ’em or loath ’em, whether you’re showing an alert, a message, or a newsletter signup, dialogue boxes draw attention to a particular piece of content without sending someone to a different page. In the past, dialogues relied on a mix of divisions, ARIA, and JavaScript. But the HTML dialog element has made them more accessible and style-able in countless ways.
    So, how can you take dialogue box design beyond the generic look of frameworks and templates? How can you style them to reflect a brand’s visual identity and help to tell its stories? Here’s how I do it in CSS using ::backdrop, backdrop-filter, and animations.
    Design by Andy Clarke, Stuff & Nonsense. Mike Worth’s website will launch in June 2025, but you can see examples from this article on CodePen. I mentioned before that Emmy-award-winning game composer Mike Worth hired me to create a highly graphical design. Mike loves ’90s animation, and he challenged me to find ways to incorporate its retro style without making a pastiche. However, I also needed to achieve that retro feel while maintaining accessibility, performance, responsiveness, and semantics.
    A brief overview of dialog and ::backdrop
    Let’s run through a quick refresher.
    Note: While I mostly refer to “dialogue boxes” throughout, the HTML element is spelt dialog.
    dialog is an HTML element designed for implementing modal and non-modal dialogue boxes in products and website interfaces. It comes with built-in functionality, including closing a box using the keyboard Esc key, focus trapping to keep it inside the box, show and hide methods, and a ::backdrop pseudo-element for styling a box’s overlay.
    The HTML markup is just what you might expect:
    <dialog> <h2>Keep me informed</h2> <!-- ... --> <button>Close</button> </dialog> This type of dialogue box is hidden by default, but adding the open attribute makes it visible when the page loads:
    <dialog open> <h2>Keep me informed</h2> <!-- ... --> <button>Close</button> </dialog> I can’t imagine too many applications for non-modals which are open by default, so ordinarily I need a button which opens a dialogue box:
    <dialog> <!-- ... --> </dialog> <button>Keep me informed</button> Plus a little bit of JavaScript, which opens the modal:
    const dialog = document.querySelector("dialog"); const showButton = document.querySelector("dialog + button"); showButton.addEventListener("click", () => { dialog.showModal(); }); Closing a dialogue box also requires JavaScript:
    const closeButton = document.querySelector("dialog button"); closeButton.addEventListener("click", () => { dialog.close(); }); Unless the box contains a form using method="dialog", which allows it to close automatically on submit without JavaScript:
    <dialog> <form method="dialog"> <button>Submit</button> </form> </dialog> The dialog element was developed to be accessible out of the box. It traps focus, supports the Esc key, and behaves like a proper modal. But to help screen readers announce dialogue boxes properly, you’ll want to add an aria-labelledby attribute. This tells assistive technology where to find the dialogue box’s title so it can be read aloud when the modal opens.
    <dialog aria-labelledby="dialog-title"> <h2 id="dialog-title">Keep me informed</h2> <!-- ... --> </dialog> Most tutorials I’ve seen include very little styling for dialog and ::backdrop, which might explain why so many dialogue boxes have little more than border radii and a box-shadow applied.
    Out-of-the-box dialogue designs I believe that every element in a design — no matter how small or infrequently seen — is an opportunity to present a brand and tell a story about its products or services. I know there are moments during someone’s journey through a design where paying special attention to design can make their experience more memorable.
    Dialogue boxes are just one of those moments, and Mike Worth’s design offers plenty of opportunities to reflect his brand or connect directly to someone’s place in Mike’s story. That might be by styling a newsletter sign-up dialogue to match the scrolls in his news section.
    Mike Worth concept design, designed by Andy Clarke, Stuff & Nonsense. Or making the form modal on his error pages look like a comic-book speech balloon.
    Mike Worth concept design, designed by Andy Clarke, Stuff & Nonsense. dialog in action
    Mike’s drop-down navigation menu looks like an ancient stone tablet.
    Mike Worth, designed by Andy Clarke, Stuff & Nonsense. I wanted to extend this look to his dialogue boxes with a three-dimensional tablet and a jungle leaf-filled backdrop.
    Mike Worth, designed by Andy Clarke, Stuff & Nonsense. This dialog contains a newsletter sign-up form with an email input and a submit button:
    <dialog> <h2>Keep me informed</h2> <form> <label for="email" data-visibility="hidden">Email address</label> <input type="email" id="email" required> <button>Submit</button> </form> <button>x</button> </dialog> I started by applying dimensions to the dialog and adding the SVG stone tablet background image:
    dialog { width: 420px; height: 480px; background-color: transparent; background-image: url("dialog.svg"); background-repeat: no-repeat; background-size: contain; } Then, I added the leafy green background image to the dialogue box’s generated backdrop using the ::backdrop pseudo element selector:
    dialog::backdrop { background-image: url("backdrop.svg"); background-size: cover; } Mike Worth, designed by Andy Clarke, Stuff & Nonsense. I needed to make it clear to anyone filling in Mike’s form that their email address is in a valid format. So I combined :has and :valid CSS pseudo-class selectors to change the color of the submit button from grey to green:
    dialog:has(input:valid) button { background-color: #7e8943; color: #fff; } I also wanted this interaction to reflect Mike’s fun personality. So, I also changed the dialog background image and applied a rubberband animation to the box when someone inputs a valid email address:
    dialog:has(input:valid) { background-image: url("dialog-valid.svg"); animation: rubberBand 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both; } @keyframes rubberBand { from { transform: scale3d(1, 1, 1); } 30% { transform: scale3d(1.25, 0.75, 1); } 40% { transform: scale3d(0.75, 1.25, 1); } 50% { transform: scale3d(1.15, 0.85, 1); } 65% { transform: scale3d(0.95, 1.05, 1); } 75% { transform: scale3d(1.05, 0.95, 1); } to { transform: scale3d(1, 1, 1); } } Tip: Daniel Eden’s Animate.css library is a fabulous source of “Just-add-water CSS animations” like the rubberband I used for this dialogue box.
    Changing how an element looks when it contains a valid input is a fabulous way to add interactions that are, at the same time, fun and valuable for the user.
    Mike Worth, designed by Andy Clarke, Stuff & Nonsense. That combination of :has and :valid selectors can even be extended to the ::backdrop pseudo-class, to change the backdrop’s background image:
    dialog:has(input:valid)::backdrop { background-image: url("backdrop-valid.svg"); } Try it for yourself:
    CodePen Embed Fallback Conclusion
    We often think of dialogue boxes as functional elements, as necessary interruptions, but nothing more. But when you treat them as opportunities for expression, even the smallest parts of a design can help shape a product or website’s personality.
    The HTML dialog element, with its built-in behaviours and styling potential, opens up opportunities for branding and creative storytelling. There’s no reason a dialogue box can’t be as distinctive as the rest of your design.
    Andy Clarke
    Often referred to as one of the pioneers of web design, Andy Clarke has been instrumental in pushing the boundaries of web design and is known for his creative and visually stunning designs. His work has inspired countless designers to explore the full potential of product and website design.
    Andy’s written several industry-leading books, including ‘Transcending CSS,’ ‘Hardboiled Web Design,’ and ‘Art Direction for the Web.’ He’s also worked with businesses of all sizes and industries to achieve their goals through design.
    Visit Andy’s studio, Stuff & Nonsense, and check out his Contract Killer, the popular web design contract template trusted by thousands of web designers and developers.
    Getting Creative With HTML Dialog originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
  16. Chris’ Corner: Type Stuff!

    by: Chris Coyier
    Mon, 02 Jun 2025 17:01:09 +0000

    Let’s do typography stuff!
    Video: “A live demo by me of early font editors on a real Macintosh Plus” by Mark Simonson Font: “Is this font easy for you to read? Good—that’s the idea.” Hyperlegible is the name of the font, designed for people with low vision. Technique: “Fluid typography means thinking in terms of type scales and flexible spacing across your defined design space.” Richard Rutter goes retrofitting a new type sizing technique into an old layout. Miriam is also thinking about all this. Richard also has a good one on avoiding faux bold, which has afflicted me many times. My hot take is that browsers shouldn’t do faux nuthin. Font: “To help young readers of all skill levels, we’re introducing Kermit, a child-friendly typeface created by the type design studio Underware.” It’s fairly pricey but I can imagine it being perfect for some projects. Like Comic Sans but cooler. P.S. you should really try Comic Code on CodePen, it’s awesome. Fonts: “UNCUT.wtf is a free typeface catalogue, focusing on somewhat contemporary type.” A lot of them are super similar which makes me wonder if many of them come from students taking a design class or something. Journey: “One day, I saw what felt like Gorton on a ferry traversing the waters Bay Area. A few weeks later, I spotted it on a sign in a national park. Then on an intercom. On a street lighting access cover. In an elevator. At my dentist’s office. In an alley.” Marcin Wichary on Manhattan’s hardest working typeface. Performance: “… file sizes of web fonts? I personally don’t have a gut feeling how much is too much and how much is to be expected.” Stoyan Stefanov reckons 20k is fair. Behind the Scenes: “This meant that on web we could simply start our font stacks with Verdana, pick a couple of reasonable fallbacks, and get IKEA branding effectively for free.” IKEA didn’t end up using Verdana, but I wish they did, I kinda love it at small sizes. This is a great look at a major typographic choice at a major brand from Robin Whittleton. Technique: “…we added text-wrap: balance on WordPress.org, and quickly got community feedback that it led to awkward, unexpected breaks in Japanese and Korean.” Kelly Choyce-Dwan whips out stuff like word-break: auto-phrase; for the win.
  17. by: Abhishek Prakash
    Mon, 02 Jun 2025 14:28:22 GMT

    Most educational programs keep students trapped behind screens, manipulating virtual objects and producing digital outputs.
    This is why the Raspberry Pi and Arduino like devices provide such a great learning environment. Adding hardware components to the board gives meaning to the software.
    The CrowPi takes this forward by giving an entire learning laboratory that transforms abstract programming concepts into tangible, interactive experiences.
    Elecrow has been known for creating great Raspberry Pi products. They are launching their latest product, CrowPi 3. They sent me the device to test and share the experience and that's what I am going to do in this article.
    What is CrowPi 3?
    Think of the CrowPi 3 as a Swiss Army knife for coding education - it packs dozens of sensors, programming environments, and learning tools into one portable, briefcase. Instead of juggling separate breadboards, sensors, and computers, everything lives in a single ecosystem.
    The CrowPi 3 transforms abstract programming concepts into tangible experiences. Write Python code to detect motion → PIR sensor triggers alarm. Code an NFC reader → tap a card to spawn TNT blocks in Minecraft. It's programming with immediate, visible consequences.
    The core components are:
    Raspberry Pi 5 as the brain of the kit (advance kit includes the pi) 20+ sensors pre-wired and ready 4.3" touchscreen + HDMI connections for external monitors Built-in breadboards and GPIO access Arduino and Pi Pico can be attached on top of it 128 GB micro SD card with custom operating system This custom operating system is a customized version of Raspbian OS and has numerous ready-to-explore projects across multiple programming environments like Python, Scratch etc.
    A dedicated section of AI projects to try beginner level AI projects using the on-board camera and various sensors.
    No prizes for guessing that there were at least two more such CrowPi kits in the past and considering the fact that this is the third such inastallment, I would think that the first two devices met with success.
    Who is this kit for?
    The primary audience for CrowPi 3 is children aged 8-16 who are learning programming and AI coding fundamentals.
    Of course, it is not just limited to children. People new to Raspberry Pi/Arduino would also benefit from the guided experiences of such a kit.
    I also think that it is suitable for teachers that need turnkey STEM curriculum tools.
    The kit has streamlined learning of all levels with a mix of both software and hardware. Start with drag-drop Scratch blocks, graduate to Python sensor control, eventually tackle more intense AI projects.
    But all this can be assembled...
    Sure, you may not need or use all of the sensors provided in the kit. And yes, you can get the sensors and accessories separately and use them with tons of open source projects available online but kits like CrowPi, make it all streamlined. This is ideal for schools and for people who want to explore programming the hardware devices without struggling with the hardware assembly.
    Hardware assembly could be fun, too, but it could be frustrating and time-consuming. These kits flatten the learning curve a little, letting the students enjoy dipping their toes in the vast ocean of electronic geekery.
    CrowPi 3 Kit contents
    📋The kit I received for this review is the basic one. The advanced kit comes with a Raspberry Pi 5 16 GB already fixed in, batteries for extra portability, an additional SD card with retro games on it, game controllers and a few more accessories. The basic kit has the following item in addition to the pre-wired ones on the board already:
    Power Supply x1 Screwdriver x1 Stepped Motor x1 Infrared Receiver Head x1 RFID Card + Tag x1 IR Remote Control x1 User Manual x1 Motor + Fan Blade x1 USB A to Micro B Cable x1 Type-C to Type-C Cable x1 NFC Card x1 TF Card Reader x1A Swiss Army knife for coding education as this kit transforms the programming concepts into tangible experiences. Learn from more than a hundred interactive projects. Crowtail-9G Servo x1 Components Pack (with wires, LED and more) x1 128G TF Card with Customized System x1 Accessories in CrowPi 3 Basic kitThe advanced kit has these items in addition to everything in the basic kit:
    NFC Tag x10 Raspberry Pi 5 (16GB) x1 Laptop Tote x1 2.4G Wireless Keyboard + Mouse x1 32G TF Card with Customized System x1 Minecraft paper x5 Crowtail - I2C HUB x1 18650 Lithium Battery x2 Game Controller x2 Experiencing CrowPi 3
    The CrowPi kit comes in a briefcase styled box which kind of gives me the cyberdeck feel. The case looks good with the frosted glass.
    CrowPi 3 Kit with frosted glass coverLet me share my experience using this open source AI education kit.
    The build
    This is a well-thought and well-built device. It comes in a briefcase styled box with a fold-out handle that makes it easy to carry. The frosted glass cover doesn't come off easily as it has strong magnets and all the sensors and components are firmly fixed in the kit.
    I didn't do a fall test by dropping it to the ground to check if it can survive something like that. If you ever do this, accidentally or otherwise, do share the data with us 😜
    There is an empty slot at the bottom that could hold a few tiny accessories. It's a small thing but
    Built-in touchscreen
    The small screen has touch capability and the touch response is pretty decent but I would only use it when there are no other options available. My fat fingers and eyes are not suitable for tiny screens anymore.
    Okay, I could access pretty much most of the things with this tiny screen and it becomes even easier to use when I connected proper keyboard and mouse to it.
    Still, it is tiny which is okay for retro gaming and a few small stuff to check the output or see debug info but you'll need a proper screen to make use of it.
    This is evident as the customized learning interface is not properly displayed in the tiny screen.
    CrowPi 3's small screen doesn't properly display its customized learning interfaceRaspbian OS customized for interactive learning
    📋I still don't have a capture card for Raspberry Pi (a shame, I know) and hence I cannot share good quality images here. Apologies as I order a capture card.The interface, when experienced on a proper monitor, shows the IDE tools and interactive project to choose from. I used their CrowView Notebook for this purpose, although it can be connected to any external monitor.
    Select interactive project from left or use IDE from the right to code on your ownTo use the interactive projects, you'll have to create an account. I think it's a local user account that stays on your system. This way, more than one people can save their progress.
    A local user account saves your progress on the deviceIn the image below, you can see that it provides 39 Python projects that teach you the basic Python programming that also interact with various sensors and components on the kit.
    Interactive Python project interfaceWhen you select a project, you have instructions on half the screen and the code editor or tool in the other half. And the programs you run can also impact the hardware (most of the time) and you can see it on CrowPi 3 kit.
    For example, in the screenshot above (if it is visible), it creates a simple program that sounds the buzzer on the board for the specified time.
    See, this allows an easier way of learning with both software and hardware in the mix as you have pre-built scenario with instructions and their impact is visible on the hardware.
    You are not restricted to this customized interface. You can also use the classic Raspbian interface and access the editors and projects from there as well.
    The sensory board experience
    The kit features two breadboards positioned strategically on the main board, eliminating the frustrating "where do I connect this?" moments.
    While breadboards are available for custom circuits, most sensors come pre-connected and ready to use. There are easy sample projects to test the functionality of these sensors and they are fun to experiment even for adults.
    The cooling fan
    The cooling fan is loud and runs continuouslyThere is a visible cooling fan with RGB lighting. While it seemed cool at the beginning, it started to annoy me later. Don't get me wrong. I know that Raspberry Pi like devices must have some sort of cooling system.
    But this fan is much too loud for its size. And it runs continuously, unnecessarily. There is no on/off button for that and I don't expect such a feature. Now, this could be a good programming challenge to write a script that turns the fan off when the CPU reaches a certain temperature threshold.
    Bottom line
    The CrowPi 3 solves the "hello world" problem in programming education. Instead of printing text to screens, students control real-world devices and see immediate physical results.
    I mean, those variables are more meaningful when they represent real sensor readings. The conditional logic makes more sense when you can control lights and motors with it.
    The ready-to-use kit eliminates the setup frustration that could arise from manually connecting all those sensors, fans and lights.
    This is suitable for classrooms, as well as motivated self-learning at home. It is also a good Christmas gift candidate if you have children in your family that might be interested in learning AI, coding and electronics.
    I don't have the pricing at the time of writing this review. Elecrow is planning to run a pre-order campaign through Kickstarter very soon. Please check it for pricing and release dates.
    CrowPi 3 on Kickstarter
  18. By: Janus Atienza
    Sat, 31 May 2025 18:41:31 +0000

    For developers, website owners, and tech-savvy entrepreneurs, a Linux virtual private server (VPS) offers flexibility, power, and control at an affordable cost. However, for beginners, managing a Linux VPS can be daunting, especially if you’re diving in without prior experience. Mistakes are common, but most can be avoided with a little preparation and awareness. Here are some of the most frequent pitfalls new users face and how to steer clear of them.
    Skipping Initial Security Configurations
    One of the biggest mistakes is deploying a Linux VPS and leaving it with default settings. Without taking steps to harden your server, it becomes a prime target for brute-force attacks and unauthorized access. Many beginners forget to:
    Disable root login or at least change the default SSH port. Set up a firewall (like UFW or iptables). Install fail2ban to prevent repeated login attempts. How to avoid it: After setting up your VPS, immediately configure basic security settings. Create a non-root user with sudo privileges, set strong passwords, and use SSH keys instead of passwords where possible.
    Not Keeping the System Updated
    Linux distributions frequently release updates to patch vulnerabilities and fix bugs. New users often forget to update their system, exposing it to known security issues.
    How to avoid it: Regularly run package updates using commands like sudo apt update && sudo apt upgrade for Debian/Ubuntu or sudo yum update for CentOS. Consider enabling automatic updates for critical packages.
    Ignoring Backups
    It’s easy to get caught up in building your server and forget to plan for the worst-case scenario. Without backups, a single mistake or failure can result in total data loss.
    How to avoid it: Set up automated backups from day one. Many VPS providers offer snapshot and backup services. Alternatively, use tools like rsync, Duplicity, or cron jobs to regularly back up files and databases to remote storage.
    Overlooking Resource Monitoring
    New users often run too many services on a low-resource VPS, leading to sluggish performance or unexpected crashes. Without proper monitoring, it’s difficult to identify what’s causing issues.
    How to avoid it: Use tools like htop, iotop, or vnstat to monitor system performance. For long-term tracking, consider installing tools like Netdata or Zabbix to keep tabs on CPU, RAM, disk, and network usage.
    Choosing the Wrong Distribution
    Not all Linux distributions are beginner-friendly. Many users jump into complex distros or ones that are not well-supported, leading to confusion and difficulty managing the server.
    How to avoid it: Stick to popular and well-documented distributions such as Ubuntu or CentOS. These have active communities and extensive tutorials. If you’re considering a reliable and secure solution, CentOS VPS hosting is a strong option, especially for server environments that demand stability and performance.
    Lack of Documentation
    New users often make changes without keeping track of what they did. This can become a problem when troubleshooting issues or migrating to a new server.
    How to avoid it: Keep a simple changelog or setup document where you note down major configurations, installed packages, and custom tweaks. This habit saves countless hours down the line.
    By understanding and avoiding these common mistakes, beginners can confidently manage a Linux VPS and make the most of its powerful capabilities. Start small, stay secure, and always keep learning.
    The post The Common Linux VPS Mistakes Beginners Make (And How to Avoid Them) appeared first on Unixmen.
  19. Guess The Random Number Game

    by: Abhishek Prakash
    Sat, 31 May 2025 20:19:04 +0530

    Time to practice your Bash script and develop a simple game.
    Exercise
    Create a bash script that implements a number guessing game. The script should:
    Generate a random number between 1 and 100 Allow the user to make guesses Provide feedback whether the guess is too high, too low, or correct Count the number of attempts Allow the user to play again after winning The game should continue until the user guesses correctly, and then ask if they want to play another round.
    💡 Hints
    Use $RANDOM to generate random numbers The modulo operator % can help limit the range Use a while loop for the main game logic Consider using a nested loop structure for replay functionality Input validation is important - check if the user enters a valid number Test data
    Test Case 1: Basic game flow
    $ ./guessing_game.sh Welcome to the Number Guessing Game! I'm thinking of a number between 1 and 100. Enter your guess: 50 Too low! Try again. Enter your guess: 75 Too high! Try again. Enter your guess: 62 Too low! Try again. Enter your guess: 68 Congratulations! You guessed it in 4 attempts! Do you want to play again? (yes/no): no Thanks for playing! Goodbye!Test Case 2: Input validation
    $ ./guessing_game.sh Welcome to the Number Guessing Game! I'm thinking of a number between 1 and 100. Enter your guess: abc Invalid input! Please enter a number between 1 and 100. Enter your guess: 150 Your guess must be between 1 and 100! Enter your guess: 0 Your guess must be between 1 and 100! Enter your guess: 42 Too high! Try again.Test Case 3: Multiple rounds
    $ ./guessing_game.sh Welcome to the Number Guessing Game! I'm thinking of a number between 1 and 100. Enter your guess: 30 Congratulations! You guessed it in 1 attempts! Do you want to play again? (yes/no): yes Starting new game... I'm thinking of a number between 1 and 100. Enter your guess: 50 Too low! Try again. Enter your guess: 60 Congratulations! You guessed it in 2 attempts! Do you want to play again? (yes/no): no Thanks for playing! Goodbye!✋A programming challenge can be solved in more than one way. The solution presented here is for reference purposes only. You may have written a different program and it could be correct as well.Solution 1: Basic implementaion
    This is a straightforward implementation using nested while loops. The outer loop controls whether the player wants to play again, while the inner loop handles the guessing game logic. Key features:
    Uses $RANDOM % 100 + 1 to generate numbers between 1-100 Input validation with regex pattern matching Simple counter for tracking attempts #!/bin/bash # Number Guessing Game - Basic Implementation # Main game loop play_again="yes" echo "Welcome to the Number Guessing Game!" while [[ "$play_again" == "yes" ]]; do # Generate random number between 1 and 100 secret_number=$((RANDOM % 100 + 1)) attempts=0 guessed=false echo "I'm thinking of a number between 1 and 100." echo # Game loop for current round while [[ "$guessed" == "false" ]]; do # Read user input echo -n "Enter your guess: " read guess # Validate input - check if it's a number if ! [[ "$guess" =~ ^[0-9]+$ ]]; then echo "Invalid input! Please enter a number between 1 and 100." continue fi # Check if guess is in valid range if [[ $guess -lt 1 || $guess -gt 100 ]]; then echo "Your guess must be between 1 and 100!" continue fi # Increment attempt counter ((attempts++)) # Check the guess if [[ $guess -eq $secret_number ]]; then echo "Congratulations! You guessed it in $attempts attempts!" guessed=true elif [[ $guess -lt $secret_number ]]; then echo "Too low! Try again." else echo "Too high! Try again." fi done # Ask if player wants to play again echo echo -n "Do you want to play again? (yes/no): " read play_again play_again=$(echo "$play_again" | tr '[:upper:]' '[:lower:]') if [[ "$play_again" == "yes" ]]; then echo echo "Starting new game..." fi done echo "Thanks for playing! Goodbye!"Solution 2: Using functions
    In this solution, I break down the game into modular functions, making the code more organized and reusable:
    generate_random(): Generates the secret number validate_input(): Handles all input validation play_round(): Contains the core game logic ask_replay(): Manages the replay prompt main(): Orchestrates the overall game flow #!/bin/bash # Number Guessing Game - Function-based Implementation # Function to generate random number generate_random() { echo $((RANDOM % 100 + 1)) } # Function to validate input validate_input() { local input=$1 # Check if input is a number if ! [[ "$input" =~ ^[0-9]+$ ]]; then echo "Invalid input! Please enter a number between 1 and 100." return 1 fi # Check if number is in range if [[ $input -lt 1 || $input -gt 100 ]]; then echo "Your guess must be between 1 and 100!" return 1 fi return 0 } # Function to play one round play_round() { local secret_number=$(generate_random) local attempts=0 local guess echo "I'm thinking of a number between 1 and 100." echo while true; do # Get user input echo -n "Enter your guess: " read guess # Validate input if ! validate_input "$guess"; then continue fi # Increment attempts ((attempts++)) # Check guess if [[ $guess -eq $secret_number ]]; then echo "Congratulations! You guessed it in $attempts attempts!" break elif [[ $guess -lt $secret_number ]]; then echo "Too low! Try again." else echo "Too high! Try again." fi done } # Function to ask for replay ask_replay() { local response echo echo -n "Do you want to play again? (yes/no): " read response response=$(echo "$response" | tr '[:upper:]' '[:lower:]') [[ "$response" == "yes" ]] } # Main program main() { echo "Welcome to the Number Guessing Game!" while true; do play_round if ! ask_replay; then break fi echo echo "Starting new game..." done echo "Thanks for playing! Goodbye!" } # Run the main program mainSolution 3: Enhanced version with difficulty levels
    I added a few extra features:
    Difficulty levels with different number ranges Performance feedback based on attempts Hints when guesses are very far off Better user experience with clear menu options #!/bin/bash # Number Guessing Game - Enhanced Version with Difficulty Levels # Function to display menu show_menu() { echo "Select difficulty level:" echo "1. Easy (1-50)" echo "2. Medium (1-100)" echo "3. Hard (1-200)" echo -n "Enter your choice (1-3): " } # Function to get range based on difficulty get_range() { case $1 in 1) echo 50 ;; 2) echo 100 ;; 3) echo 200 ;; *) echo 100 ;; # Default to medium esac } # Main game echo "Welcome to the Number Guessing Game!" echo play_again="yes" while [[ "$play_again" == "yes" ]]; do # Select difficulty show_menu read difficulty # Validate difficulty selection if ! [[ "$difficulty" =~ ^[1-3]$ ]]; then echo "Invalid choice! Using medium difficulty." difficulty=2 fi # Get range for selected difficulty max_number=$(get_range $difficulty) # Generate random number secret_number=$((RANDOM % max_number + 1)) attempts=0 echo echo "I'm thinking of a number between 1 and $max_number." echo # Game loop while true; do echo -n "Enter your guess: " read guess # Validate input if ! [[ "$guess" =~ ^[0-9]+$ ]]; then echo "Invalid input! Please enter a number." continue fi if [[ $guess -lt 1 || $guess -gt $max_number ]]; then echo "Your guess must be between 1 and $max_number!" continue fi ((attempts++)) # Check guess if [[ $guess -eq $secret_number ]]; then echo "Congratulations! You guessed it in $attempts attempts!" # Give performance feedback if [[ $attempts -le 5 ]]; then echo "Excellent! You're a mind reader!" elif [[ $attempts -le 10 ]]; then echo "Good job! That was quick!" else echo "Well done! Practice makes perfect!" fi break elif [[ $guess -lt $secret_number ]]; then echo "Too low! Try again." # Give hint for very far guesses if [[ $((secret_number - guess)) -gt $((max_number / 4)) ]]; then echo "(Hint: You're quite far off!)" fi else echo "Too high! Try again." # Give hint for very far guesses if [[ $((guess - secret_number)) -gt $((max_number / 4)) ]]; then echo "(Hint: You're quite far off!)" fi fi done # Ask for replay echo echo -n "Do you want to play again? (yes/no): " read play_again play_again=$(echo "$play_again" | tr '[:upper:]' '[:lower:]') if [[ "$play_again" == "yes" ]]; then echo echo "Starting new game..." echo fi done echo "Thanks for playing! Goodbye!"📖 Concepts to revise
    The solutions discussed here use some terms, commands and concepts and if you are not familiar with them, you should learn more about them.
    Variables: secret_number, attempts, guess Arithmetic operations: $RANDOM % 100 + 1, numeric comparisons Conditional statements: if/elif/else for guess validation and checking Loops: while loops, nested loops, continue statement Regular expressions: [[ "$guess" =~ ^[0-9]+$ ]] for number validation Functions: Modular code organization (Solutions 2 & 3) Input/Output: read command, echo with -n flag String manipulation: tr command for case conversion Command substitution: $(command) syntax 📚 Further reading
    If you are new to bash scripting, we have a streamlined tutorial series on Bash that you can use to learn it from scratch or use it to brush up the basics of bash shell scripting.
    Bash Scripting Tutorial Series for Beginners [Free]Get started with Bash Shell script learning with practical examples. Also test your learning with practice exercises.Linux HandbookAbhishek Prakash
  20. by: Adnan Shabbir
    Sat, 31 May 2025 12:15:51 +0000

    Tails is a Tor-based project inspired by the Debian Linux distro. Tails works on Tor Foundation, i.e., the onion router. It is supposed to be a secure OS and difficult to trace with ordinary tools/tricks.
    Tails is used to perform privacy-focused tasks without leaving digital traces. These tasks include accessing or monitoring the target, i.e., it is recommended to access the identity type of data ethically (with consent of the target).
    Today, this guide brings a brief walkthrough of the Tails OS and also lists the process to set up Tails.
    Tails OS | A Quick Walkthrough Tails Development and Merger With Tor Release Cycle Top Features of Tails OS Built-in Security and Privacy Tools for Maximum Anonymity Persistent Vs Non-Persistent Storage in Tails How to Install and Set up Tails on a USB Drive (Step-by-Step Guide) Hardware Requirements for Installing Tails Step 1: Download and Verify the Tails OS Disk Image (For USB or Virtual Machines) Step 2: Install Tails Should You Use Tails? | Technical Pros and Cons Conclusion Tails OS | A Quick Walkthrough
    Let’s have a quick walkthrough of the features, some facts, and tools that Tails has:
    Tails Development and Merger With Tor
    Tails was first released in 2009 as an iteration of Incognito, a Gentoo-based Linux distribution. The Tails project was originally named “Amnesia,” and now “Amnesia” is the default username/hostname of the Tails OS. In 2023, the Tails submitted a request to merge with Tor, which was completed in 2024, and now Tails is a Tor project. Release Cycle
    Tails usually release the update after every 6-8 weeks. However, the major release (Like 5.0, 6.0, 7.0) is expected approximately every 2 years. Top Features of Tails OS
    Communication via Tails is done using Tor (The Onion Router). Direct or non-Tor traffic is blocked by default. Can create persistent (keeping the data) and non-persistent (temporary) storage. Tails verifies and authenticates the Tails version you acquire. Wipes out the memory (RAM) after every reboot or shutdown, nullifying the chance of accessing the sensitive data, i.e., passwords, logins, etc, after restarts/ shutdowns. MAC Address Spoofing Built-in Security and Privacy Tools for Maximum Anonymity
    Tor Network: An Anonymous network to route traffic anonymously. Thunderbird: An email client to send/receive encrypted emails. KeePassXc: A password manager to securely save passwords. Electrum: Bitcoin wallet OnionShare: Sharing files/media anonymously MAT2: A tool to remove metadata from files, i.e., PDF. GnuPG (GPG): Tool for encrypting, signing, and verifying emails, using Public-Key cryptography. Persistent Vs Non-Persistent Storage in Tails
    Before proceeding to its setup, let‘s have a look at the difference between Persistent and Non-Persistent.
    Feature Persistent Non-Persistent Data Saving Yes No Boot Time Slight Longer Faster than Non-persistent Recommended For When you want to have the data in the upcoming sessions. Maximum Anonymity How to Install and Set up Tails on a USB Drive (Step-by-Step Guide)
    Why are you installing Tails? If the purpose is anonymity, you need to create a non-persistent Live USB. However, if the purpose is to learn and implement, then you can create a persistent one to keep the history and some data from the previous sessions.
    Recommended: Use Tails as a Live OS, i.e., a non-persistent OS. Not Recommended: Avoid installing it on your primary host or primary virtual machine, where traces can persist. Hardware Requirements for Installing Tails
    64-bit processor Minimum 2GB RAM (Recommended is 4GB) Minimum 8 GB USB drive (Recommended is 16GB) Step 1: Download and Verify the Tails OS Disk Image (For USB or Virtual Machines)
    Download the Tails (either for USB sticks or the ISO file for Virtual machines).

    Download Tails:

    Once downloaded, verify your downloaded version:

    Confirm that the verification is successful before proceeding further:

    Step 2: Install Tails
    Once done, you must have a USB bootable tool like balenaEtcher (if using Linux), Rufus (if using Windows), etc. Here, I have listed two possibilities:
    Installation Option 1: Installing Tails Using the GNOME Disks App Installation Option 2: Installing Tails Using the Balena Etcher  
    Installation Option 1: GNOME Disks App If you are using a GNOME desktop environment, you can make the Tails USB using the GNOME Disks Desktop application. Here’s the process.
    Attach the USB with the Linux OS, and open the “GNOME Disks” app. Now, select the USB and click the “vertical ellipsis”.

    It will then ask you to choose the Disk Image:

    Confirm to start writing Tails on USB:

    This will take a few minutes. Once all done, you can eject the drive and boot from the USB to run Tails in an isolated environment.
    Installation Option 2: Installing Tails Using the balenaEtcher First, you must download and install the Balena Etcher on your respective Linux distribution.
    Once installed, you have to make the USB bootable with the Tails disk image that you have already downloaded.
    Follow this guide to briefly understand how to install and use Balena Etcher
    Setting Up Persistent Storage and Administrator Password
    When you boot from Tails, you will have to pass through the following interface, where you can create persistent storage and set the administrator password.

    Persistent Storage: To keep the data, history for further sessions. Administrator Password: To handle the permissions or admin password required for installing applications. Now, you have to set the Tor connection, where you have two options, i.e., choose “Connect to Tor automatically”.

    This way, you can set anonymity through Tails.
    What is Tor/Onion Circuits: The Path that the Tor network uses to route traffic from a user’s device to the destination server with anonymity.
    Here’s the terminal look of the Tails:

    Here you go with the Tails:

    Should You Use Tails? | Technical Pros and Cons
    If you still have questions about whether Tails is a perfect fit for me or not, don’t worry, I have compiled a technical Pros/Cons of Tails to assist you in this regard:
    Technical Feature/Component Pros Cons Tor-based Anonymity Routes traffic through the Tor network by default. Some websites discourage the Tor Project. Data Security It’s RAM-dependent, and thus, data is wiped out after every boot, i.e., no data breach or tracing through data Data is lost, i.e., the new Tails user who is not familiar with non-persistent working. Once the user is familiar with the system, this issue will decrease. Privacy Tools Built-in tools for file sharing, password, email client, etc. Limited application availability (outside the default installation) No Installation Just plug and play. Plug in the live USB of Tails, and you are good to go. No hard and time-consuming installations. Unstable performance compared to the full-fledged installed system. Hardware Protection Tails spoofs MAC addresses. So, nothing beyond that when it comes to security. It may malfunction sometimes, i.e., in a conflict with the internet hardware devices. Disk Image Verification Disk Image is briefly verified on the Tails official website. It might be difficult for the new or non-technical users. System Footprint A very small footprint, i.e., negligible, because of the advanced encryption/protection level. This makes it not suitable for routine or daily tasks. Updates Frequent Updates,i.e., every 6 weeks. Create a bootable system with every update. Pro-Tip: For maximum security, always use the non-persistent USB for Tails and enjoy this state-of-the-art tool in the tech era.
    Conclusion
    Tails OS is one of the best anonymity tools based on the Debian distro and is a part of the Tor project. With one end in Open Source (Linux-based) and the other in anonymity (Tor project).
    Tails OS is installed and used as a Live non-persistent USB, which minimizes the risk of any traces. Today, I have drafted an in-depth review of the Tails OS, including its installation on a USB as well.
    FAQs:
    Q1: Is Tails OS Legal?
    Yes, Tails is legal. Tails is an open-source Debian-inspired Tor project. The Onion Routing (Tor) nature of Tails makes it suspicious but not illegal.
    Q2: Does Tails hide your IP?
    Tails is a Tor project, and when routing, it hides your IP and server information.
    Q3: Does Tails run in RAM?
    Since it’s an amnestic, no data or history is kept. This anonymity is due to RAM. It temporarily stores data and refreshes it after each session.
    Q4: What is the Tails filesystem?
    Tails works on the Ext4 file system, i.e., Fourth Extended Filesystem.
  21. by: Abhishek Kumar
    Sat, 31 May 2025 04:29:37 GMT

    In one of my earlier articles, I showed how you can preview HTML files inside Visual Studio Code. That setup worked well for testing static pages, but what if you want to go beyond markup and bring interactivity into the mix?
    With JavaScript being the backbone of the modern web and countless developers now diving into frameworks like React, Vue, and Svelte, being able to run JavaScript code directly inside VS Code becomes almost essential.
    Running JavaScript in the editor helps you avoid constant context-switching, reduces distractions, and gives you immediate feedback when debugging.
    There are two approaches here:
    Running JavaScript inside VS Code using Node.js: most efficient and editor-native approach. Run it in a browser or using extensions: handy for quick tests or visual feedback. Let's see about using them.
    Understanding the role of Node.js
    JavaScript was originally designed to run inside browsers, which come with their own JavaScript engines (like V8 in Chrome).
    Node.js takes that same V8 engine and brings it to your local machine. This lets you run JavaScript outside the browser, directly from the command line or terminal.
    It’s particularly useful for backend work, automation scripts, or just quick testing without the overhead of an HTML shell.
    If you're unsure whether Node.js is already installed on your system, open a terminal and type:
    node -vIf you see a version number, you’re all set. If not, you’ll need to download Node.js and follow the installation instructions for your operating system.
    We have covered node installation on Ubuntu.
    Install Node.js and npm on Ubuntu Linux [Free Cheat Sheet]Node.js and npm can be easily installed using the Ubuntu repository or the NodeSource repository. Learn both ways of installing Node.js on Ubuntu Linux.It's FOSSAbhishek PrakashSet up a JavaScript project
    Once everything’s installed, open VS Code and create a new folder for your project. Inside it, launch the terminal (Ctrl + ~ or Terminal > New Terminal) and run npm init -y.
    This initializes a basic project and creates a package.json file, which will be useful for managing your scripts and dependencies later.
    With the environment ready, create a new file named app.js and add a bit of JavaScript, for example:
    console.log("Hello, VS Code!"); To run it, simply type node app.js in the terminal.
    The output will appear immediately in the console, confirming that Node is executing your file properly.
    Add a custom script for simpler runs
    To make things smoother, especially as your project grows, it’s a good idea to define a custom script in your package.json file. Open that file and find the "scripts" section, then add:
    "start": "node app.js" This allows you to run your script just by typing npm start, instead of repeating the filename every time.
    Optional: Using the Code Runner extension
    If you prefer a quick way to execute small snippets without setting up a project, Code Runner can help. It’s a lightweight VS Code extension that runs code in a sandboxed output window.
    To get started:
    Open the Extensions tab in VS Code. Search for “Code Runner” and install it. Open a .js file, write some code, right-click, and select “Run Code.” For example, a file like example.js with:
    console.log("Hello from Code Runner!");It will output directly to VS Code’s "Output" tab.
    The main limitation here is that it doesn’t use the integrated terminal like we used above, which can restrict input/output behavior for more complex scripts.
    Wrapping up
    With Node.js set up inside VS Code, running JavaScript becomes a seamless part of your workflow, no browser tabs or external tools required.
    Whether you're testing a quick function or building out a larger project, using the terminal and custom npm scripts keeps things fast and distraction-free.
    Extensions like Code Runner can help for quick one-off tests, but for anything serious, sticking to the Node-powered method inside VS Code gives you more control, better error output, and a real development feel.
    Once this setup becomes second nature, jumping into frameworks like React or Express will feel a lot more natural too.
    Now that you’ve got the tools, go ahead, experiment, break stuff, debug, and build.
  22. by: Temani Afif
    Fri, 30 May 2025 13:45:43 +0000

    Ready for the second part? We are still exploring the shape() function, and more precisely, the arc command. I hope you took the time to digest the first part because we will jump straight into creating more shapes!
    As a reminder, the shape() function is only supported in Chrome 137+ and Safari 18.4+ as I’m writing this in May 2025.
    Sector shape
    Another classic shape that can also be used in pie-like charts.
    It’s already clear that we have one arc. As for the points, we have two points that don’t move and one that moves depending on how much the sector is filled.
    The code will look like this:
    .sector { --v: 35; /* [0 100]*/ aspect-ratio: 1; clip-path: shape(from top, arc to X Y of R, line to center); } We define a variable that will control the filling of the sector. It has a value between 0 and 100. To draw the shape, we start from the top, create an arc until the point (X, Y), and then we move to the center.
    Yes! Unlike the polygon() function, we have keywords for the particular cases such as top, bottom, left, etc. It’s exactly like background-position that way. I don’t think I need to detail this part as it’s trivial, but it’s good to know because it can make your shape a bit easier to read.
    The radius of the arc should be equal to 50%. We are working with a square element and the sector, which is a portion of a circle, need to fill the whole element so the radius is equal to half the width (or height).1
    As for the point, it’s placed within that circle, and its position depends on the V value. You don’t want a boring math explanation, right? No need for it, here is the formula of X and Y:
    X = 50% + 50% * sin(V * 3.6deg) Y = 50% - 50% * cos(V * 3.6deg) Our code becomes:
    .sector { --v: 35; /* [0 100] */ aspect-ratio: 1; clip-path: shape(from top, arc to calc(50% + 50% * sin(var(--v) * 3.6deg)) calc(50% - 50% * cos(var(--v) * 3.6deg)) of 50%, line to center); } CodePen Embed Fallback Hmm, the result is not good, but there are no mistakes in the code. Can you figure out what we are missing?
    It’s the size and direction of the arc!
    Remember what I told you in the last article? You will always have trouble with them, but if we try the different combinations, we can easily fix the issue. In our case, we need to use: small cw.
    CodePen Embed Fallback Better! Let’s try it with more values and see how the shape behaves:
    CodePen Embed Fallback Oops, some values are good, but others not so much. The direction needs to be clockwise, but maybe we should use large instead of small? Let’s try:
    CodePen Embed Fallback Still not working. The issue here is that we are moving one point of the arc based on the V value, and this movement creates a different configuration for the arc command.
    Here is an interactive demo to better visualize what is happening:
    CodePen Embed Fallback When you update the value, notice how large cw always tries to follow the largest arc between the points, while small cw tries to follow the smallest one. When the value is smaller than 50, small cw gives us a good result. But when it’s bigger than 50, the large cw combination is the good one.
    I know, it’s a bit tricky and I wanted to study this particular example to emphasize the fact that we can have a lot of headaches working with arcs. But the more issues we face, the better we get at fixing them.
    The solution in this case is pretty simple. We keep the use of large cw and add a border-radius to the element. If you check the previous demo, you will notice that even if large cw is not producing a good result, it’s filling the area we want. All we need to do is clip the extra space and a simple border-radius: 50% will do the job!
    CodePen Embed Fallback I am keeping the box-shadow in there so we can see the arc, but we can clearly see how border-radius is making a difference on the main shape.
    There is still one edge case we need to consider. When the value is equal to 100, both points of the arc will have the same coordinates, which is logical since the sector is full and we have a circle. But when it’s the case, the arc will do nothing by definition and we won’t get a full circle.
    To fix this, we can limit the value to, for example, 99.99 to avoid reaching 100. It’s kind of hacky, but it does the job.
    .sector { --v: 35; /* [0 100]*/ --_v: min(99.99, var(--v)); aspect-ratio: 1; clip-path: shape(from top, arc to calc(50% + 50% * sin(var(--_v) * 3.6deg)) calc(50% - 50% * cos(var(--_v) * 3.6deg)) of 50% large cw, line to center); border-radius: 50%; } Now our shape is perfect! And don’t forget that you can apply it to image elements:
    CodePen Embed Fallback Arc shape
    Similar to the sector shape, we can also create an arc shape. After all, we are working with the arc command, so we have to do it.
    We already have half the code since it’s basically a sector shape without the inner part. We simply need to add more commands to cut the inner part.
    .arc { --v: 35; --b: 30px; --_v: min(99.99, var(--v)); aspect-ratio: 1; clip-path: shape(from top, arc to calc(50% + 50% * sin(var(--_v) * 3.6deg)) calc(50% - 50% * cos(var(--_v) * 3.6deg)) of 50% cw large, line to calc(50% + (50% - var(--b)) * sin(var(--_v) * 3.6deg)) calc(50% - (50% - var(--b)) * cos(var(--_v) * 3.6deg)), arc to 50% var(--b) of calc(50% - var(--b)) large ); border-radius: 50%; } From the sector shape, we remove the line to center piece and replace it with another line command that moves to a point placed on the inner circle. If you compare its coordinates with the previous point, you will see an offset equal to --b, which is a variable that defines the arc’s thickness. Then we draw an arc in the opposite direction (ccw) until the point 50% var(--b), which is also a point with an offset equal to --b from the top.
    I am not defining the direction of the second arc since, by default, the browser will use ccw.
    CodePen Embed Fallback Ah, the same issue we hit with the sector shape is striking again! Not all the values are giving a good result due to the same logic we saw earlier, and, as you can see, border-radius is not fixing it. This time, we need to find a way to conditionally change the size of the arc based on the value. It should be large when V is bigger than 50, and small otherwise.
    Conditions in CSS? Yes, it’s possible! First, let’s convert the V value like this:
    --_f: round(down, var(--_v), 50) The value is within the range [0 99.99] (don’t forget that we don’t want to reach the value 100). We use round() to make sure it’s always equal to a multiple of a specific value, which is 50 in our case. If the value is smaller than 50, the result is 0, otherwise it’s 50.
    There are only two possible values, so we can easily add a condition. If --_f is equal to 0 we use small; otherwise, we use large:
    .arc { --v: 35; --b: 30px; --_v: min(99.99, var(--v)); --_f: round(down,var(--_v), 50); --_c: if(style(--_f: 0): small; else: large); clip-path: shape(from top, arc to calc(50% + 50% * sin(var(--_v) * 3.6deg)) calc(50% - 50% * cos(var(--_v) * 3.6deg)) of 50% cw var(--_c), line to calc(50% + (50% - var(--b)) * sin(var(--_v) * 3.6deg)) calc(50% - (50% - var(--b)) * cos(var(--_v) * 3.6deg)), arc to 50% var(--b) of calc(50% - var(--b)) var(--_c) ); } I know what you are thinking, but let me tell you that the above code is valid. You probably don’t know it yet, but CSS has recently introduced inline conditionals using an if() syntax. It’s still early to play with it, but we have found a perfect use case for it. Here is a demo that you can test using Chrome Canary:
    CodePen Embed Fallback Another way to express conditions is to rely on style queries that have better support:
    .arc { --v: 35; --b: 30px; --_v: min(99.99, var(--v)); --_f: round(down, var(--_v), 50); aspect-ratio: 1; container-name: arc; } .arc:before { content: ""; clip-path: shape(from top, arc to calc(50% + 50% * sin(var(--_v) * 3.6deg)) calc(50% - 50% * cos(var(--_v) * 3.6deg)) of 50% cw var(--_c, large), line to calc(50% + (50% - var(--b)) * sin(var(--_v) * 3.6deg)) calc(50% - (50% - var(--b)) * cos(var(--_v) * 3.6deg)), arc to 50% var(--b) of calc(50% - var(--b)) var(--_c, large) ); @container style(--_f: 0) { --_c: small } } The logic is the same but, this feature requires a parent-child relation, which is why I am using a pseudo-element. By default, the size will be large, and if the value of --_f is equal to 0, we switch to small.
    CodePen Embed Fallback Note that we have to register the variable --_f using @property to be able to either use the if() function or style queries.
    Did you notice another subtle change I have made to the shape? I removed border-radius and I applied the conditional logic to the first arc. Both have the same issue, but border-radius can fix only one of them while the conditional logic can fix both, so we can optimize the code a little.
    Arc shape with rounded edges
    What about adding rounded edges to our arc? It’s better, right?
    Can you see how it’s done? Take it as a small exercise and update the code from the previous examples to add those rounded edges. I hope you are able to find it by yourself because the changes are pretty straightforward — we update one line command with an arc command and we add another arc command at the end.
    clip-path: shape(from top, arc to calc(50% + 50% * sin(var(--_v) * 3.6deg)) calc(50% - 50% * cos(var(--_v) * 3.6deg)) of 50% cw var(--_c, large), arc to calc(50% + (50% - var(--b)) * sin(var(--_v) * 3.6deg)) calc(50% - (50% - var(--b)) * cos(var(--_v) * 3.6deg)) of 1% cw, arc to 50% var(--b) of calc(50% - var(--b)) var(--_c, large), arc to top of 1% cw ); If you do not understand the changes, get out a pen and paper, then draw the shape to better see the four arcs we are drawing. Previously, we had two arcs and two lines, but now we are working with arcs instead of lines.
    And did you remember the trick of using a 1% value for the radius? The new arcs are half circles, so we can rely on that trick where you specify a tiny radius and the browser will do the job for you and find the correct value!
    CodePen Embed Fallback Conclusion
    We are done — enough about the arc command! I had to write two articles that focus on this command because it’s the trickiest one, but I hope it’s now clear how to use it and how to handle the direction and size thing, as that is probably the source of most headaches.
    By the way, I have only studied the case of circular arcs because, in reality, we can specify two radii and draw elliptical ones, which is even more complex. Unless you want to become a shape() master, you will rarely need elliptical arcs, so don’t bother yourself with them.
    Until the next article, I wrote an article for Frontend Masters where you can create more fancy shapes using the arc command that is a good follow-up to this one.
    Footnotes
    (1) The arc command is defined to draw elliptical arcs by taking two radii, but if we define one radius value, it means that the vertical and horizontal radius will use that same value and we have circular arcs. When it’s a length, it’s trivial, but when we use percentages, the value will resolve against the direction-agnostic size, which is equal to the length of the diagonal of the box, divided by sqrt(2).
    In our case, we have a square element so 50% of the direction-agnostic size will be equal to 50% of sqrt(Width² + Height²)/sqrt(2). And since both width and height are equal, we end with 50% of the width (or the height). ⮑

    Better CSS Shapes Using shape() — Part 2: More on Arcs originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
  23. by: Abhishek Prakash
    Fri, 30 May 2025 17:30:45 +0530

    An interesting development came from Microsoft as it released a new terminal-based editor with open source license.
    I kind of liked it at first glance until I tried my hands on a shell script written in this editor and then I ran into:
    The issue is that it added the classic Windows-style line endings, which is not liked by UNIX-like systems.
    I knew it was too good to be true to have something perfect for Linux from Microsoft 🤦
    Here are the highlights of this edition :
    Open-source notification Inbox infrastructure Listmonk newsletter Historical view of system resource utilization Bang bang... shebang And memes, news and tools to discover 🚀 Level up your coding skills and build your own bots
    Harness the power of machine learning to create digital agents and more with hot courses like Learning LangChain, The Developer's Playbook for Large Language Model Security, Designing Large Language Model Applications, and more.
    Part of the purchase goes to Code for America! Check out the ebook bundle here.
    Humble Tech Book Bundle: Machine Learning, AI, and Bots by O’Reilly 2025Master machine learning with this comprehensive library of coding and programming courses from the pros at O’Reilly.Humble Bundle  
     
      This post is for subscribers only
    Subscribe now Already have an account? Sign in
  24. by: Abhishek Prakash
    Thu, 29 May 2025 04:29:31 GMT

    Important thing first. Ubuntu 20.04 LTS version will be reaching its end of life on 31st May. It was released in April 2020 and had a standard support of five years.
    Please check your Ubuntu version and if you are using 20.04, you can:
    Do a fresh installation of Ubuntu 24.04 LTS to get the latest packages. Upgrade to Ubuntu 22.04 LTS from your existing 20.04 installation, keeping your files intact. Opt for Ubuntu Pro, which will ensure you get essential security patches until 2030 but no new software. Ubuntu 20.04 LTS is Reaching End of Life — Here are Your OptionsUpgrade or sign-up for extended support before it is too late!It's FOSS NewsSourav RudraTime to plan your update.
    💬 Let's see what else you get in this edition
    A new Linux kernel release. File permission in Linux. GNU Taler payment system being approved for Swiss use. And other Linux news, tips, and, of course, memes! This edition of FOSS Weekly is supported by PikaPods. ❇️ PikaPods: Enjoy Self-hosting Hassle-free
    PikaPods allows you to quickly deploy your favorite open source software. All future updates are handled automatically by PikaPods while you enjoy using the software. PikaPods also share revenue with the original developers of the software.
    You get a $5 free credit to try it out and see if you can rely on PikaPods.
    PikaPods - Instant Open Source App HostingRun the finest Open Source web apps from $1.20/month, fully managed, no tracking, no ads, full privacy. Self-hosting was never this convenient.Instant Open Source App Hosting📰 Linux and Open Source News
    GNU Taler has officially entered the Swiss market. Linux kernel 6.15 is here with a Rust-based NVIDIA driver. SteamOS now officially supports more handhelds than just the Steam Deck. Qt has introduced Qt Bridges, a new piece of tech for bridging Qt applications with other frameworks and programming languages. Rhino Linux's new UBXI KDE Desktop doesn't disappoint.
    Hands-On with Rhino Linux’s New UBXI KDE 6 DesktopRhino Linux’s first UBXI port is here!It's FOSS NewsSourav Rudra🧠 What We’re Thinking About
    Carmen from Mission Libre has started a petition to get Qualcomm to release fully-free drivers for their in-production chipsets. If the petition is signed by 5,000 people, a hardcopy of the petition and signatures will be mailed to Qualcomm's head office. We can get 5,000 signatures, can't we?
    Home | Tell Qualcomm: Publish Free Drivers for Modern Wi-Fi Chipsets!Tell Qualcomm: Publish Free Drivers for Modern Wi-Fi Chipsets!🧮 Linux Tips, Tutorials and More
    VS Code on Arch is possible and easy. Understand the concept of file permission. It's a must-know for Linux users. Want more from Obsidian? Our plugin guide can be helpful. Looking for some note taking apps suggestion? We have an extensive list.
    Top 16 Best Note Taking Apps For Linux [2025]Plenty of amazing note-taking apps for Linux. Here’s what we recommend you to check out.It's FOSSAnkush Das Why should you opt for It's FOSS Plus membership:
    ✅ Ad-free reading experience
    ✅ Badges in the comment section and forum
    ✅ Supporting creation of educational Linux materials
    Join It's FOSS Plus 👷 Homelab and Maker's Corner
    While it is a proprietary piece of hardware, Flexbar can be a nice addition to your Linux setup.
    Miss Apple’s Touch Bar? Flexbar Brings This Experience to LinuxWhile Apple has discontinued the Touch Bar, Linux users can now enjoy the same experience with Flexbar.It's FOSS NewsSourav RudraAlso, learn a thing or two about MCP servers, the latest buzzword in the (AI) tech world.
    ✨ Apps Highlight
    If you ever wanted to run an operating system inside your browser, then Puter is the solution for you. It is open source and can be self-hosted as well.
    Puter is a Complete, Fully Functional OS that Runs in Your Web BrowserRun an operating system straight from your browser.It's FOSS NewsSourav RudraAn It's FOSS reader created an FFmpeg AAC Audio Encoder Plugin for DaVinci Resolve. This will help you get effortless AAC audio encoding on Linux if you use DaVinci Resolve video editor.
    📽️ Videos I am Creating for You
    I tried Microsoft's new terminal editor on Linux! I hate to admit it but I liked what I saw here. This is an excellent approach. I wonder why Linux didn't have something like this before. See it in action 👇
    Subscribe to It's FOSS YouTube Channel🧩 Quiz Time
    Can you identify all the GitHub alternatives in this puzzle?
    GitHub Alternatives: PuzzleSolve this puzzle by figuring out the alternatives to GitHub!It's FOSSAnkush Das💡 Quick Handy Tip
    In Xfce, you can use the panel item "Directory Menu" to get quick access to files from anywhere. This is like the Places extension in GNOME, but better.
    In the configuration menu for it, provide the file extension in the following format *.txt;*.jsonc as shown in the screenshot above to access the files quickly. Clicking on those files opens it in the default app.
    🤣 Meme of the Week
    The ricing never stops! 👨‍💻
    🗓️ Tech Trivia
    On May 27, 1959, MIT retired the Whirlwind computer, a groundbreaking machine famous for pioneering real-time computing and magnetic core memory.
    🧑‍🤝‍🧑 FOSSverse Corner
    ProFOSSer Sheila is having an issue with MX Linux, can you help?
    MX Linux / XFCE missing desktop background image!I am at a loss as to how to fix a new issue on MX-Linux Xfce that started about 30 min ago. I was working on things and my windows are always only expanded far enough right so that I can still see my Conky (top-right on desktop). I clicked outside the window on Conky and it disappeared. So did the background image. Later, switching workspaces, I found the same was true on all of them and when I right clicked on the desktop, no context menu. I went in to the desktop settings and tried to apply a…It's FOSS CommunitySheila_Flanagan❤️ With love
    Share it with your Linux-using friends and encourage them to subscribe (hint: it's here).
    Share the articles in Linux Subreddits and community forums.
    Follow us on Google News and stay updated in your News feed.
    Opt for It's FOSS Plus membership and support us 🙏
    Enjoy FOSS 😄
  25. by: Women in Tech
    Wed, 28 May 2025 21:38:08 +0000

    In this Q&A, we sit down with Tina Schniebs, Board Treasurer for Women in Technology (WIT) and a digital finance risk management Deputy Director at Ridgeline International. She shares her insights on the Leadership Foundry, her journey through the program and advice for women considering board service. Tina Schniebs, WIT Treasurer and Chair, Finance Committee Can you start by telling us a bit about your roles with WIT and Ridgeline International? At WIT, I serve as the Board Treasurer, overseeing the Finance Committee and ensuring our financials run smoothly. In my day job, I work in digital finance risk management, where I teach, consult and speak on how digitizing finance impacts our everyday lives and our federal, defense and intelligence communities – and how they can use technology, both offensively and defensively, to achieve their mission objectives. What is the Leadership Foundry and how did you get involved? WIT’s mission is to empower women in technology from the classroom to the boardroom, guiding women from early career stages through executive leadership and board service. The Leadership Foundry fulfills the second part of that mission. When I first heard about it, I had just started a business. I was heavily focused on getting it up and running, so I knew I was not yet in a position to take on a board seat within the company that we had grown. The program seemed like a great opportunity to better understand what board service entails and get connected with other organizations that are looking for board members with experience bringing up a small business successfully. How has the program evolved over time and how did the new certification enhance your experience? I first joined during COVID, which was challenging due to the virtual format, but the program has since evolved to include a board certification, providing a clear focus on preparing participants for actual board roles. The changes that they made for this new cohort really nailed down the point of the experience – it’s not just learning what being a board member is like, but actually wanting to be on a board and being prepared to do it. While the certification isn't strictly necessary, it adds value by clearly defining the purpose of the Leadership Foundry for participants. It provides a structured curriculum and connects participants with a network of people as part of the National Association of Certified Directors (NACD), helping women access board opportunities. It’s not just about learning what a board is; it's about preparing to serve on one. Can you describe the structure of the Leadership Foundry program? The program includes monthly in-person meetings featuring guest speakers with board experience, covering topics like private company boards, venture funding and public board challenges. There’s also a weekly virtual study group to discuss the certification material, fostering a collaborative learning environment. My cohort was small, with just six women, which allowed for close networking. My cohort of women were very much ready to do board service, or had done some sort of board service in the past. So they were very focused on, I want a public company board seat – I'm looking for access to that board seat. How do I get that? What's the networking that I need to do? What does public company service look like versus private company service? What's the difference between a non-profit board and a for-profit board? How did the program help you grow professionally? The most transformative aspect was learning to shift my mindset from executive decision-making to board-level thinking. Being an executive doesn't necessarily prepare you for a board role, where the focus is on risk management and strategic oversight rather than day-to-day operations. Networking with accomplished women in my cohort and hearing firsthand accounts from experienced board members were also invaluable. In fact, I did a think tank event with one of the ladies from the cohort, Theresa Caragol, about risk management and things that we learned about each other. I think it's also given me a lot more confidence in stepping up to the table and saying: I have a voice too. I understand this stuff. I went through this training program, so I know what I'm talking about. I know that this is what we're supposed to be doing, rather than just relying on your instincts. It gives you a little bit more certainty in the guidance that you're providing to the organization. How did the program push you outside of your comfort zone? How did it help you address challenges unique to women in leadership? The industry I've been in for 23 years is male dominated, and I was the only woman at our company for the first 13 months. It was very comfortable in that position, but being with this cohort of women helped me to better understand what their challenges are and how they navigated their career fields to get where they were. One of the speakers that joined us, for instance, was a man that is doing venture funding in the seed capital rounds. It came up during that discussion that there is less funding provided to women, and particularly minority women, in the seed funding fields. That really opened a neuron chain for me. I didn't realize that there was that kind of bias because as a financial advisor, you look at the balance, your profitability or the numbers. I'm a big advocate of financial privacy – if the applications were filled out in a way where you couldn't see the biographic information of the person actually filing the application, wouldn’t that make the playing field more fair? Companies should only be quantitatively evaluating a company for their growth potential, not qualitatively evaluating the employees or the founders. The certification test was also tough, requiring a shift in thinking from executive to risk manager. The test involves scenario-based questions with a unique scoring system where answering incorrectly hurts your score, but not answering at all has no impact. It was a challenging format, but it reinforced the mindset shift the program aims to teach. What advice would you give to women considering applying to join the Leadership Foundry? It's important to understand why you want to pursue board service. The program is ideal for those with executive experience who are ready to make the transition, not for middle managers or those still considering their career direction. If you want to get in and you think that the Leadership Foundry is the right step for you, you need to focus on the reasons that you want to be a director or a board member – what is the thing that you want to do next in your career and why? Board service, in a lot of situations, is a part time position and it doesn't pay. And if it does pay, you've bought stock, or you had to financially invest in the company that you're getting on the board for. So you really have to think, am I willing to split my time between their full time job and a board position? If you're unsure, there are resources to help you decide if board service is right for you. But we also need a space for women within WIT to ask the questions: What is board service? How does it work? Is it right for me? Is this the next step in my career that I actually want to take? Or do I want to specialize in my area? Do I want to go into executive leadership? Do you have a risk mindset? Do you have the kind of a mindset that puts you in a position to make hard decisions outside of what an executive would make? That's a consideration that you need to make, because board service is not for everybody. It’s okay to be a subject matter expert or operator without pursuing executive or board roles. We need to emphasize that career satisfaction comes from finding the right path, not necessarily following traditional progressions. Ready to take your career to the next level? Applications for The Leadership Foundry are now open! Apply Now

Important Information

Terms of Use Privacy Policy Guidelines We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.