دسته: برنامه‌نویسان

  • Developer Spotlight: Max Barvian | Codrops

    Developer Spotlight: Max Barvian | Codrops


    In past Developer Spotlights, we’ve featured devs who’ve pushed the craft of building award-winning websites. But web development is more than just translating great design—Max Barvian is one of those pioneering devs who have a deep understanding of the core mechanics of frontend development. In 2024, he shared one of the coolest CSS-powered, scroll-driven animations with us here on Codrops. We can’t shine the light enough on Max, as his work represents the next frontier in web development—one that merges deep technical knowledge with creative experimentation.

    Hi! My name is Max Barvian. I’m a UI engineer currently working at Clerk.

    Projects I’m proud of

    NumberFlow

    NumberFlow is an animated number component for React, Vue, Svelte, and vanilla TS/JS. It was heavily inspired by the number animations in the wonderful Family app:

    I built NumberFlow as a custom element with wrapper components for each framework. All the animations are powered by the Web Animations API (WAAPI). It uses the FLIP technique, registered custom CSS properties, spring-based linear() timings, new CSS math functions, and composited KeyframeEffects for better interruption handling.

    The response to NumberFlow has been surreal. 𝕏 is currently using it for their analytics dashboard, and Elon Musk even retweeted this screenshot of it:

    barvian.me

    When it came time to rebuild my portfolio last year, my goal was to make some combination of Godly and the Apple TV home screen. I’d really wanted a site like that for years, with a grid of project videos that smoothly transitioned into detail pages, but never felt confident about pulling it off. Then I found the View Transitions API. Despite its shortcomings (i.e. no interruption handling), it felt like the perfect tool for the job. View Transitions using snapshots of “old” views seemed perfect for the video grid, and meant I wouldn’t have to worry about animating a bunch of <video> elements at the same time. Ultimately, I had to use a few more tricks to get decent performance during the transitions, but I still can’t imagine having built the site with anything else. I was honored when Googlers Addy Osmani and Una Kravets shared my little site as a demo for View Transitions.

    Musée

    I stumbled upon this incredible design by Kevin Pham on Dribbble a couple years ago and immediately fell in love with it. I had wanted to experiment with CSS Scroll Snapping and 3D scenes for a while, and this seemed like the perfect candidate. I ended up using React Three Fiber, Motion for React, and Tailwind to implement it. It’s not perfect (there’s a pesky bug with mobile Safari on the last slide that I haven’t been able to fix), but I’m pretty happy with how it turned out. I was honored when Guillermo Rauch, Paul Henschel, Matt Perry, and Three.js all reposted it.

    Fluid type projects

    This work is probably the most boring on the list but I’m still happy with it. I was working on a Tailwind plugin for CSS clamp() when I encountered some longstanding accessibility issues with fluid type. I didn’t want to bring those issues into my plugin, so I spent a whole Sunday watching math videos on YouTube and talking to my physicist brother to figure out how to work around them. I eventually published the results in Smashing Magazine with some help from their great editors there, and was honored to see Adrian Roselli reference the work in his original article. Utopia, a popular fluid clamp generator, also integrated the findings into their tool.

    About me

    I got into creative development in a 7th grade journalism class, when my teacher made me the webmaster for our school newspaper. I asked my parents for Dreamweaver that year for Christmas and got my first freelance client a year after that. I’ve since moved on from Dreamweaver 🙂, but I’ve never wanted to do anything else professionally. I feel lucky that I’ve been able to make a career out of my passion.

    Current challenges

    At Clerk I’m working on building the component library we use for our dashboard. It’s been a fun challenge to try to build something that equally emphasizes UX and DX! I hope to share more on 𝕏 as it progresses. React Aria Components has been a huge inspiration here.

    Tools

    I basically live in VS Code writing React, Tailwind, and Motion code all day.

    Philosophy

    Someone I follow on 𝕏 thought NumberFlow was a good example of a quote by Charlie Munger:

    “Take a simple idea and take it seriously.”
    —Charlie Munger

    That’s stuck with me over the last few months, and I think it’s increased my enjoyment of projects I previously would’ve dismissed as too routine or boring.

    It’s an honor to be featured on a site I’ve been reading my whole career. Thanks a lot, Manoela and the Codrops team!



    Source link

  • Designer Spotlight: Stephanie Bruce | Codrops

    Designer Spotlight: Stephanie Bruce | Codrops


    Meet Stephanie Bruce, an Independent Designer and Webflow Developer based in London, UK. She has been designing for over 2 years, previously working in Finance. 

    She loves editorial layouts, photography and visually creative web designs. She works closely with agencies and clients worldwide.

    In this spotlight, Stephanie shares a selection of her favorite projects — a window into her creative process, inspirations, and evolution as a designer.

    Featured work

    Valentine

    This is my latest project where I did the art direction, photography direction, web design and development for Freewrite Valentine. The main purpose of the website is to promote their latest Freewrite Valentine, playing tribute to the original Olivetti Valentine typewriter.

    I used retro ads and posters as the main inspiration for the web design and photography direction. We decided to go with a bold red colour throughout the website to emphasise the retro red vibes. I had a two weeks deadline to design and build, as well as photography direction.

    MOD Agency Collab

    A web design project I did at MOD agency, with creative director Matt Jumper. My role was to design the website and create data visuals. It was my first time designing data visuals and I was pretty happy with how fun they turned out. Huge thanks to Mod agency for bringing me along for this project.

    SP28K

    SP28K was an exploration website I did on the Flow Party On Demand course. For this design I decided to explore brutalist design with a touch of editorial layout. This project challenged me to go for a bold approach using expressive typography and high-contrast fonts. Photoshoot of the speaker was done in Spline.

    Concepts and explorations

    Outside of client work, I love spending time creating my own concepts and web design explorations. By creating concept work, I learnt how much I love editorial, photography based websites and how I hope to attract similar work in the near future.

    Especially being a relatively new designer, these concepts have helped me get noticed on social media and led to many opportunities.

    Brief biography and career highlights

    I switched careers from Finance to Design over two years ago. I wanted to find a job that I loved, and once I discovered the world of Digital Design, I became pretty obsessed. I feel like I found my calling.

    When I worked in Finance, I spent a lot of my spare time immersed in the creative world. I would go to exhibitions, galleries, theatre plays, etc. I also studied Photography, which helped me develop an eye for detail and composition. I feel that the combination of my exposure to the arts and my photography skills has played a big role in developing a strong visual eye for design.

    Since changing careers, I’ve had some amazing opportunities to work with leading designers and agencies — from a six-month internship with Fons Mans to collaborations with designers like Dann Petty and Benten Woodring.

    I’ve been freelancing since the beginning of my design career and am very grateful that my work and network have led to multiple collaborations with international clients and agencies.

    Inspiration

    I find that most of my inspiration comes from looking at design outside of web design. I often look at magazine layouts, prints/posters, and branding assets. Exploring these areas challenges me to create things you don’t typically see on websites.

    I also draw a lot of inspiration from visiting art galleries and exhibitions around London, as well as from films and video games like Firewatch and Before Your Eyes.

    Future Goals

    Currently, I’m focused on working with agencies, as I enjoy collaborating and learning as much as possible from them.

    In the near future, I’d love to work with lifestyle and e-commerce clients, and maybe team up with someone to create a purposely small, boutique agency.

    Message to Readers

    Put in the time to practice design, and get comfortable with sharing your work online and networking — it can lead to so many opportunities and collaborations.

    I’d also say it’s totally fine to explore different skills at the beginning, but I recommend committing to mastering one or two that truly excite you. Stay open to learning and keep pushing yourself to improve, no matter how many years of experience you have.

    Feel free to reach out to me on Twitter or Instagram — whether you have a project in mind or just want to grab a coffee, in person or online!





    Source link

  • Droip: The Next Big Revolution in WordPress – Redefining No-Code Web Building

    Droip: The Next Big Revolution in WordPress – Redefining No-Code Web Building


    Let’s be real—building a WordPress site with traditional page builders can feel like assembling IKEA furniture with missing pieces.

    You install a page builder only to find out it doesn’t do half the things you need. So you pile on plugins to fill the gaps, and they end up conflicting with one another.

    Your site slows down, SEO takes a hit, and suddenly, you’re knee-deep in subscription fees, support tickets, and messy workarounds.

    It’s 2025. We deserve better. 

    That era of outdated page builders and plugin-heavy setups is over.

    Today’s web demands speed, flexibility, and full creative control—minus the bloat and the added costs. That’s where Droip comes in. A new kind of builder made for modern creators. 

    But what makes it unique? Let’s break it down.

    All-in-One Web Building Ecosystem 

    Droip is a full-fledged, no-code ecosystem that lets you build smarter.

    Whether it’s SEO, forms, popups, dynamic content, or even image editing, Droip handles it natively.

    Because it’s all native, your site stays lean, fast, and conflict-free. Oh, and your wallet? It stays happy too.

    What that means for you:

    • No surprise costs or upgrade traps.
    • Faster load times and better performance.
    • One support team, one solution.
    • Scales with your business—whether you’re a solo creator or running a full agency.

    Pricing: It’s transparent, with no hidden upsells. Check the Pricing page for the details.

    To learn how Droip works, watch a quick video overview of Droip in action. 

    Modern UI With Maximum Control

    Let’s start with the UI. 

    The moment you open the editor, everything feels intuitive.

    It’s sleek. It’s modern. It’s not that stiff, clunky layout you’ve seen in other WordPress builders. 

    Instead, the editor gives you an interface that feels familiar, like the modern major web builders you already know, but packs the kind of power only Droip can deliver.

    Everything’s exactly where you expect it to be. 

    The menu panels are clean and concise. Element settings are instantly accessible.

    The UX flows effortlessly from dragging elements to switching panels, it’s all frictionless.

    And yes, it also has both dark and light modes for your comfort.

    Overall, it provides a clean, smooth workspace designed to help you move fast and build without barriers.

    Design Freedom For Everyone

    When it comes to design, Droip hands you the keys to total design freedom.

    Whether you’re starting from scratch or using predesigned layouts, you have all the flexibility and options.

    A Growing Collection of Stunning Templates

    Start with Droip’s growing collection of stunning templates, from sleek portfolios to bold business sites. They’re professionally designed, fully customizable, and included in your subscription (no sneaky extra fees)!  

    Pre-Made Sections, Pages, and Components

    Mix and match ready-made sections, pages, and components like contact forms, testimonials, cards, and more. It’s like having a design toolkit at your fingertips. Just drag, drop, customize if needed, and you’re all set.

    Turn Figma Designs into Fully Editable Pages—In Seconds

    Imagine dragging in your Figma mockup and watching it become a live, editable page in seconds. If you have got your site designed in Figma, you can just copy and paste it into Droip—yes, literally. 

    The builder instantly converts it into a fully editable, auto-responsive page with a single click. And the best part? It automatically adapts to all breakpoints, including any custom ones you define.

    Want to Start from Scratch? Go for It!

    If you’re the “I want full control” type, Droip’s intuitive drag-and-drop canvas is all yours. Build pixel-perfect layouts, experiment, and make it yours.

    Droip was built with the atomic approach to give you granular control over every aspect of your website. With deep element editing, you can adjust every detail, from typography to layouts, to fit your exact vision.

    Native Dynamic Content. No ACF Required.

    Managing dynamic content in WordPress usually means extra plugins like ACF. Not anymore.

    Droip lets you create, manage, and style dynamic content like listings, directories, and portfolios right out of the box. 

    Connect your content, customize it visually, and even set dynamic SEO for every item’s detail page. All built-in and all visual.

    A Smarter Media Manager That Works Like a Design Tool

    Droip’s media manager is not just for organizing images.

    You can crop, resize, add filters, or create custom text paths all inside Droip’s powerful native media manager.

    Image Editing Tools

    One of the standout features of Droip’s media manager is its advanced image editing capabilities. 

    Edit your images directly within Droip, from basic cropping and resizing to applying advanced filters, without relying on third-party tools. 

    Text Path Creation

    Another innovative feature is the ability to create text paths. This allows you to design text that follows any path or shape for that extra creative edge.

    Extensive Icons & Shapes library

    Droip has an extensive library of shapes so you can do more than ever. 

    You can leverage an array of distinctive shapes, customize them to create unique visuals, and effortlessly add them to any part of your website.

    Plus, it also houses a vast collection of high-quality icons, all ready to be refined to perfection.

    Instant Global Styling Sync with Variables 

    Most builders make global styling difficult with scattered controls. But this WordPress builder has a dedicated feature called Variables that allows you to save and apply reusable styles across your entire site. 

    The system is centralized and features a real-time preview, meaning you can update your design in seconds. Say you want to tweak your brand’s primary color. Change it once, and Droip updates every button, heading, and section styled with that variable instantly.

    You can also create multiple styling modes, such as light and dark themes, and switch between them with a single click—perfect for seasonal refreshers or theme updates.

    Reusable Components with Symbols

    Droip also comes with a feature called Symbols, which lets you turn any element along with all of its nested children into a reusable component.

    That means if you build something once like a button, a pricing card, or even an entire section, you can reuse it throughout the site

    You can even set your global header and footer as Symbols, which makes keeping everything consistent across your site way easier.

    Immersive Interactions and Animations

    If you have been settling for basic motion, a few hover effects, maybe a fade-in or two, it’s time to achieve more. 

    Droip has rich interactions and animation capabilities. You can create immersive, responsive experiences that feel polished and purposeful—not just flashy. From hover effects to scroll-based reveals, you’re free to build any web interactions.

    And when you’re ready to go beyond simple effects, it has an interaction timeline that gives you a visual playground to choreograph complex, multi-step animations with ease. Paired with the custom timing editor, you can shape how your animation flows down to the finest detail.

    Text Animations

    It also approaches Text Animations with the same depth and flexibility. You can choose your trigger, select transition styles, and animate at the character, word, or element level. 

    You can fine-tune every movement, like speed, direction, intensity, delay, and duration, until it’s just right.

    Multiple Backgrounds & Effects

    Droip offers robust options for layering multiple backgrounds and shadow effects. 

    You can layer multiple backgrounds from solid colors to gradients (linear, radial, conic) or images for dynamic, vibrant designs. 

    Combine that with shadow effects for added depth and dimension, and you can create a truly unique visual experience without being limited by pre-set templates.

    Droip Apps for Seamless Integrations

    Droip has a convenient approach when it comes to connecting integrations. 

    You can directly install and connect third-party integrations without leaving the builder and automate workflows by integrating essential tools like analytics, email marketing, and customer support.

    Native Pop-up Builder

    The built-in popup builder also checks all the right boxes, giving you full control over both design and behavior. 

    Design your pop-ups visually, set visibility conditions, and choose custom triggers, whether it’s a click, scroll, or exit intent. You can position them exactly where you want on the screen.

    But that’s not all. You can also customize the appearance with smooth transitions, whether it’s a subtle notification or a full-screen takeover.

    Form Builder with Built-in Form Data Manager

    Creating forms elsewhere can be a hassle, requiring multiple tools to manage both form design and data collection.

    But with this no-code website builder, you can practically design any web form and then access and manage form data with the built-in Form Data Manager. 

    Whether you’re collecting leads, registrations, or feedback, Droip combines form creation and data management in one place.

    Unlimited Breakpoints for Responsiveness 

    Many builders limit your ability to adjust responsiveness across devices, leaving you with only a few pre-set breakpoints.

    Here, however, you can define unlimited breakpoints and fine-tune responsiveness for every screen size, ensuring your design adapts perfectly.

    AI-Powered Website Creation

    Droip also has AI features to assist and accelerate your entire workflow. 

    You can instantly generate page structures and layouts, all with a single prompt. It intelligently understands your content and automatically creates optimal layouts, which are neatly structured and easily accessible in the Layers Panel. 

    And if you need help crafting the perfect copy, it can do that too. It even generates meta titles and descriptions, saving you time while ensuring your site stays optimized for search engines.

    Role Manager

    Another essential feature for managing your website is the Role Manager.

    With the Role Manager in Droip, you can control what users can access and edit within the Droip Editor.

    Whether you’re working solo or collaborating with a team, Droip lets you customize who has access to what in a pretty straightforward way.

    Accessibility Built-in

    Accessibility is often left to external plugins in other platforms. But Droip bakes it right into the experience.

    From increasing text size and reducing motion to enabling larger cursors and magnifying content, the builder offers a wide range of built-in tools to offer an inclusive website creation experience. It also includes support for various visual impairments, like color blindness. 

    It also has a built-in color contrast checker to ensure that your text is readable and your color choices meet accessibility standards. 

    Dynamic and AI-Powered SEO

    For SEO, you get the basics: meta titles, descriptions, and Open Graph tags, all easily editable for every page. Even better, you can generate SEO metadata automatically with AI, saving you time.

    But when working with dynamic content, Droip takes SEO a step further. 

    You can set dynamic SEO, so you don’t have to write SEO data for every single dynamic detail page. Whether it’s a product catalog or course listings, dynamic SEO optimizes the individual detail pages automatically, saving you from manual updates.

    No Performance Compromise

    With so many powerful features built into the platform, you might wonder if performance takes a hit. 

    But no.

    While other traditional WordPress page builders produce bloated code or excessive scripts, Droip delivers clean, minimal markup so even the most complex site loads fast and smooth.

    Automatic Page Audit for Quality Control

    Most platforms leave quality control up to you.

    But Droip has a Page Audit feature that automatically catches issues before they become problems. 

    Whether it’s missing alt text, links, or class names, you’ll get a clear report so you can publish with confidence.

    Final Verdict

    With its packed feature set, slick UI, and native performance, it’s clear that Droip is a complete powerhouse solution at an unbeatable price.

    It’s sleek, it’s powerful, and it’s exactly what WordPress has been waiting for. 

    Where other builders hit their limits, Droip puts you in the driver’s seat, giving you the freedom and tools to craft extraordinary websites.

    So, if you’re still patching plugins together and wasting your money, it’s time to try Droip to feel the difference.



    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

  • 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

  • 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

  • A Nightscout Segment for OhMyPosh shows my realtime Blood Sugar readings in my Git Prompt

    A Nightscout Segment for OhMyPosh shows my realtime Blood Sugar readings in my Git Prompt



    I’ve talked about how I love a nice pretty prompt in my Windows Terminal and made videos showing in detail how to do it. I’ve also worked with my buddy TooTallNate to put my real-time blood sugar into a bash or PowerShell prompt, but this was back in 2017.

    Now that I’m “Team OhMyPosh” I have been meaning to write a Nightscout “segment” for my prompt. Nightscout is an open source self-hosted (there are commercial hosts also like T1Pal) website and API for remote display of real-time and near-real-time glucose readings for Diabetics like myself.

    Since my body has an active REST API where I can just do an HTTP GET (via curl or whatever) and see my blood sugar, it clearly belongs in a place of honor, just like my current Git Branch!

    My blood sugar in my Prompt!

    Oh My Posh supports configurable “segments” and now there’s a beta (still needs mmol and stale readings support) Nightscout segment that you can setup in just a few minutes!

    This prompt works in ANY shell on ANY os! You can do this in zsh, PowerShell, Bash, whatever makes you happy.

    Here is a YouTube of Jan from OhMyPosh and I coding the segment LIVE in Go.

    https://www.youtube.com/watch?v=_meKUIm9NwA

    If you have an existing OhMyPosh json config, you can just add another segment like this. Make sure your Nightscout URL includes a secure Token or is public (up to you). Note also that I setup “if/then” rules in my background_templates. These are optional and up to you to change to your taste. I set my background colors to red, yellow, green depending on sugar numbers. I also have a foreground template that is not really used, as you can see it always evaluates to black #000, but it shows you how you could set it to white text on a darker background if you wanted.

    {
    "type": "nightscout",
    "style": "diamond",
    "foreground": "#ffffff",
    "background": "#ff0000",
    "background_templates": [
    "{{ if gt .Sgv 150 }}#FFFF00{{ end }}",
    "{{ if lt .Sgv 60 }}#FF0000{{ end }}",
    "#00FF00"
    ],
    "foreground_templates": [
    "{{ if gt .Sgv 150 }}#000000{{ end }}",
    "{{ if lt .Sgv 60 }}#000000{{ end }}",
    "#000000"
    ],

    "leading_diamond": "",
    "trailing_diamond": "\uE0B0",
    "properties": {
    "url": "https://YOURNIGHTSCOUTAPP.herokuapp.com/api/v1/entries.json?count=1&token=APITOKENFROMYOURADMIN",
    "http_timeout": 1500,
    "template": " {{.Sgv}}{{.TrendIcon}}"
    }
    },

    By default we will only go out and hit your Nightscout instance every 5 min, only when the prompt is repainted, and we’ll only wait 1500ms before giving up. You can set that “http_timeout” (how long before we give up) if you feel this slows you down. It’ll be cached for 5 min so it’s unlikely  to b something you’ll notice. The benefit of this new OhMyPosh segment over the previous solution is that it requires no additional services/chron jobs and can be setup extremely quickly. Note also that you can customize your template with NerdFonts. I’ve included a tiny syringe!

    What a lovely prompt with Blood Sugar!

    Next I’ll hope to improve the segment with mmol support as well as strikeout style for “stale” (over 15 min old) results. You’re also welcome to help out by watching our YouTube and submitting a PR!


    Sponsor: Make login Auth0’s problem. Not yours. Provide the convenient login features your customers want, like social login, multi-factor authentication, single sign-on, passwordless, and more. Get started for free.




    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

  • JavaScript and TypeScript Projects with React, Angular, or Vue in Visual Studio 2022 with or without .NET

    JavaScript and TypeScript Projects with React, Angular, or Vue in Visual Studio 2022 with or without .NET



    I was reading Gabby’s blog post about the new TypeScript/JavaScript project experience in Visual Studio 2022. You should read the docs on JavaScript and TypeScript in Visual Studio 2022.

    If you’re used to ASP.NET apps when you think about apps that are JavaScript heavy, “front end apps” or TypeScript focused, it can be confusing as to “where does .NET fit in?”

    You need to consider the responsibilities of your various projects or subsystems and the multiple totally valid ways you can build a web site or web app. Let’s consider just a few:

    1. An ASP.NET Web app that renders HTML on the server but uses TS/JS
      • This may have a Web API, Razor Pages, with or without the MVC pattern.
      • You maybe have just added JavaScript via <script> tags
      • Maybe you added a script minimizer/minifier task
      • Can be confusing because it can feel like your app needs to ‘build both the client and the server’ from one project
    2. A mostly JavaScript/TypeScript frontend app where the HTML could be served from any web server (node, kestrel, static web apps, nginx, etc)
      • This app may use Vue or React or Angular but it’s not an “ASP.NET app”
      • It calls backend Web APIs that may be served by ASP.NET, Azure Functions, 3rd party REST APIs, or all of the above
      • This scenario has sometimes been confusing for ASP.NET developers who may get confused about responsibility. Who builds what, where do things end up, how do I build and deploy this?

    VS2022 brings JavaScript and TypeScript support into VS with a full JavaScript Language Service based on TS. It provides a TypeScript NuGet Package so you can build your whole app with MSBuild and VS will do the right thing.

    NEW: Starting in Visual Studio 2022, there is a new JavaScript/TypeScript project type (.esproj) that allows you to create standalone Angular, React, and Vue projects in Visual Studio.

    The .esproj concept is great for folks familiar with Visual Studio as we know that a Solution contains one or more Projects. Visual Studio manages files for a single application in a Project. The project includes source code, resources, and configuration files. In this case we can have a .csproj for a backend Web API and an .esproj that uses a client side template like Angular, React, or Vue.

    Thing is, historically when Visual Studio supported Angular, React, or Vue, it’s templates were out of date and not updated enough. VS2022 uses the native CLIs for these front ends, solving that problem with Angular CLI, Create React App, and Vue CLI.

    If I am in VS and go “File New Project” there are Standalone templates that solve Example 2 above. I’ll pick JavaScript React.

    Standalone JavaScript Templates in VS2022

    Then I’ll click “Add integration for Empty ASP.NET Web API. This will give me a frontend with javascript ready to call a ASP.NET Web API backend. I’ll follow along here.

    Standalone JavaScript React Template

    It then uses the React CLI to make the front end, which again, is cool as it’s whatever version I want it to be.

    React Create CLI

    Then I’ll add my ASP.NET Web API backend to the same solution, so now I have an esproj and a csproj like this

    frontend and backend

    Now I have a nice clean two project system – in this case more JavaScript focused than .NET focused. This one uses npm to startup the project using their web development server and proxyMiddleware to proxy localhost:3000 calls over to the ASP.NET Web API project.

    Here is a React app served by npm calling over to the Weather service served from Kestrel on ASP.NET.

    npm app running in VS 2022 against an ASP.NET Web API

    This is inverted than most ASP.NET Folks are used to, and that’s OK. This shows me that Visual Studio 2022 can support either development style, use the CLI that is installed for whatever Frontend Framework, and allow me to choose what web server and web browser (via Launch.json) I want.

    If you want to flip it, and put ASP.NET Core as the primary and then bring in some TypeScript/JavaScript, follow this tutorial because that’s also possible!


    Sponsor: Make login Auth0’s problem. Not yours. Provide the convenient login features your customers want, like social login, multi-factor authentication, single sign-on, passwordless, and more. Get started for free.




    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

  • Using Home Assistant to integrate a Unifi Protect G4 Doorbell and Amazon Alexa to announce visitors

    Using Home Assistant to integrate a Unifi Protect G4 Doorbell and Amazon Alexa to announce visitors



    I am not a Home Assistant expert, but it’s clearly a massive and powerful ecosystem. I’ve interviewed the creator of Home Assistant on my podcast and I encourage you to check out that chat.

    Home Assistant can quickly become a hobby that overwhelms you. Every object (entity) in your house that is even remotely connected can become programmable. Everything. Even people! You can declare that any name:value pair that (for example) your phone can expose can be consumable by Home Assistant. Questions like “is Scott home” or “what’s Scott’s phone battery” can be associated with Scott the Entity in the Home Assistant Dashboard.

    I was amazed at the devices/objects that Home Assistant discovered that it could automate. Lights, remotes, Spotify, and more. You’ll find that any internally connected device you have likely has an Integration available.

    Temperature, Light Status, sure, that’s easy Home Automation. But integrations and 3rd party code can give you details like “Is the Living Room dark” or “is there motion in the driveway.” From these building blocks, you can then build your own IFTTT (If This Then That) automations, combining not just two systems, but any and all disparate systems.

    What’s the best part? This all runs LOCALLY. Not in a cloud or the cloud or anyone’s cloud. I’ve got my stuff running on a Raspberry Pi 4. Even better I put a Power Over Ethernet (PoE) hat on my Rpi so I have just one network wire into my hub that powers the Pi.

    I believe setting up Home Assistant on a Pi is the best and easiest way to get started. That said, you can also run in a Docker Container, on a Synology or other NAS, or just on Windows or Mac in the background. It’s up to you. Optionally, you can pay Nabu Casa $5 for remote (outside your house) network access via transparent forwarding. But to be clear, it all still runs inside your house and not in the cloud.

    Basic Home Assistant Setup

    OK, to the main point. I used to have an Amazon Ring Doorbell that would integrate with Amazon Alexa and when you pressed the doorbell it would say “Someone is at the front door” on our all Alexas. It was a lovely little integration that worked nicely in our lives.

    Front Door UniFi G4 Doorbell

    However, I swapped out the Ring for a Unifi Protect G4 Doorbell for a number of reasons. I don’t want to pump video to outside services, so this doorbell integrates nicely with my existing Unifi installation and records video to a local hard drive. However, I lose any Alexa integration and this nice little “someone is at the door” announcement. So this seems like a perfect job for Home Assistant.

    Here’s the general todo list:

    • Install Home Assistant
    • Install Home Assistant Community Store
      • This enables 3rd party “untrusted” integrations directly from GitHub. You’ll need a GitHub account and it’ll clone custom integrations directly into your local HA.
      • I also recommend the Terminal & SSH (9.2.2), File editor (5.3.3) add ons so you can see what’s happening.
    • Get the UniFi Protect 3rd party integration for Home Assistant
      • NOTE: Unifi Protect support is being promoted in Home Assistant v2022.2 so you won’t need this step soon as it’ll be included.
      • “The UniFi Protect Integration adds support for retrieving Camera feeds and Sensor data from a UniFi Protect installation on either an Ubiquiti CloudKey+, Ubiquiti UniFi Dream Machine Pro or UniFi Protect Network Video Recorder.”
      • Authenticate and configure this integration.
    • Get the Alexa Media Player integration
      • This makes all your Alexas show up in Home Assistant as “media players” and also allows you to tts (text to speech) to them.
      • Authenticate and configure this integration.

    I recommend going into your Alexa app and making a Multi-room Speaker Group called “everywhere.” Not only because it’s nice to be able to say “play the music everywhere” but you can also target that “Everywhere” group in Home Assistant.

    Go into your Home Assistant UI at http://homeassistant.local:8123/ and into Developer Tools. Under Services, try pasting in this YAML and clicking “call service.”

    service: notify.alexa_media_everywhere
    data:
      message: Someone is at the front door, this is a test
      data:
        type: announce
        method: speak

    If that works, you know you can automate Alexa and make it say things. Now, go to Configuration, Automation, and Add a new Automation. Here’s mine. I used the UI to create it. Note that your Entity names may be different if you give your front doorbell camera a different name.

    Binary_sensor.front_door_doorbell

    Notice the format of Data, it’s name value pairs within a single field’s value.

    Alexa Action

    …but it also exists in a file called Automations.yaml. Note that the “to: ‘on’” trigger is required or you’ll get double announcements, one for each state change in the doorbell.

    - id: '1640995128073'
      alias: G4 Doorbell Announcement with Alexa
      description: G4 Doorbell Announcement with Alexa
      trigger:
      - platform: state
        entity_id: binary_sensor.front_door_doorbell
        to: 'on'
      condition: []
      action:
      - service: notify.alexa_media_everywhere
        data:
          data:
            type: announce
            method: speak
          message: Someone is at the front door
      mode: single

    It works! There’s a ton of cool stuff I can automate now!


    Sponsor: Make login Auth0’s problem. Not yours. Provide the convenient login features your customers want, like social login, multi-factor authentication, single sign-on, passwordless, and more. Get started for free.




    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

  • I got tired – Scott Hanselman’s Blog

    I got tired – Scott Hanselman’s Blog



    I got tired - photo by Elisa VenturI have been blogging here for the last 20 years. Every Tuesday and Thursday, quite consistently, for two decades. But last year, without planning it, I got tired and stopped. Not sure why. It didn’t correspond with any life events. Nothing interesting or notable happened. I just stopped.

    I did find joy on TikTok and amassed a small group of like-minded followers there. I enjoy my YouTube as well, and my weekly podcast is going strong with nearly 900 (!) episodes of interviews with cool people. I’ve also recently started posting on Mastodon (a fediverse (federated universe)) Twitter alternative that uses the ActivityPub web standard. I see that Mark Downie has been looking at ActivityPub as well for DasBlog (the blog engine that powers this blog) so I need to spend sometime with Mark soon.

    Being consistent is a hard thing, and I think I did a good job. I gave many talks over many years about Personal Productivity but I always mentioned doing what “feeds your spirit.” For a minute here the blog took a backseat, and that’s OK. I filled that (spare) time with family time, personal projects, writing more code, 3d printing, games, taekwondo, and a ton of other things.

    Going forward I will continue to write and share across a number of platforms, but it will continue to start here as it’s super important to Own Your Words. Keep taking snapshots and backups of your keystrokes as you never know when your chosen platform might change or go away entirely.

    I’m still here. I hope you are too! I will see you soon.

    Related Links:




    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