نویسنده: post Bina

  • 6.34 Million Google Clicks! 🤩

    6.34 Million Google Clicks! 🤩


    Yesterday Online PNG Tools smashed through 6.33M Google clicks and today it’s smashed through 6.34M Google clicks! That’s 10,000 new clicks in a single day – the smash train keeps on rollin’!

    What Are Online PNG Tools?

    Online PNG Tools offers a collection of easy-to-use web apps that help you work with PNG images right in your browser. It’s like a Swiss Army Knife for anything PNG-related. On this site, you can create transparent PNGs, edit icons, clean up logos, crop stamps, change colors of signatures, and customize stickers – there’s a tool for it all. The best part is that you don’t need to install anything or be a graphic designer. All tools are made for regular people who just want to get stuff done with their images. No sign-ups, no downloads – just quick and easy PNG editing tools.

    Who Created Online PNG Tools?

    Online PNG Tools were created by me and my team at Browserling. We’ve build simple, browser-based tools that anyone can use without needing to download or install anything. Along with PNG tools, we also work on cross-browser testing to help developers make sure their websites work great on all web browsers. Our mission is to make online tools that are fast, easy to use, and that are helpful for everyday tasks like editing icons, logos, and signatures.

    Who Uses Online PNG Tools?

    Online PNG Tools and Browserling are used by everyone – from casual users to professionals and even Fortune 100 companies. Casual users often use them to make memes, edit profile pictures, or remove backgrounds. Professionals use them to clean up logos, design icons, or prepare images for websites and apps.

    Smash too and see you tomorrow at 6.35M clicks! 📈

    PS. Use coupon code SMASHLING for a 30% discount on these tools at onlinePNGtools.com/pricing. 💸



    Source link

  • Designing for Flow, Not Frustration: The Transformation of Arts Corporation Through Refined Animation

    Designing for Flow, Not Frustration: The Transformation of Arts Corporation Through Refined Animation


    You know what they say about playing sounds on a website: don’t. Autoplaying audio is often considered intrusive and disruptive, which is why modern web practices discourage it. However, sound design, when used thoughtfully, can enhance the user experience and reinforce a brand’s identity. So when Arts Corporation approached me to redesign their website with a request to integrate audio, I saw an opportunity to create an immersive experience that complemented their artistic vision.

    To ensure the sound experience was as seamless as possible, I started thinking about ways to refine it, such as muting audio when the tab is inactive or when a video is playing. That focus on detail made me wonder: what are some other UX improvements that are often overlooked but could make a significant difference? That question set the foundation for a broader exploration of how subtle refinements in animation and interaction design could improve the overall user experience.

    When an Idea is Good on Paper

    The client came in with sketches and a strong vision for the website, including a key feature: “construction lines” overlaid across the design.

    These lines had to move individually, as though being “pushed” by the moving cursor. While this looked great in concept, it introduced a challenge: ensuring that users wouldn’t become frustrated when trying to interact with elements positioned behind the lines. 

    After some testing and trying to find ways to keep the interaction, I realized a compromise was necessary. Using GSAP ScrollTrigger, I made sure that when sections including buttons and links became visible, the interactive lines would be disabled. In the end, the interaction remained only in a few places, but the concept wasn’t worth the frustration.

    Splitting Text Like There’s No Tomorrow

    Another challenge in balancing animation and usability was ensuring that text remained readable and accessible. Splitting text has become a standard effect in the industry, but not everyone takes the extra step to prevent issues for users relying on screen readers. The best solution in my case was to simply revert to the original text once the animation was completed. Another solution, for those who need the text to remain split, would be using aria-label and aria-hidden.

    <h1 aria-label="Hello world">
      <span aria-hidden="true">
        <span>H</span>
        <span>e</span>
        <span>l</span>
        <span>l</span>
        <span>o</span>
      </span>
      <span aria-hidden="true">
        <span>W</span>
        <span>o</span>
        <span>r</span>
        <span>l</span>
        <span>d</span>
      </span>
    </h1>

    This way the user hears only the content of the aria-label attribute, not the text within the element.

    Scroll-Based Disorientation

    Another crucial consideration was scroll-based animations. While they add depth and interactivity, they can also create confusion if users stop mid-scroll and elements appear frozen in unexpected positions.

    Example of scroll-based animation stopped between two states
    Example of a scroll-based animation stopped between two states

    To counter this, I used GSAP ScrollTrigger’s snap feature. This ensured that when users stopped scrolling, the page would snap to the nearest section naturally, maintaining a seamless experience.

    Arrays Start at 5?

    Autoplaying sliders can be an effective way to signal interactivity, drawing users into the content rather than letting them assume it’s static. However, they can also create confusion if not implemented thoughtfully. While integrating the site, I realized that because some slides were numbered, users might land on the page and find themselves on the fifth slide instead of the first, disrupting their sense of flow.

    To address this, I set sliders to autoplay only when they entered the viewport, ensuring that users always started at the first slide. This not only maintained consistency but also reinforced a structured and intuitive browsing experience. By making autoplay purposeful rather than arbitrary, we guide users through the content without causing unnecessary distractions.

    Transition Confusion

    Page transitions play a crucial role in maintaining a smooth, immersive experience, but if not handled carefully, they can lead to momentary confusion. One challenge I encountered was the risk of the transition overlay blending with the footer, since both were black in my design. Users would not perceive a transition at all, making navigation feel disjointed.

    To solve this, I ensured that transition overlays had a distinct contrast by adding a different shade of black, preventing any ambiguity when users navigate between pages. I also optimized transition timing, making sure animations were fast enough to keep interactions snappy but smooth enough to avoid feeling abrupt. This balance created a browsing experience where users always had a clear sense of movement and direction within the site.

    I Can Feel a Shift

    A common issue in web development that often gets overlooked is the mobile resize trigger that occurs when scrolling, particularly when the browser’s address bar appears or disappears on some devices. This resize event can disrupt the smoothness of animations, causing sudden visual jumps or inconsistencies as the page shifts.

    To tackle this, I made sure that ScrollTrigger wouldn’t refresh or re-trigger its animations unnecessarily when this resize event occurred by turning on ignoreMobileResize:

    ScrollTrigger.config({
       ignoreMobileResize: true
     });

    I also ensured that any CSS or JavaScript based on viewport height would not be recalculated on a vertical resize on mobile. Here’s a utility function I use to handle resize as an example: 

    /**
     * Attaches a resize event listener to the window and executes a callback when the conditions are met.
     * 
     * @param {Function} callback - The function to execute when the resize condition is met.
     * @param {number} [debounceTime=200] - Time in milliseconds to debounce the resize event.
     */
    function onResize(callback, debounceTime = 200) {
      let oldVh = window.innerHeight;
      let oldVw = window.innerWidth;
      const isTouchDevice = 'maxTouchPoints' in navigator && navigator.maxTouchPoints > 0;
    
      // Define the resize handler with debounce to limit function execution frequency
      const resizeHandler = $.debounce(() => {
        const newVh = window.innerHeight;
        const newVw = window.innerWidth;
    
        /**
         * Condition:
         *  - If the device is touch and the viewport height has changed significantly (≥ 25%).
         *  - OR if the viewport width has changed at all.
         * If either condition is met, execute the callback and update old dimensions.
         */
        if ((isTouchDevice && Math.abs(newVh - oldVh) / oldVh >= 0.25) || newVw !== oldVw) {
          callback();
          oldVh = newVh;
          oldVw = newVw;
        }
      }, debounceTime);
    
      // Attach the resize handler to the window resize event
      $(window).on('resize', resizeHandler);
    }

    Copy That! Rethinking Contact Links

    It was the client’s request to have a simple contact link with a “mailto” instead of a full contact page. While this seemed like a straightforward approach, it quickly became clear that mailto links come with usability issues. Clicking one automatically opens the default email app, which isn’t always the one the user actually wants to use. Many people rely on webmail services like Gmail or Outlook in their browser, meaning a forced mail client launch can create unnecessary friction. Worse, if the user is on a shared or public computer, the mail app might not even be configured, leading to confusion or an error message.

    To improve this experience, I opted for a more user-friendly approach: mailto links would simply copy the email to the clipboard and display a confirmation message. 

    The Takeaway

    This project reinforced the importance of balancing creativity with usability. While bold ideas can drive engagement, the best experiences come from refining details users may not even notice. Whether it’s preventing unnecessary animations, ensuring smooth scrolling, or rethinking how users interact with contact links, these small decisions make a significant impact. In the end, great web design isn’t just about visuals, it’s about crafting an experience that feels effortless for the user.



    Source link

  • Understand the Key Differences & Choose the Right Solution


    In today’s rapidly evolving cyber landscape, organizations face an increasing number of sophisticated threats. Consequently, the need for robust cybersecurity measures has never been more critical. Two prominent solutions in this domain are Endpoint Detection and Response (EDR) and Extended Detection and Response (XDR). While both serve essential roles in safeguarding an organization’s digital assets, they cater to different needs and offer distinct functionalities. This article delves deep into the nuances of EDR vs XDR, providing insights into their features, differences, and when to deploy each solution.

    What is EDR?

    Endpoint Detection and Response (EDR) is a cybersecurity approach that focuses primarily on monitoring and securing endpoint devices such as laptops, desktops, and servers. EDR solutions are designed to detect, investigate, and respond to potential threats at the endpoint level. By employing advanced analytics and automated responses, EDR tools operate under the premise of an “assume breach” mentality. This means they are always on the lookout for suspicious activities, even if the organization believes its systems are secure.

    Key Features of EDR

    • Real-time Monitoring: EDR solutions provide continuous surveillance of endpoint activities, enabling organizations to detect anomalies swiftly.
    • Automated Response: EDR tools can automatically contain threats, limiting their potential impact before human intervention is required.
    • Data Collection: These solutions gather extensive data from endpoints, including system logs, file access, and user activities, allowing for thorough investigations.
    • Threat Intelligence: EDR platforms leverage threat intelligence to enhance their detection capabilities, identifying known threats and emerging vulnerabilities.

    Benefits of EDR

    • Focused Security: EDR is primarily designed to protect endpoints, making it an excellent choice for organizations with significant endpoint exposure.
    • Cost-effective: For businesses with limited budgets, EDR solutions can provide robust endpoint protection without the higher costs associated with more comprehensive solutions.
    • Scalability: As organizations grow, EDR solutions can easily adapt to increasing numbers of endpoints and evolving threats.

    What is XDR?

    Extended Detection and Response (XDR) is a holistic cybersecurity solution that integrates data from multiple security layers, including endpoints, networks, servers, and cloud environments. Unlike EDR, which focuses solely on endpoint devices, XDR aims to provide a comprehensive view of an organization’s security posture by correlating data across various sources. This enables security teams to detect and respond to threats more effectively.

    Key Features of XDR

    • Unified Security Approach: XDR consolidates data from various security tools and platforms, offering a centralized view of threats across the entire infrastructure.
    • Enhanced Visibility: By analyzing data from multiple sources, XDR provides deeper insights into potential threats, making it easier to identify complex attack patterns.
    • Automated Threat Response: Like EDR, XDR also employs automation to respond to threats, but it does so across a broader range of data sources.
    • Cross-domain Detection: XDR is capable of detecting threats that may originate from different areas, such as network traffic, cloud applications, and email systems.

    Benefits of XDR

    • Comprehensive Coverage: XDR’s ability to integrate data from various sources ensures that organizations have a complete view of their security landscape.
    • Improved Incident Response: By providing a unified view of threats, XDR allows security teams to respond more quickly and effectively to incidents.
    • Reduced Complexity: XDR simplifies security operations by reducing the number of tools and interfaces security teams must manage.

    EDR vs XDR: Key Differences

    While both EDR and XDR are essential components of a modern cybersecurity strategy, they serve different purposes and have distinct features. Below is a comparison highlighting the critical differences between EDR and XDR:

    Feature

    EDR (Endpoint Detection and Response)

    XDR (Extended Detection and Response)

    Scope Focuses on endpoint devices Covers multiple security layers
    Data Sources Endpoint-specific data Integrates data from various sources
    Detection Methods Signature-based and behavioral analysis Advanced analytics, AI, and data correlation
    Threat Detection Primarily endpoint threats Advanced threats across all domains
    Incident Response Endpoint-focused Cross-domain response
    Integration Typically integrated with endpoint tools Integrates with multiple security solutions

    When to Choose EDR

    Organizations may opt for EDR solutions under specific circumstances:

    • Small to Medium-Sized Infrastructure: Businesses with fewer endpoints and primarily endpoint-based threats may find EDR sufficient for their needs.
    • Budget Constraints: EDR solutions tend to be more cost-effective than XDR, making them ideal for organizations with limited financial resources.
    • Strong Endpoint Security Posture: If an organization already has robust endpoint security measures in place, EDR can enhance those efforts without overwhelming complexity.

    When to Choose XDR

    On the other hand, XDR is more suitable for organizations facing different challenges:

    • Complex IT Environments: Organizations with extensive IT infrastructures that require visibility across endpoints, networks, and cloud applications should consider XDR.
    • High-Risk Industries: Sectors such as finance, healthcare, and government, which are often targeted by sophisticated threats, can benefit from XDR’s comprehensive approach.
    • Need for Advanced Analytics: Organizations looking to leverage machine learning and AI to identify patterns across multiple data sources will find XDR more advantageous.

    The Role of Seqrite EDR and XDR

    Seqrite offers advanced EDR and XDR solutions tailored to meet the diverse needs of organizations. With a focus on comprehensive endpoint protection and extended visibility, Seqrite’s offerings empower businesses to strengthen their security posture effectively.

    Seqrite EDR

    Seqrite EDR provides real-time monitoring and automated response capabilities, ensuring that organizations can detect and mitigate threats swiftly. Its user-friendly interface and robust analytics make it a valuable addition to any cybersecurity strategy.

    Seqrite XDR

    Seqrite XDR enhances threat detection and response capabilities by integrating data from various security layers. This solution empowers organizations to gain deeper insights into their security landscape, facilitating quicker and more effective incident response.

    Conclusion

    In the ongoing battle against cyber threats, understanding the distinctions between EDR and XDR is vital for organizations looking to enhance their security measures. While EDR excels in endpoint protection, XDR provides a more comprehensive view of an organization’s security posture by integrating data across multiple sources. Depending on the specific needs and challenges faced by an organization, either solution—or a combination of both—can significantly bolster cybersecurity efforts.

    By investing in advanced solutions like Seqrite EDR and XDR, organizations can ensure they are well-equipped to navigate the complexities of the modern threat landscape and safeguard their digital assets effectively.



    Source link

  • 6.35 Million Google Clicks! 🤑

    6.35 Million Google Clicks! 🤑


    Yesterday Online PNG Tools smashed through 6.34M Google clicks and today it’s smashed through 6.35M Google clicks! That’s 10,000 new clicks in a single day – the smash train keeps on rollin’!

    What Are Online PNG Tools?

    Online PNG Tools offers a collection of easy-to-use web apps that help you work with PNG images right in your browser. It’s like a Swiss Army Knife for anything PNG-related. On this site, you can create transparent PNGs, edit icons, clean up logos, crop stamps, change colors of signatures, and customize stickers – there’s a tool for it all. The best part is that you don’t need to install anything or be a graphic designer. All tools are made for regular people who just want to get stuff done with their images. No sign-ups, no downloads – just quick and easy PNG editing tools.

    Who Created Online PNG Tools?

    Online PNG Tools were created by me and my team at Browserling. We’ve build simple, browser-based tools that anyone can use without needing to download or install anything. Along with PNG tools, we also work on cross-browser testing to help developers make sure their websites work great on all web browsers. Our mission is to make online tools that are fast, easy to use, and that are helpful for everyday tasks like editing icons, logos, and signatures.

    Who Uses Online PNG Tools?

    Online PNG Tools and Browserling are used by everyone – from casual users to professionals and even Fortune 100 companies. Casual users often use them to make memes, edit profile pictures, or remove backgrounds. Professionals use them to clean up logos, design icons, or prepare images for websites and apps.

    Smash too and see you tomorrow at 6.36M clicks! 📈

    PS. Use coupon code SMASHLING for a 30% discount on these tools at onlinePNGtools.com/pricing. 💸



    Source link

  • Mastering Carousels with GSAP: From Basics to Advanced Animation

    Mastering Carousels with GSAP: From Basics to Advanced Animation


    Carousels are a fairly common UI pattern (there are many excellent carousel and slider examples available on Codrops). While carousel designs vary depending on the use case, the following demos explore how the GreenSock Animation Platform (GSAP) can be used to achieve seamless looping, smooth animations, and ultimately, a better user experience.

    This article is for frontend designers and developers interested in enhancing the functionality and visual appeal of a standard horizontal carousel. Familiarity with JavaScript and basic GSAP methods will be helpful, but anyone looking for inspiration and practical examples may find the following content useful.

    What You’ll Learn

    • Basic carousel implementation using HTML and CSS
    • How to use gsap.utils.wrap() and horizontalLoop()
    • Advanced animation techniques, including image parallax and function-based values

    Our Basic Carousel

    Let’s start with a horizontally scrolling carousel using only HTML and CSS:

    <div class="carousel">
        
        <div class="carousel-slide">
          <img src="https://images.unsplash.com/photo-1659733582156-d2a11801e59f?q=50&w=1600">
          <h2>We're No</h2>
          <h5>Strangers to love</h5>
        </div>
            
        ...
    
    </div>
    .carousel {
      width: 100vw;
      height: 80vh;
      gap: 10px;
      overflow-x: auto;
      scroll-snap-type: x mandatory;
      display: flex;
      -webkit-overflow-scrolling: touch;
    }
    
    .carousel-slide {
      position: relative;
      flex: 0 0 50%;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      color: white;
      scroll-snap-align: center;
      overflow: hidden;
    }
    
    .carousel-slide img {
      position: absolute;
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
    
    h2 {
      position: relative;
      margin: 0;
      font-size: 1.8rem;
    }
    
    h5 {
      position: relative;
      margin: 2% 0 0 0;
      font-size: 1rem;
      font-weight: 100;
      letter-spacing: 0.3px;
    }
    
    /* Simplify the scroll bar appearance */
    ::-webkit-scrollbar {
      height: 13px;
    }
    
    ::-webkit-scrollbar-track {
      background: transparent;
    }
    
    ::-webkit-scrollbar-thumb {
      border-top: 6px solid #000;
      background: #555;
      width: 50%;
    }
    
    ::-webkit-scrollbar-thumb:hover {
      background: #bbb;
    }
    
    @media (max-width: 500px) {
      .carousel-slide {
        flex: 0 0 80%;
      }
    
      ::-webkit-scrollbar-thumb {
        width: 80%;
      }
    }

    Here’s the result:

    It uses scroll snapping and some custom styling on the scrollbar. Nothing fancy, but it works even when JavaScript is disabled.

    Note that the HTML above is intentionally concise. However, in production, it’s important to follow accessibility best practices, including using alt text on images and descriptive ARIA attributes for screen reader users.

    Building on the Foundation – GSAP Demo 1A

    To see how GSAP can enhance a carousel, we’ll explore two different approaches—the first using gsap.utils.wrap(). Wrap is one of several handy utility methods included in gsap.js—no plugin required! Given a min/max range, it returns a value within that range:

     gsap.utils.wrap(5, 10, 12); // min 5, max 10, value to wrap 12: returns 7

    The example above returns 7 because 12 is 2 more than the maximum of 10, so it wraps around to the start and moves 2 steps forward from there. In a carousel, this can be used to loop infinitely through the slides.

    Here’s a simple demo of how it can be applied:

    In the HTML, a <nav> block has been added that contains previous/next buttons and progress text:

    <nav class="carousel-nav">
      <button class="prev" tabindex="0" aria-label="Previous Slide"></button>
      <button class="next" tabindex="0" aria-label="Next Slide"></button>
      <div>1/8</div>
    </nav>

    A few new rules have been added to the CSS, most importantly to .carousel-slide-abs:

    .carousel-slide-abs {
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      width: 75vw;
      height: 70vh;
    }

    In the JS, we override the carousel’s scroll-snap-type and display the <nav> block. Since we no longer have a scrollable area, the buttons are necessary to maintain keyboard accessibility. Safari requires tabindex="0" to allow users to tab to them. Additionally, aria-labels are important since the buttons have no visible text content.

    We apply the new class to each slide, which effectively stacks them all in the center. We also set the initial opacity: 1 for the first slide and 0 for the rest:

    gsap.set(".carousel", { "scroll-snap-type": "none" });
    
    gsap.set(".carousel-nav", { display: "block" });
    
    slides.forEach((slide, i) => {
      slide.classList.add("carousel-slide-abs");
      gsap.set(slide, { opacity: (i === 0 ? 1 : 0) });
    });

    Next, we need a function that transitions to the previous or next slide. changeSlide() is passed a direction parameter of either positive or negative 1. Inside this function, we:

    1. Fade out the current slide
    2. Update the current slide index using gsap.utils.wrap()
    3. Fade in the new current slide
    4. Update the progress text

    The different easing on the outro and intro tweens helps prevent excessive overlapping opacity during the crossfade.

    next.addEventListener("click", () => changeSlide( 1 ));
    prev.addEventListener("click", () => changeSlide( -1 ));
    
    function changeSlide( dir ) {
      
      gsap.to(slides[currentIndex], { opacity: 0, ease: "power3" });
      
      currentIndex = gsap.utils.wrap(0, slides.length, (currentIndex += dir));
      
      gsap.to(slides[currentIndex], { opacity: 1, ease: "power3.inOut" });
      
      gsap.set(".carousel-nav div", { innerText: `${currentIndex + 1}/${slides.length}` });
    
    }

    Polishing the Transition – GSAP Demo 1B

    To take this idea further, let’s add more detail to the outro and intro animations:

    For the 3D perspective to work, we’ve added perspective: 750px to .carousel-slide-abs in the CSS.

    Instead of targeting the slides themselves, we set the opacity of their child elements to 0—except for those in the first slide.

     gsap.set(slide.children, { opacity: (i === 0 ? 1 : 0) });

    Then, we do the following inside changeSlide():

    1. Store a reference to the outgoing slide’s children
    2. Update currentIndex, just as before
    3. Create a const for the incoming slide’s children
    4. Kill tweens on both slides’ children to prevent conflicts if slides change rapidly
    5. Create a timeline for the transition:
    gsap.timeline({ defaults:{ ease: "expo" } })
      // update progress text
      .set(".carousel-nav div", { innerText: `${currentIndex + 1}/${slides.length}` })
    
      // old slide outro
      .to(oldLayers[0], {
        duration: 0.3,
        rotateY: (dir<0 ? -75 : 75),
        scale: 0.6,
        ease: "power2.in"
      }, 0)
      .to(oldLayers, {
        duration: 0.3,
        opacity: 0,
        ease: "power2.in"
      }, 0)
    
      // new slide intro
      .to(newLayers, {
        opacity: 1,
        ease: "power1.inOut",
        stagger: 0.2
      }, 0.2)
      .fromTo(newLayers[0], {
        rotateY: (dir<0 ? 90 : -90),
        scale: 0.6
      },{
        rotateY: 0,
        scale: 1
      }, 0.3)
      .fromTo([newLayers[1], newLayers[2]], {
        y: 35
      },{
        duration: 1,
        y: 0,
        stagger: 0.14
      }, 0.4);

    Easing and staggers help smooth out and space the movement. The dir parameter modifies the rotationY, adding a subtly unique motion to previous and next actions.

    This basic setup can be easily customized further. Animating a clip-path, applying a blur filter, or experimenting with additional 3D transforms could all produce interesting results.

    A Different Approach – GSAP Demo 2A

    Another way to create a seamless looping carousel with GSAP is to use the horizontalLoop() helper function. Although GSAP helper functions aren’t officially part of the core library, they’re a handy collection of code snippets and shortcuts. They also serve as great learning resources for writing more advanced GSAP code.

    This specific helper function animates elements along their x-axis and repositions them once they’re out of view to create an infinite loop. Here’s a basic implementation:

    Again, we override the CSS and display the <nav> element. Then we call horizontalLoop(), which takes two parameters: an array of the carousel slides and a config object for setting various options.

    const loop = horizontalLoop(slides, {
      paused: true,       // no auto-scroll
      paddingRight: 10,   // match the 10px flex gap
      center: true,       // snap the active slide to the center
      onChange: (slide, index) => { // called when the active slide changes
        if (activeSlide) {
          gsap.to(".active", { opacity: 0.3 });
          activeSlide.classList.remove("active");
        }
        slide.classList.add("active");
        activeSlide = slide;
        gsap.to(".active", { opacity: 1, ease: "power2.inOut" });
        gsap.set(".carousel-nav div", { innerText: `${index + 1}/${slides.length}` });
      }
    });

    The most notable of these options is the onChange callback, where we can write code that executes each time the active slide changes. In this example, we’re removing and adding the “active” class name and tweening the opacity to draw more focus to the center slide.

    The helper function returns a timeline with several useful added methods, including next(), previous(), and toIndex(). We’ll use these to add navigation functionality to our previous/next buttons, as well as to the individual slides:

    next.addEventListener("click", () => loop.next({ duration: 1, ease: "expo" }));
    prev.addEventListener("click", () => loop.previous({ duration: 1, ease: "expo" }));
    
    // each slide can function as a button to activate itself
    slides.forEach((slide, i) => {
      slide.addEventListener("click", () => loop.toIndex(i, {duration: 1, ease: "expo"}))
    });

    Finally, we set the initial carousel state by adjusting the opacity of each slide and calling toIndex() with no tween duration, which centers the active slide.

    gsap.set(".carousel-slide", { opacity: (i) => (i === 0 ? 1 : 0.3) });
    
    loop.toIndex(0, { duration: 0 }); 

    If you’re unfamiliar with function-based values in GSAP, this is an amazing feature—definitely check out that link to learn how they work. Here, we’re iterating through each element with the class name “carousel-slide,” returning an opacity value of 1 for the first slide and 0.3 for the rest.

    The remainder of the JS is just the helper function, copied and pasted from the GSAP docs demo. In most cases, you won’t need to modify anything inside it. (We’ll look at an exception in Demo 2C.)

    Add Draggable & InertiaPlugin – GSAP Demo 2B

    To make the carousel move on drag, we’ll need two plugins: Draggable and the Inertia Plugin. Once those scripts are included, you can set draggable: true in the config object.

    In addition to drag behavior, this iteration includes some text animation, with logic to prevent it from running on the first load (plus hover in/out animations on the nav buttons).

    onChange: (slide, index) => { // called when the active slide changes
      if (activeSlide) {
        gsap.to(".carousel h2, .carousel h5", { overwrite: true, opacity: 0, ease: "power3" });
        gsap.to(".active", { opacity: 0.3 });
        activeSlide.classList.remove("active");
      }
      slide.classList.add("active");
      activeSlide = slide;
      
      // intro animation for new active slide
      gsap.timeline({ defaults:{ ease:"power1.inOut" } })
    
        // fade in the new active slide
        .to(".active", { opacity: 1, ease: "power2.inOut" }, 0)
    
        // fade out the progress text, change its value, fade it back in
        .to(".carousel-nav div", { duration: 0.2, opacity: 0, ease: "power1.in" }, 0)
        .set(".carousel-nav div", { innerText: `${index + 1}/${slides.length}` }, 0.2)
        .to(".carousel-nav div", { duration: 0.4, opacity: 0.5, ease: "power1.inOut" }, 0.2)
    
        // fade in the text elements and translate them vertically
        .to(".active h2, .active h5", { opacity: 1, ease: "power1.inOut" }, 0.3)
        .fromTo(".active h2, .active h5", { y:(i)=>[40,60][i] },{ duration: 1.5, y: 0, ease: "expo" }, 0.3)
    
        // skip active slide animation on first run
        .progress( firstRun? 1: 0 )
    }

    Adding Parallax – GSAP Demo 2C

    To make the movement more engaging, let’s calculate each slide’s horizontal progress and use it to create a parallax effect.

    Until now, we haven’t modified the helper function. However, to calculate slide progress, this version includes one change inside horizontalLoop().

    Now, every time the carousel timeline updates, slideImgUpdate() is called. This function sets each image’s xPercent based on the progress of its parent slide. Progress is 0 when the slide is offstage to the left, and 1 when it’s offstage to the right.

    function slideImgUpdate(){
      slides.forEach( slide => {
        const rect = slide.getBoundingClientRect();
        const prog = gsap.utils.mapRange(-rect.width, innerWidth, 0, 1, rect.x);
        const val = gsap.utils.clamp(0, 1, prog );
        gsap.set(slide.querySelector("img"), {
          xPercent: gsap.utils.interpolate(0, -50, val)
        });
      });
    }

    GSAP utility functions mapRange(), interpolate(), and clamp() make the progress calculation much easier. Note, in the CSS, the width of .carousel-slide img is increased to 150%, so there will be enough image for a 50% horizontal movement.

    Taking It Further

    There are endless ways you could build on these demos, customizing both appearance and functionality. A few ideas include:

    • Modify how many slides are shown at once—a single, full-frame version could be interesting, as could several smaller slides to create a cover flow effect. In both of those examples, the progress indicator also became a fun area for experimentation.
    • Additional details could be added by calling custom functions inside the helper function’s onPress, onRelease, or onThrowComplete callbacks. Here’s one more iteration on Demo 2, where the entire carousel shrinks while the pointer is held down.
    • The carousel could even serve as navigation for a separate animated page element, like on Nite Riot.
    • If you want the carousel to respond to mouse wheel movements, GSAP’s Observer plugin offers an easy way to handle those events.
    • With GSAP’s matchMedia(), you can specify different animations for various viewport widths and tailor behavior for users who prefer reduced motion.



    Source link

  • Beware! Fake ‘NextGen mParivahan’ Malware Returns

    Beware! Fake ‘NextGen mParivahan’ Malware Returns


    Cybercriminals continually refine their tactics, making Android malware more insidious and challenging to detect. A new variant of the fake NextGen mParivahan malware has emerged, following its predecessor’s deceptive strategies but introducing significant enhancements.

    Previously, attackers exploited the government’s traffic notification system to distribute malware, sending fake messages that appeared to be official traffic violation alerts. These messages contained details like ticket numbers and vehicle registration information to appear legitimate, tricking users into downloading a malicious app. Once installed, the app requested extensive permissions, hid its icon, and silently exfiltrated sensitive data, including SMS messages—while communicating with attackers via a Telegram bot.

    Figure 1. WhatsApp message received by Victim

    In this latest variant, the malware is distributed under the guise of “NextGen mParivahan,” mimicking the official government application. It uses the same distribution method as before—leveraging fake traffic violation messages to lure users into installing the malicious app.

    The official NextGen mParivahan app, developed by the Ministry of Road Transport & Highways, provides digital access to driving licenses, vehicle registration certificates, and other transport services. Available on the Google Play Store, it replaces the earlier mParivahan app with improved features and user experience.

    However, cybercriminals have seized the opportunity presented by the app’s rebranding, distributing malware under the “NextGen mParivahan” name to deceive users. In this latest variant, the malware retains its SMS-stealing capabilities. It has significantly expanded its reach—now targeting messages from social media, communication, and e-commerce apps, posing an even more significant threat to user privacy.

    Moreover, some samples have employed a stealthier command-and-control (C2) mechanism by concealing its C2 details within a compiled .so file and dynamically generating them at runtime. This approach greatly complicates detection and analysis. Some samples are intentionally malformed to further hinder security efforts and leverage multi-stage dropper-payload architectures to bypass signature-based and heuristic detection systems.

    Our previous blog analyzed the earlier version’s infection chain and communication tactics (Beware! Malicious Android Malware Disguised as Government Alerts). These latest variants not only retain those functionalities but expand on them, increasing both their stealth and data theft capabilities.

    In this blog, we’ll explain how this new variant operates and why its new enhancements make it an even greater threat to Android users.

    Technical analysis:

    We came across two variants of the new version: one utilizing a malformed multi-stage dropper-payload architecture and another employing a stealthier C2 extraction method while stealing notification data from other apps.

    1. Malformed multi-stage dropper-payload

    First Stage – Dropper Second Stage – Payload
    File name e_challan_report parivahan
    MD5 ad4626eff5238ce7c996852659c527bc ae1f49bd14027c7adea18147cb02f72a
    App name NextGen mParivahan NextGen mParivahan
    Package Name com.xyz.dropper com.example.icici

    Anti-analysis technique

    The malware author intentionally crafted these dropper and payload APKs to hinder static analysis. Many open-source Android APK analysis tools failed to process this APK, making analysis more challenging. See below:

    Apktool failed to decompile the APK-

    Figure 2. Apktool Error

    Jadx failed to decompile –

    Figure 3. Jadx Error

    Androguard failed to decompile –

    Figure 4. Androguard Error

     

    Bytecode viewer failed to decompile –

    Figure 5. Bytecode viewer Error

    7zip also failed to extract APK file –

    Figure 6. 7zip Error

    Android build tools AAPT (Android Asset Packaging Tool) and AAPT2 (Android Asset Packaging Tool) are also unable to dump the AndroidManifest.xml file –

    Figure 7. AAPT Error

    Additionally, this malformed APK file fails to install on Android 8.1 and earlier versions due to a corrupt XML file, as the OS cannot extract it like later Android versions.

    Figure 8. Android 8.1 APK installation Error

    The error displayed by all these tools indicates an unsupported compression method, meaning the APK file uses an invalid compression technique. However, AAPT and Android OS 8.1 (API level 27) report a corrupt AndroidManifest.xml error unrelated to the unsupported compression method. Despite this, the malformed APK installs and runs smoothly on Android devices and emulators running Android OS 9 (API level 28) and above without any issues.

    Why Do Analysis Tools Fail While Android OS (9+) Runs This APK?

    An APK file is essentially a ZIP archive. Below is its header format, where the values at offsets 08 and 09 indicate the compression method used in the ZIP file.

    Figure 9. Structure of APK ZIP file (Reference: The structure of a PKZip file)

    Android APK files follow the ZIP format and typically use two compression methods:

    1. Store (No Compression) – Used for files that don’t need compression, such as pre-optimized binaries and some assets.
    2. Deflate (Standard Compression) – The most used method for compressing resources, XML files, and other non-executable content.

    The compression method used by most of the APK files –

    Figure 10. Normal file Hex

    The compression method used by this malformed dropper APK file is neither Deflate nor Store. Its value is 0x1998 (decimal 6552), which is not supported by the ZIP format.

     

    Figure 11. Malformed APK Hex
    • All analysis tools strictly follow the ZIP format and expect the compression method to be either Deflate or Store only. However, Android OS only checks whether the compression method is Deflate or not. If it is not Deflate, the OS assumes it to be Store (i.e., uncompressed).
    • Android 9 introduced a different method for parsing monolithic apps compared to Android 8. This new implementation handles asset access differently. As a result, certain APKs that caused manifest corruption errors in Android 8 and earlier versions no longer encounter this issue on Android 9.

    Extracting and decoding AndroidManifest file 

    I wrote a script to extract the raw AndroidManifest.xml from an APK by parsing its ZIP structure. It locates the Central Directory, finds AndroidManifest.xml, extracts its compression details and raw data, and then, by using Androguard, decodes the extracted raw AndroidManifest.xml into a readable XML format.

    Figure 12. Extraction and encoding AndroidManifest.xml

    Below is the decoded AndroidManifest.xml of the Dropper APK. It requests permissions for QUERY_ALL_PACKAGES to list installed apps and REQUEST_INSTALL_PACKAGES to install the payload application.

    Figure 13. Decoded AndroidManifest xml file of Dropper application.

    Below is the decoded AndroidManifest.xml of the Payload APK. It requests sensitive permissions such as RECEIVE_SMS, READ_SMS, and SEND_SMS to access and send SMS messages.

    Figure 14. Decoded AndroidManifest xml from payload application

    Malware execution

    After launch, the Dropper application prompts the user to update the app. Upon clicking “Update,” it requests permission to allow installations from unknown sources. Once granted, it installs the Payload APK, which uses the same icon as the Dropper but hides its icon from the app drawer.

    Figure 15. Dropper application execution

    Now, if the user clicks on the mParivahan app icon, it launches the Payload application. First, it requests SMS and Call permissions. Then, it displays a page asking the user to enter their vehicle and phone numbers to track challan status. Next, it prompts the user to pay ₹1 via PhonePe, Google Pay, or Paytm, requiring them to enter their payment PIN. After the transaction, it shows a confirmation page stating, “Payment completed, wait for 30 minutes, and do not delete the app from the device.”

    Figure 16. Payload application execution

    However, the application steals the entered information in the background and saves it to a Firebase database. Since the app has SMS access permissions, it also captures incoming SMS data and uploads it to Firebase.

    Figure 17. Pin and device info stealing code
    1. Stealthier native c2 extraction and notification stealer

    File name NextGen mParivahan.apk
    MD5 8bf7ea1c35697967a33c0876df5f30b9
    App name NextGen mParivahan
    Package name com.sakurai.endo3798132

     

    Upon launch, the second variant requests SMS and call management permissions. It then prompts the user to grant notification access to the malware. After obtaining all necessary permissions, the user is asked to enter a phone number. Once the user clicks “Continue,” it opens the Google homepage and hides its icon.

    Figure 18. App execution

    Malware, which has access to notification data, continuously monitors notifications. Whenever a new notification is posted, it captures the data and sends it to the C2 server.

    Figure 19. Notification stealer code

    The malware application maintains a list of apps targeted for notification theft. The targeted applications include WhatsApp, Facebook, Amazon, Zomato, Telegram, Google Messages, Gmail etc.

    Figure 20. Targeted application list

    C2 extraction from native code

    The malware dynamically generates the C2 server URL at runtime, avoiding plain-text storage to evade detection. The figure below shows code from the Java section, where the SecreatHeven class is responsible for loading the native library “libbunnycoban.so” and defining native functions. Here, the bunnylovesCarrot() function returns the C2 server URL. There are two additional functions, hiddendandelion() and SecreatAcron(), that return the IP info service URL and IP info token. The malware might use these functions during C2 server generation, as they are not referenced elsewhere in the code.

    Figure 21. Java code loading so file

    Here is a code snippet that shows the code for generating the C2 server from the .so file.

    Figure 22. Code used to construct c2 server from so file

    The logs clearly reveal the C2 server used by this malware –

    Figure 23. c2 mention in logcat

    Both variants also have SMS-stealing capabilities similar to the previous version. They access SMS data and send it to the extracted C2 server or Firebase. Additionally, they implement a bootloader broadcast receiver for persistence, which allows the application to start in the background after the device boots.

     

    MITRE ATT&CK Tactics and Techniques:

    Quick Heal Detection of Android Malware

    Quick Heal detects such malicious applications with variants of Android.Spyagent.A

    It is recommended that all mobile users should install a trusted Anti-Virus like “Quick Heal Mobile Security for Android” to mitigate such threats and stay protected. Our antivirus software restricts users from downloading malicious applications on their mobile devices. Download your Android protection here

    Conclusion:

    This malware variant demonstrates how cybercriminals continuously advance their techniques to evade detection and steal more user data. Leveraging malformed APKs, dynamic C2 generation, and anti-analysis methods makes it increasingly difficult for traditional security tools to identify their malicious activities. Additionally, their ability to access notifications, SMS, and sensitive app data poses a significant risk to user privacy.

    However, as threats evolve, so do analysis methodologies. Security solutions and threat intelligence efforts are improving detection techniques by deep-diving into obfuscation strategies, dynamic analysis, and advanced threat-hunting approaches. Strengthening security awareness, using trusted sources for app installations, and employing modern analysis tools are essential in combating these emerging threats.

    IOCs

    URLs:

    Https[:]//cyberdefensetech[.]cc/

     

    TIPS TO STAY DIGITALLY SAFE: 

    • Download applications only from trusted sources like Google Play Store.
    • Do not click on any links received through messages or any other social media platforms as they may be intentionally or inadvertently pointing to malicious sites.
    • Read the pop-up messages from the Android system before accepting or/allowing any new permissions.
    • Be extremely cautious about what applications you download on your phone, as malware authors can easily spoof the original applications’ names, icons, and developer details.
    • For enhanced phone protection, always use a good antivirus like Quick Heal Mobile Security for Android.

    Don’t wait! Secure your smartphones today with Quick Heal Total Security for Mobiles & Smartphones – Buy or Renew Today!

     



    Source link

  • Apache Tomcat Remote Code Execution Vulnerability


    Apache Tomcat is a popular, open-source web server and servlet container maintained by the Apache Software Foundation. It provides a reliable and scalable environment for executing Java Servlets and serving web pages built using Java Server Pages (JSP). Frequently deployed in both development and production environments, Tomcat plays a crucial role in delivering dynamic Java-based web applications across various enterprise use cases.

    Recently, a critical security vulnerability identified as CVE-2025-24813 was discovered in Apache Tomcat. This vulnerability exploits a flaw in the handling of partial file uploads and session file persistence, potentially allowing attackers to achieve remote code execution (RCE) under certain conditions. The issue arises from how Tomcat’s default servlet manages write operations combined with deserialization logic for persisted session files.

    CVE-2025-24813

    Initially published in early March with a CVSS score of 5.5, the severity of CVE-2025-24813 was later reassessed and upgraded to 9.8 (High). Recognizing the potential impact of this flaw, the Cybersecurity and Infrastructure Security Agency (CISA) added it to its Known Exploited Vulnerabilities (KEV) catalogue, underscoring the urgency for affected organizations to patch their systems.

    CVE-2025-24813 is a critical vulnerability in Apache Tomcat that can lead to remote code execution (RCE) when specific server configurations are in place. The issue arises from how Tomcat handles partial PUT requests in conjunction with file-based session persistence.

    This issue becomes exploitable when the default servlet is explicitly configured with ‘readonly’ parameter is set to false — a setting that enables write operations such as HTTP PUT. By default, Tomcat sets ‘readonly’ to true, which restricts write access and helps mitigate risk. This parameter is defined in the web.xml configuration file, typically located in the conf/ directory of the Tomcat installation.

    When partial PUT support is also enabled (enabled by default), an attacker can exploit this behaviour to upload a crafted serialized payload, targeting a session file. If Tomcat is configured to persist session data to disk, the uploaded file may later be automatically deserialized by the server, resulting in attacker-controlled code execution.

    The vulnerability affects the following versions of Apache Tomcat:

    • 11.0.0‑M1 through 11.0.2
    • 10.1.0‑M1 through 10.1.34
    • 9.0.0‑M1 through 9.0.98

    Exploitation Prerequisites for CVE-2025-24813

    To exploit CVE-2025-24813, several server-side conditions must be in place. These prerequisites enable an attacker to craft a malicious PUT request that results in the deserialization of attacker-controlled data, potentially leading to remote code execution (RCE).

    The following conditions must be met:

    • The default servlet’s readonly attribute is set to false, permitting write access via HTTP PUT requests
    • Partial PUT functionality is enabled — i.e., Tomcat accepts the Content-Range header (enabled by default)
    • The application is configured to use Tomcat’s file-based session persistence mechanism

    Exploitation Flow

    The exploitation of CVE-2025-24813 involves a sequence of carefully crafted steps that take advantage of Tomcat’s handling of partial file uploads and session deserialization. The following outlines a typical attack chain under vulnerable conditions:

    Environment Setup: The target server must have ‘readonly’ parameter set to false for the default servlet, partial PUT support enabled, and file-based session persistence configured.

    Payload Generation: The attacker generates a malicious serialized object — typically using a tool like ysoserial — embedding a command that will execute upon deserialization.

    Payload Upload: The crafted payload is uploaded to the server via an HTTP PUT request with a Content-Range header. This simulates a partial upload and results in the creation of a session file on disk.

    Triggering Deserialization: A follow-up request is made to the application with the JSESSIONID set to the uploaded session file’s name. This causes Tomcat to deserialize the file, assuming it to be a legitimate session object.

    Code Execution: If a suitable deserialization gadget exists on the classpath, the payload is executed, leading to remote code execution under the privileges of the Tomcat process.

    Mitigation

    The recommended and most effective mitigation for CVE-2025-24813 is to upgrade Apache Tomcat to a version where the vulnerability has been addressed. This flaw is fully patched in the following Tomcat releases:

    These versions include enhancements to the handling of temporary files created via partial PUT requests, ensuring such files are not mistakenly deserialized as session objects — thereby preventing remote code execution.

    For environments where immediate upgrades are not possible, the following temporary mitigations can help reduce risk:

    • Keep the default servlet’s readonly parameter set to true, which prevents write operations via PUT requests. This is the default and recommended setting.
    • Disable support for partial PUT requests, especially if not used by the application. This can be achieved at the connector level or via upstream web server rules (e.g., Nginx or Apache HTTPD).
    • Avoid using file-based session persistence, particularly when writable paths overlap with session storage locations.
    • Review and sanitize the server classpath to remove unnecessary libraries such as commons-collections, which may introduce exploitable deserialization gadgets.

        Seqrite Endpoint Protection

    All Seqrite Customers are protected from this vulnerability by following signatures:

    • HTTP/CVE-2025-24813!VS.49414

    Authors:

    Vinay Kumar

    Vineet Sarote



    Source link

  • Upgrading a 20 year old University Project to .NET 6 with dotnet-upgrade-assistant

    Upgrading a 20 year old University Project to .NET 6 with dotnet-upgrade-assistant



    I wrote a Tiny Virtual Operating System for a 300-level OS class in C# for college back in 2001 (?) and later moved it to VB.NET in 2002. This is all pre-.NET Core, and on early .NET 1.1 or 2.0 on Windows. I moved it to GitHub 5 years ago and ported it to .NET Core 2.0 at the time. At this point it was 15 years old, so it was cool to see this project running on Windows, Linux, in Docker, and on a Raspberry Pi…a machine that didn’t exist when the project was originally written.

    NOTE: If the timeline is confusing, I had already been working in industry for years at this point but was still plugging away at my 4 year degree at night. It eventually took 11 years to complete my BS in Software Engineering.

    This evening, as the children slept, I wanted to see if I could run the .NET Upgrade Assistant on this now 20 year old app and get it running on .NET 6.

    Let’s start:

    $ upgrade-assistant upgrade .\TinyOS.sln
    -----------------------------------------------------------------------------------------------------------------
    Microsoft .NET Upgrade Assistant v0.3.256001+3c4e05c787f588e940fe73bfa78d7eedfe0190bd

    We are interested in your feedback! Please use the following link to open a survey: https://aka.ms/DotNetUASurvey
    -----------------------------------------------------------------------------------------------------------------

    [22:58:01 INF] Loaded 5 extensions
    [22:58:02 INF] Using MSBuild from C:\Program Files\dotnet\sdk\6.0.100\
    [22:58:02 INF] Using Visual Studio install from C:\Program Files\Microsoft Visual Studio\2022\Preview [v17]
    [22:58:06 INF] Initializing upgrade step Select an entrypoint
    [22:58:07 INF] Setting entrypoint to only project in solution: C:\Users\scott\TinyOS\src\TinyOSCore\TinyOSCore.csproj
    [22:58:07 INF] Recommending executable TFM net6.0 because the project builds to an executable
    [22:58:07 INF] Initializing upgrade step Select project to upgrade
    [22:58:07 INF] Recommending executable TFM net6.0 because the project builds to an executable
    [22:58:07 INF] Recommending executable TFM net6.0 because the project builds to an executable
    [22:58:07 INF] Initializing upgrade step Back up project

    See how the process is interactive at the command line, with color prompts and a series of dynamic multiple-choice questions?

    Updating .NET project with the upgrade assistant

    Interestingly, it builds on the first try, no errors.

    When I manually look at the .csproj I can see some weird version numbers, likely from some not-quite-baked version of .NET Core 2 I used many years ago. My spidey sense says this is wrong, and I’m assuming the upgrade assistant didn’t understand it.

        <!-- <PackageReference Include="ILLink.Tasks" Version="0.1.4-preview-906439" /> -->
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.0-preview2-final" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0-preview2-final" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0-preview2-final" />
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0-preview2-final" />

    I also note a commented-out reference to ILLink.Tasks which was a preview feature in Mono’s Linker to reduce the final size of apps and tree-trim them. Some of that functionality is built into .NET 6 now so I’ll use that during the build and packaging process later. The reference is not needed today.

    I’m gonna blindly upgrade them to .NET 6 and see what happens. I could do this by just changing the numbers and seeing if it restores and builds, but I can also try dotnet outdated which remains a lovely tool in the upgrader’s toolkit.

    image

    This “outdated” tool is nice as it talks to NuGet and confirms that there are newer versions of certain packages.

    In my tests – which were just batch files at this early time – I was calling my dotnet app like this:

    dotnet netcoreapp2.0/TinyOSCore.dll 512 scott13.txt  

    This will change to the modern form with just TinyOSCore.exe 512 scott13.txt with an exe and args and no ceremony.

    Publishing and trimming my TinyOS turns into just a 15 meg EXE. Nice considering that the .NET I need is in there with no separate install. I could turn this little synthetic OS into a microservice if I wanted to be totally extra.

    dotnet publish -r win-x64 --self-contained -p:PublishSingleFile=true -p:SuppressTrimAnalysisWarnings=true

    If I add

    -p:EnableCompressionInSingleFile=true

    Then it’s even smaller. No code changes. Run all my tests, looks good. My project from university from .NET 1.1 is now .NET 6.0, cross platform, self-contained in 11 megs in a single EXE. Sweet.


    Sponsor: At Rocket Mortgage® the work you do around here will be 100% impactful but won’t take all your free time, giving you the perfect work-life balance. Or as we call it, tech/life balance! Learn more.




    About Scott

    Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

    facebook
    bluesky
    subscribe
    About   Newsletter

    Hosting By
    Hosted on Linux using .NET in an Azure App Service










    Source link

  • Easter Sale! 🐣

    Easter Sale! 🐣


    At Browserling and Online Tools, we love sales.

    We just created a new automated Easter Sale.

    Now each year, on the Easter Day, we show a 50% discount offer to all users who visit our site.

    This year it runs today, next year on April 5, etc.

    Here’s how it looks.

    Buy a subscription now and see you next time!



    Source link

  • Build a Python Site Connectivity Checker App with PyQt (Step-by-Step)



    Build a Python Site Connectivity Checker App with PyQt (Step-by-Step)



    Source link