بلاگ

  • HTTP Logging in ASP.NET: how to automatically log all incoming HTTP requests (and its downsides!)

    HTTP Logging in ASP.NET: how to automatically log all incoming HTTP requests (and its downsides!)


    Aren’t you tired of adding manual logs to your HTTP APIs to log HTTP requests and responses? By using a built-in middleware in ASP.NET, you will be able to centralize logs management and have a clear view of all the incoming HTTP requests.

    Table of Contents

    Just a second! 🫷
    If you are here, it means that you are a software developer.
    So, you know that storage, networking, and domain management have a cost .

    If you want to support this blog, please ensure that you have disabled the adblocker for this site.
    I configured Google AdSense to show as few ADS as possible – I don’t want to bother you with lots of ads, but I still need to add some to pay for the resources for my site.

    Thank you for your understanding.
    Davide

    Whenever we publish a service, it is important to add proper logging to the application. Logging helps us understand how the system works and behaves, and it’s a fundamental component that allows us to troubleshoot problems that occur during the actual usage of the application.

    In this blog, we have talked several times about logging. However, we mostly focused on the logs that were written manually.

    In this article, we will learn how to log incoming HTTP requests to help us understand how our APIs are being used from the outside.

    Scaffolding the empty project

    To showcase this type of logging, I created an ASP.NET API. It’s a very simple application with CRUD operations on an in-memory collection.

    [ApiController]
    [Route("[controller]")]
    public class BooksController : ControllerBase
    {
        private readonly List<Book> booksCatalogue = Enumerable.Range(1, 5).Select(index => new Book
        {
            Id = index,
            Title = $"Book with ID {index}"
        }).ToList();
    
        private readonly ILogger<BooksController> _logger;
    
        public BooksController(ILogger<BooksController> logger)
        {
            _logger = logger;
        }
    }
    

    These CRUD operations are exposed via HTTP APIs, following the usual verb-based convention.

    For example:

    [HttpGet("{id}")]
    public ActionResult<Book> GetBook([FromRoute] int id)
    {
        _logger.LogInformation("Looking if in my collection with {TotalBooksCount} books there is one with ID {SearchedId}"
                , booksCatalogue.Count, id);
    
        Book? book = booksCatalogue.SingleOrDefault(x => x.Id == id);
    
        return book switch
        {
            null => NotFound(),
            _ => Ok(book)
        };
    }
    

    As you can see, I have added some custom logs: before searching for the element with the specified ID, I also wrote a log message such as “Looking if in my collection with 5 books there is one with ID 2”.

    Where can I find the message? For the sake of this article, I decided to use Seq!

    Seq is a popular log sink (well, as you may know, my favourite one!), that is easy to install and to integrate with .NET. I’ve thoroughly explained how to use Seq in conjunction with ASP.NET in this article and in other ones.

    In short, the most important change in your application is to add Seq as the log sink, like this:

    builder.Services.AddLogging(lb => {
        lb.AddSeq();
    });
    

    Now, whenever I call the GET endpoint, I can see the related log messages appear in Seq:

    Custom log messages

    But sometimes it’s not enough. I want to see more details, and I want them to be applied everywhere!

    How to add HTTP Logging to an ASP.NET application

    HTTP Logging is a way of logging most of the details of the incoming HTTP operations, tracking both the requests and the responses.

    With HTTP Logging, you don’t need to manually write custom logs to access the details of incoming requests: you just need to add its related middleware, configure it as you want, and have all the required logs available for all your endpoints.

    Adding it is pretty straightforward: you first need to add the HttpLogging middleware to the list of services:

    builder.Services.AddHttpLogging(lb => { });
    

    so that you can use it once the WebApplication instance is built:

    There’s still a problem, though: all the logs generated via HttpLogging are, by default, ignored, as logs coming from their namespace (named Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware) are at Information log level, thus ignored because of the default configurations.

    You either have to update the appsetting.json file to tell the logging system to process logs from that namespace:

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning",
          "Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
        }
      }
    }
    

    or, alternatively, you need to do the same when setting up the logging system in the Program class:

    builder.Services.AddLogging(lb => {
      lb.AddSeq();
    + lb.AddFilter("Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware", LogLevel.Information);
    });
    

    We then have all our pieces in place: let’s execute the application!

    First, you can spin up the API; you should be able to see the Swagger page:

    Swagger page for our application&rsquo;s API

    From here, you can call the GET endpoint:

    Http response of the API call, as seen on Swagger

    You should now able to see all the logs in Seq:

    Logs list in Seq

    As you can see from the screenshot above, I have a log entry for the request and one for the response. Also, of course, I have the custom message I added manually in the C# method.

    Understanding HTTP Request logs

    Let’s focus on the data logged for the HTTP request.

    If we open the log related to the HTTP request, we can see all these values:

    Details of the HTTP Request

    Among these details, we can see properties such as:

    • the host name (localhost:7164)
    • the method (GET)
    • the path (/books/4)

    and much more.

    You can see all the properties as standalone items, but you can also have a grouped view of all the properties by accessing the HttpLog element:

    Details of the HTTP Log element

    Notice that for some elements we do not have access to the actual value, as the value is set to [Redacted]. This is a default configuration that prevents logging too many things (and undisclosing some values) as well as writing too much content on the log sink (the more you write, the less performant the queries become – and you also pay more!).

    Among other redacted values, you can see that even the Cookie value is not directly available – for the same reasons explained before.

    Understanding HTTP Response logs

    Of course, we can see some interesting data in the Response log:

    Details of the HTTP Response

    Here, among some other properties such as the Host Name, we can see the Status Code and the Trace Id (which, as you may notice, is the same as the one in te Request).

    As you can see, the log item does not contain the body of the response.

    Also, just as it happens with the Request, we do not have access to the list of HTTP Headers.

    How to save space, storage, and money by combining log entries

    For every HTTP operation, we end up with 2 log entries: one for the Request and one for the Response.

    However, it would be more practical to have both request and response info stored in the same log item so we can understand more easily what is happening.

    Lucky for us, this functionality is already in place. We just need to set the CombineLogs property to true when we add the HttpLogging functionality:

    builder.Services.AddHttpLogging(lb =>
    {
    +  lb.CombineLogs = true;
    }
    );
    

    Then, we are able to see the data for both the request and the related response in the same log element.

    Request and Response combined logs

    The downsides of using HTTP Logging

    Even though everything looks nice and pretty, adding HTTP Logging has some serious consequences.

    First of all, remember that you are doing some more operations for every incoming HTTP request. Just processing and storing the log messages can bring to an application performance downgrade – you are using parts of the processing resources to interpret the HTTP context, create the correct log entry, and store it.

    Depending on how your APIs are structured, you may need to strip out sensitive data: HTTP Logs, by default, log almost everything (except for the parts stored as Redacted). Since you don’t want to store as plain text the content of the requests, you may need to create custom logic to redact parts of the request and response you want to hide: you may need to implement a custom IHttpLoggingInterceptor.

    Finally, consider that logging occupies storage, and storage has a cost. The more you log, the higher the cost. You should define proper strategies to avoid excessive storage costs while keeping valuable logs.

    Further readings

    There is a lot more, as always. In this article, I focused on the most essential parts, but the road to having proper HTTP Logs is still long.

    You may want to start from the official documentation, of course!

    🔗 HTTP logging in ASP.NET Core | Microsoft Docs

    This article first appeared on Code4IT 🐧

    All the logs produced for this article were stored on Seq. You can find more info about installing and integrating Seq in ASP.NET Core in this article:

    🔗 Easy logging management with Seq and ILogger in ASP.NET | Code4IT

    Wrapping up

    HTTP Logging can be a good tool for understanding the application behaviour and detecting anomalies. However, as you can see, there are some important downsides that need to be considered.

    I hope you enjoyed this article! Let’s keep in touch on LinkedIn or Twitter! 🤜🤛

    Happy coding!

    🐧





    Source link

  • Animating in Frames: Repeating Image Transition

    Animating in Frames: Repeating Image Transition


    In our last Motion Highlights collection, I added a really amazing reel by Joana Correia, a truly skilled motion designer. Her works are so thoughtful and browsing her latest projects I stumbled upon one of her other reels wrapping up her last year. Right at the beginning, there is this:

    This small excerpt showcases a really interesting sliced repetition effect, which inspired me to try something new: animating “frames” of the same image along a path. I’m not sure if this is any good, but for some reason, I really like it. It feels like it could fit well within editorial design contexts.

    It’s just a proof of concept, but I hope it sparks some new ideas for you too! 🙂

    Configuration

    There are better ways to do this obviously, but since this is a proof of concept and we want to be able to show various effects in our demo, I decided to do it like this. So here’s how the configuration works.

    Each grid item can override the global animation settings by specifying data- attributes directly in the HTML. This allows fine-tuning of transitions on a per-item basis.

    You can customize the following options for each .grid__item:

    • clipPathDirectiondata-clip-path-direction: Direction for clip-path animation (top-bottom, bottom-top, left-right, right-left).
    • stepsdata-steps: Number of mover elements created between grid item and panel.
    • stepDurationdata-step-duration: Duration (in seconds) of each mover animation step.
    • stepIntervaldata-step-interval: Delay (in seconds) between each mover’s animation start.
    • rotationRangedata-rotation-range: Maximum random rotation (±value, degrees) applied to movers.
    • wobbleStrengthdata-wobble-strength: Maximum random positional wobble (in pixels) during motion path generation.
    • moverPauseBeforeExitdata-mover-pause-before-exit: Pause duration (in seconds) before movers exit.
    • panelRevealEasedata-panel-reveal-ease: Easing function used when revealing the panel.
    • gridItemEasedata-grid-item-ease: Easing function for animating grid item exits.
    • moverEnterEasedata-mover-enter-ease: Easing function for movers entering.
    • moverExitEasedata-mover-exit-ease: Easing function for movers exiting.
    • panelRevealDurationFactordata-panel-reveal-duration-factor: Multiplier to adjust panel reveal animation timing.
    • clickedItemDurationFactordata-clicked-item-duration-factor: Multiplier to adjust clicked grid item animation timing.
    • gridItemStaggerFactordata-grid-item-stagger-factor: Multiplier for staggered grid item animations (based on distance).
    • moverBlendModedata-mover-blend-mode: CSS mix-blend-mode to apply to movers (normal, screen, etc.).
    • pathMotiondata-path-motion: Path motion type: linear (straight) or sine (curved).
    • sineAmplitudedata-sine-amplitude: Height of sine wave if using sine path motion (in pixels).
    • sineFrequencydata-sine-frequency: Frequency of sine wave motion (higher = more waves).

    Example

    <figure class="grid__item"
            data-clip-path-direction="left-right"
            data-steps="8"
            data-rotation-range="20"
            data-path-motion="sine"
            data-sine-amplitude="60"
            data-sine-frequency="6.28">
    
      <div class="grid__item-image" style="background-image: url(assets/img32.webp)"></div>
      
      <figcaption class="grid__item-caption">
        <h3>Aura — K21</h3>
        <p>Model: Lily Cooper</p>
      </figcaption>
      
    </figure>

    This item will fly with 8 movers, stronger rotation wobble, a sine wave path, and panel opening from left to right.

    Try it out and play with it and I really hope you enjoy it!



    Source link

  • How Data Analytics Can Help You Grow Your Business

    How Data Analytics Can Help You Grow Your Business


    In today’s fast-paced and competitive business landscape, companies must leverage data analytics to better understand their customers, improve products and services, and make informed decisions that can help their business grow. With the right tools and insightful analytics, businesses can identify new opportunities, spot trends, and gain a competitive advantage. In this article, we will explore four ways data analytics can help you grow your business. Keep reading to learn more.

    Boosting Customer Engagement and Loyalty

    Customer Engagement

     

    One of the primary benefits of using data analytics in your business is the ability to better understand your customers. By collecting and analyzing customer data, you can gain insights into their preferences, needs, and behaviors. This information can then be used to create targeted marketing campaigns and personalized experiences that are tailored to their specific interests. As a result, customers will feel more engaged with your brand and are more likely to remain loyal, resulting in higher customer retention rates and increased revenue.

    Additionally, by analyzing customer feedback, businesses can determine what aspects of their products or services require improvement. This can lead to increased customer satisfaction and an even stronger brand reputation. Having access to some of the best data analytics programs can greatly enhance your understanding of your target audience.

    Furthermore, data analytics allows businesses to identify and reach out to potential customers, leading to a more effective acquisition process. By utilizing various channels, techniques, and types of data, businesses can identify potential customers who are most likely to convert, allowing them to maximize their marketing efforts and investments.

    Improving Operational Efficiency

    Data analytics can also be invaluable in improving operational efficiency within a business. By collecting and analyzing data from internal processes, businesses can pinpoint areas of inefficiency, identify bottlenecks, and determine areas that require optimization. This can lead to significant cost savings and better resource allocation, ultimately resulting in improved profitability.

    Data analytics can also be applied to supply chain management, helping businesses optimize their inventory levels, reduce waste, and manage their relationships with suppliers more effectively. This can result in a more streamlined supply chain, leading to improved customer satisfaction and increased revenue.

    Businesses that are involved in transportation or logistics, such as those utilizing Esso Diesel for fuel, can also employ data analytics for optimizing routes and vehicle performance. By analyzing data on fuel consumption, traffic patterns, and driver behavior, businesses can implement more cost-effective and efficient transportation strategies, leading to significant savings and a better environmental footprint.

    Supporting Informed Decision-Making

    Data analytics is a key tool in helping business leaders make more informed and data-driven decisions. Rather than relying on intuition or gut feelings, businesses can use data to analyze past performance, project future trends, and identify patterns to support their decision-making process. This results in better strategic planning and more effective decision-making, enabling businesses to grow and stay ahead of their competition.

    For example, data analytics can be used to identify revenue-generating products or services, allowing businesses to focus their resources on these areas. This can help to consolidate their position within the market and drive growth through targeted investments and expansion.

    Innovating and Developing New Products

    Innovating and Developing New Products

    Lastly, data analytics can support innovation by helping businesses to identify new product development opportunities. By understanding customer needs, preferences, and pain points, businesses can develop products and services that meet the demands of their existing customers, but also attract new ones.

    Furthermore, data analytics can be used to identify emerging trends or unmet needs within the market. By leveraging this information, businesses can position themselves as leaders and innovators within their industry, setting them apart from their competitors and driving growth.

    Data analytics is a powerful tool that can drive growth and improvements across various aspects of a business, from enhancing customer engagement and loyalty to optimizing internal processes, supporting informed decision-making, and fostering innovation. By harnessing the power of data analytics, businesses can set themselves on a path to sustained growth and success.



    Source link

  • How to create Custom Attributes, and why they are useful &vert; Code4IT

    How to create Custom Attributes, and why they are useful | Code4IT


    Just a second! 🫷
    If you are here, it means that you are a software developer.
    So, you know that storage, networking, and domain management have a cost .

    If you want to support this blog, please ensure that you have disabled the adblocker for this site.
    I configured Google AdSense to show as few ADS as possible – I don’t want to bother you with lots of ads, but I still need to add some to pay for the resources for my site.

    Thank you for your understanding.
    Davide

    In C#, attributes are used to describe the meaning of some elements, such as classes, methods, and interfaces.

    I’m sure you’ve already used them before. Examples are:

    • the [Required] attribute when you define the properties of a model to be validated;
    • the [Test] attribute when creating Unit Tests using NUnit;
    • the [Get] and the [FromBody] attributes used to define API endpoints.

    As you can see, all the attributes do not specify the behaviour, but rather, they express the meaning of a specific element.

    In this article, we will learn how to create custom attributes in C# and some possible interesting usages of such custom attributes.

    Create a custom attribute by inheriting from System.Attribute

    Creating a custom attribute is pretty straightforward: you just need to create a class that inherits from System.Attribute.

    [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
    public class ApplicationModuleAttribute : Attribute
    {
     public Module BelongingModule { get; }
    
     public ApplicationModuleAttribute(Module belongingModule)
       {
     BelongingModule = belongingModule;
       }
    }
    
    public enum Module
    {
     Authentication,
     Catalogue,
     Cart,
     Payment
    }
    

    Ideally, the class name should end with the suffix -Attribute: in this way, you can use the attribute using the short form [ApplicationModule] rather than using the whole class name, like [ApplicationModuleAttribute]. In fact, C# attributes can be resolved by convention.

    Depending on the expected usage, a custom attribute can have one or more constructors and can expose one or more properties. In this example, I created a constructor that accepts an enum.
    I can then use this attribute by calling [ApplicationModule(Module.Cart)].

    Define where a Custom Attribute can be applied

    Have a look at the attribute applied to the class definition:

    [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
    

    This attribute tells us that the ApplicationModule can be applied to interfaces, classes, and methods.

    System.AttributeTargets is an enum that enlists all the points you can attach to an attribute. The AttributeTargets enum is defined as:

    [Flags]
    public enum AttributeTargets
    {
     Assembly = 1,
     Module = 2,
     Class = 4,
     Struct = 8,
     Enum = 16,
     Constructor = 32,
     Method = 64,
     Property = 128,
     Field = 256,
     Event = 512,
     Interface = 1024,
     Parameter = 2048,
     Delegate = 4096,
     ReturnValue = 8192,
     GenericParameter = 16384,
     All = 32767
    }
    

    Have you noticed it? It’s actually a Flagged enum, whose values are powers of 2: this trick allows us to join two or more values using the OR operator.

    There’s another property to notice: AllowMultiple. When set to true, this property tells us that it’s possible to use apply more than one attribute of the same type to the same element, like this:

    [ApplicationModule(Module.Cart)]
    [ApplicationModule(Module.Catalogue)]
    public class ItemDetailsService { }
    

    Or, if you want, you can inline them:

    [ApplicationModule(Module.Cart), ApplicationModule(Module.Catalogue)]
    public class ItemDetailsService { }
    

    Practical usage of Custom Attributes

    You can use custom attributes to declare which components or business areas an element belongs to.

    In the previous example, I defined an enum that enlists all the business modules supported by my application:

    public enum Module
    {
        Authentication,
        Catalogue,
        Cart,
        Payment
    }
    

    This way, whenever I define an interface, I can explicitly tell which components it belongs to:

    [ApplicationModule(Module.Catalogue)]
    public interface IItemDetails
    {
        [ApplicationModule(Module.Catalogue)]
        string ShowItemDetails(string itemId);
    }
    
    [ApplicationModule(Module.Cart)]
    public interface IItemDiscounts
    {
        [ApplicationModule(Module.Cart)]
        bool CanHaveDiscounts(string itemId);
    }
    

    Not only that: I can have one single class implement both interfaces and mark it as related to both the Catalogue and the Cart areas.

    [ApplicationModule(Module.Cart)]
    [ApplicationModule(Module.Catalogue)]
    public class ItemDetailsService : IItemDetails, IItemDiscounts
    {
        [ApplicationModule(Module.Catalogue)]
        public string ShowItemDetails(string itemId) => throw new NotImplementedException();
    
        [ApplicationModule(Module.Cart)]
        public bool CanHaveDiscounts(string itemId) => throw new NotImplementedException();
    }
    

    Notice that I also explicitly enriched the two inner methods with the related attribute – even if it’s not necessary.

    Further readings

    As you noticed, the AttributeTargets is a Flagged Enum. Don’t you know what they are and how to define them? I’ve got you covered! I wrote two articles about Enums, and you can find info about Flagged Enums in both articles:

    🔗 5 things you should know about enums in C# | Code4IT

    and
    🔗 5 more things you should know about enums in C# | Code4IT

    This article first appeared on Code4IT 🐧

    There are some famous but not-so-obvious examples of attributes that you should know: DebuggerDisplay and InternalsVisibleTo.

    DebuggerDisplay can be useful for improving your debugging sessions.

    🔗 Simplify debugging with DebuggerDisplay attribute dotNET | Code4IT

    IntenalsVisibleTo can be used to give access to internal classes to external projects:;for example, you can use that attribute when writing unit tests.

    🔗 Testing internal members with InternalsVisibleTo | Code4IT

    Wrapping up

    In this article, I showed you how to create custom attributes in C# to specify which modules a class or a method belongs to. This trick can be useful if you want to speed up the analysis of your repository: if you need to retrieve all the classes that are used for the Cart module (for example, because you want to move them to an external library), you can just search for Module.Cart across the repository and have a full list of elements.

    In particular, this approach can be useful for the exposed components, such as API controllers. Knowing that two or more modules use the same Controller can help you understand if a change in the API structure is necessary.

    Another good usage of this attribute is automatic documentation: you could create a tool that automatically enlists all the interfaces, API endpoints, and classes grouped by the belonging module. The possibilities are infinite!

    I hope you enjoyed this article! Let’s keep in touch on LinkedIn, Twitter or BlueSky! 🤜🤛

    Happy coding!

    🐧





    Source link

  • Zero Trust Best Practices for Enterprises and Businesses


    Cybersecurity threats are becoming more sophisticated and frequent in today’s digital landscape. Whether a large enterprise or a growing small business, organizations must pivot from traditional perimeter-based security models to a more modern, robust approach—Zero Trust Security. At its core, Zero Trust operates on a simple yet powerful principle: never trust, always verify.

    Implementing Zero Trust is not a one-size-fits-all approach. It requires careful planning, integration of the right technologies, and ongoing management. Here are some key zero trust best practices to help both enterprises and small businesses establish a strong zero-trust foundation:

    1. Leverage IAM and AD Integrations

    A successful Zero-Trust strategy begins with Identity and Access Management (IAM). Integrating IAM solutions with Active Directory (AD) or other identity providers helps centralize user authentication and enforce policies more effectively. These integrations allow for a unified view of user roles, permissions, and access patterns, essential for controlling who gets access to what and when.

    IAM and AD integrations also enable seamless single sign-on (SSO) capabilities, improving user experience while ensuring access control policies are consistently applied across your environment.

    If your organization does not have an IdP or AD, choose a ZT solution with a User Management feature for Local Users.

    1. Ensure Zero Trust for Both On-Prem and Remote Users

    Gone are the days when security could rely solely on protecting the corporate network perimeter. With the rise of hybrid work models, extending zero-trust principles beyond traditional office setups is critical. This means ensuring that both on-premises and remote users are subject to the same authentication, authorization, and continuous monitoring processes.

    Cloud-native Zero Trust Network Access (ZTNA) solutions help enforce consistent policies across all users, regardless of location or device. This is especially important for businesses with distributed teams or those who rely on contractors and third-party vendors.

    1. Implement MFA for All Users for Enhanced Security

    Multi-factor authentication (MFA) is one of the most effective ways to protect user identities and prevent unauthorized access. By requiring at least two forms of verification, such as a password and a one-time code sent to a mobile device, MFA dramatically reduces the risk of credential theft and phishing attacks.

    MFA should be mandatory for all users, including privileged administrators and third-party collaborators. It’s a low-hanging fruit that can yield high-security dividends for organizations of all sizes.

    1. Ensure Proper Device Posture Rules

    Zero Trust doesn’t stop at verifying users—it must also verify their devices’ health and security posture. Whether it’s a company-issued laptop or a personal mobile phone, devices should meet specific security criteria before being granted access to corporate resources.

    This includes checking for up-to-date antivirus software, secure OS configurations, and encryption settings. By enforcing device posture rules, businesses can reduce the attack surface and prevent compromised endpoints from becoming a gateway to sensitive data.

    1. Adopt Role-Based Access Control

    Access should always be granted on a need-to-know basis. Implementing Role-Based Access Control (RBAC) ensures that users only have access to the data and applications required to perform their job functions, nothing more, nothing less.

    This minimizes the risk of internal threats and lateral movement within the network in case of a breach. For small businesses, RBAC also helps simplify user management and audit processes, primarily when roles are clearly defined, and policies are enforced consistently.

    1. Regularly Review and Update Policies

    Zero Trust is not a one-time setup, it’s a continuous process. As businesses evolve, so do user roles, devices, applications, and threat landscapes. That’s why it’s essential to review and update your security policies regularly.

    Conduct periodic audits to identify outdated permissions, inactive accounts, and policy misconfigurations. Use analytics and monitoring tools to assess real-time risk levels and fine-tune access controls accordingly. This iterative approach ensures that your Zero Trust architecture remains agile and responsive to emerging threats.

    Final Thoughts

    Zero Trust is more than just a buzzword, it’s a strategic shift that aligns security with modern business realities. Adopting these zero trust best practices can help you build a more resilient and secure IT environment, whether you are a large enterprise or a small business.

    By focusing on identity, device security, access control, and continuous policy refinement, organizations can reduce risk exposure and stay ahead of today’s ever-evolving cyber threats.

    Ready to take the next step in your Zero Trust journey? Start with what you have, plan for what you need, and adopt a security-first mindset across your organization.

    Embrace the Seqrite Zero Trust Access Solution and create a secure and resilient environment for your organization’s digital assets. Contact us today.

     



    Source link

  • Native Design Tokens: The Foundation of Consistent, Scalable, Open Design

    Native Design Tokens: The Foundation of Consistent, Scalable, Open Design


    As design and development teams grow and projects span across web, mobile, and internal tools, keeping everything consistent becomes tricky. Even small changes, like updating a brand color or adjusting spacing, can turn into hours of manual work across design files, codebases, and documentation. It is easy for things to drift out of sync.

    That is where design tokens come in. They are a way to define and reuse the key design decisions like colors, typography, and spacing in a format that both designers and developers can use. Instead of repeating values manually, tokens let teams manage these decisions from a central place and apply them consistently across tools and platforms.

    With Penpot’s new native support for design tokens, this workflow becomes more accessible and better integrated. Designers can now create and manage tokens directly inside their design files. Developers can rely on those same tokens being structured and available for use in code. No plugins, no copy pasting, no mismatched styles.

    In this article, we will look at what design tokens are and why they matter, walk through how Penpot implements them, and explore some real world workflows and use cases. Whether you are working solo or managing a large design system, tokens can help bring order and clarity to your design decisions—and we will show you how.

    What are Design Tokens?

    Design tokens are a way to describe the small but important visual decisions that make up your user interface. Things like primary colors, heading sizes, border radius, or spacing between elements. Instead of hardcoding those values in a design file or writing them directly into code, you give each one a name and store it as a token.

    Each token is a small piece of structured data. It has a name, a value, and a type. For example, a button background might be defined like this:

    "button-background": {
      "$value": "#005FCC",
      "$type": "color"
    }

    By putting all your decisions into a token format like this, they can be shared and reused across different projects and tools. Designers can use tokens inside the design tool, while developers can use them to generate CSS variables, theme files, or design system code. It is a way to keep everyone aligned, without needing to sync manually.

    The idea behind tokens has been around for a while, but it is often hard to implement unless you are using very specific tools or have custom workflows in place. Penpot changes that by building token support directly into the tool. You do not need extra plugins or complex naming systems. You define tokens once, and they are available everywhere in your design.

    Tokens are also flexible. You can create simple ones like colors or font sizes, or more complex groups for shadows, typography, or spacing systems. You can even reference other tokens, so if your design language evolves, you only need to change one thing.

    Why Should You Care About Design Tokens?

    Consistency and efficiency are two of the main reasons design tokens are becoming essential in design and development work. They reduce the need for manual coordination, avoid inconsistencies, and make it easier to scale design decisions. Here is how they help across different roles:

    For designers
    Tokens remove the need to repeat yourself. Instead of manually applying the same color or spacing across every frame, you define those values once and apply them as tokens. That means no more copy-pasting styles or fixing inconsistencies later. Everything stays consistent, and updates take seconds, not hours.

    For developers
    You get design values in a format that is ready to use. Tokens act as a shared language between design and code, so instead of pulling hex codes out of a mockup, you work directly with the same values defined by the design team. It reduces friction, avoids mismatches, and makes handoff smoother.

    For teams and larger systems
    Tokens are especially useful when multiple people are working on the same product or when you are managing a design system across several platforms or brands. They allow you to define decisions once and reuse them everywhere, keeping things in sync and easy to update when the brand evolves or when new platforms are added.

    Watch this quick and complete demo as Laura Kalbag, designer, developer and educator at Penpot, highlights the key benefits and main uses of Penpot’s design tokens:

    What Sets Penpot Apart?

    Penpot is not just adding support for design tokens as a separate feature. Tokens are being built directly into how Penpot works. They are part of the core design process, not an extra tool you have to manage on the side.

    You can create tokens from the canvas or from the token panel, organize them into sets, and apply them to components, styles, or entire boards. You do not need to keep track of where a value is used—Penpot does that for you. When you change a token, any component using it updates automatically.

    Take a look at this really great overview:

    Tokens in Penpot follow the same format defined by the Design Tokens Community Group, which makes them easy to sync with code and other tools. They are stored in a way that works across platforms, and they are built to be shared, copied, or extended as your project grows.

    You also get extra capabilities like:

    • Tokens that can store text, numbers, and more
    • Math operations between tokens (for example, spacing that is based on a base value)
    • Integration with Penpot’s graph engine, so you can define logic and conditions around your tokens

    That means you can do more than just store values—you can create systems that adapt based on context or scale with your product.

    Key features

    Penpot design tokens support different token types, themes, and sets.

    Design tokens in Penpot are built to be practical and flexible from the start. Whether you are setting up a simple style guide or building a full design system, these features help you stay consistent without extra effort.

    • Native to the platform
      Tokens are a core part of Penpot. You do not need plugins, workarounds, or naming tricks to make them work. You can create, edit, and apply them directly in your files.
    • Based on open standards
      Penpot follows the format defined by the Design Tokens Community Group (W3C), which means your tokens are portable and ready for integration with other tools or codebases.
    • Component aware
      You can inspect which tokens are applied to components right on the canvas, and copy them out for use in code or documentation.
    • Supports multiple types
      Tokens can represent strings, numbers, colors, font families, shadows, and more. This means you are not limited to visual values—you can also manage logic-based or structural decisions.
    • Math support
      Define tokens in relation to others. For example, you can set a spacing token to be twice your base unit, and it will update automatically when the base changes.
    • Graph engine integration
      Tokens can be part of more advanced workflows using Penpot’s visual graph engine. This opens the door for conditional styling, dynamic UI variations, or even generative design.

    Practical Use Cases

    Design tokens are flexible building blocks that can support a range of workflows. Here are a few ways they’re already proving useful:

    • Scaling across platforms
      Tokens make it easier to maintain visual consistency across web, mobile, and desktop interfaces. When spacing, colors, and typography are tokenized, they adapt across screen sizes and tech stacks without manual rework.
    • Creating themes and variants
      Whether you’re supporting light and dark modes, multiple brands, or regional styles, tokens let you swap out entire visual styles by changing a single set of values—without touching your components.
    • Simplifying handoff and implementation
      Because tokens are defined in code-friendly formats, they eliminate guesswork. Developers can use tokens as source-of-truth values, reducing design drift and unnecessary back-and-forth.
    • Prototyping and iterating quickly
      Tokens make it easier to explore design ideas without breaking things. Want to try out a new font scale or update your color palette? Change the token values and everything updates—no tedious find-and-replace needed.
    • Versioning design decisions
      You can track changes to tokens over time just like code. That means your design system becomes easier to maintain, document, and evolve—without losing control.

    Your First Tokens in Penpot

    So how do you actually work with tokens in Penpot?

    The best way to understand design tokens is to try them out. Penpot makes this surprisingly approachable, even if you’re new to the concept. Here’s how to start creating and using tokens inside the editor.

    Creating a Token

    1. Open your project and click on the Tokens tab in the left panel.
    2. You’ll see a list of token types like color, dimension, font size, etc.
    3. Click the + button next to any token type to create a new token.

    You’ll be asked to fill in:

    • Name: Something like dimension.small or color.primary
    • Value: For example, 8px for a dimension, or #005FCC for a color
    • Description (optional): A short note about what it’s for

    Hit Save, and your token will appear in the list. Tokens are grouped by type, so it stays tidy even as your set grows.

    If you try to create a token with a name that already exists, you’ll get an error. Token names must be unique.

    Editing and Duplicating Tokens

    You can right-click any token to edit or duplicate it.

    • Edit: Change the name, value, or description
    • Duplicate: Makes a copy with -copy added to the name

    Handy if you’re exploring alternatives or setting up variants.

    Referencing Other Tokens (Aliases)

    Tokens can point to other tokens. This lets you define a base token and reuse it across multiple other tokens. If the base value changes, everything that references it updates automatically.

    For example:

    1. Create a token called dimension.small with a value of 8px
    2. Create another token called spacing.small
    3. In spacing.small, set the value to {dimension.small}

    Now if you ever update dimension.small to 4px, the spacing token will reflect that change too.

    Token references are case-sensitive, so be precise.

    Using Math in Tokens

    Penpot supports simple math in token values—especially useful for dimension tokens.

    You can write things like:

    • {dimension.base} * 2
    • 16 + 4
    • {spacing.small} + {spacing.medium}

    Let’s say dimension.base is 4px, and you want a larger version that’s always double. You can set dimension.large to:

    csharpCopyEdit{dimension.base} * 2
    

    This means if you ever change the base, the large size follows along.

    Math expressions support basic operators:

    • + addition
    • - subtraction
    • * multiplication

    This adds a lightweight logic layer to your design decisions—especially handy for spacing scales, typography ramps, or breakpoints.

    What’s Next for Penpot Design Tokens?

    Penpot has an exciting roadmap for design tokens that will continue to expand their functionality:

    • GitHub Sync: A feature allowing teams to easily export and import design tokens, facilitating smooth collaboration between design and development teams.
    • Gradients: An upcoming addition to design tokens, enabling designers to work with gradients as part of their design system.
    • REST API & Automation: The future addition of a REST API will enable even deeper integrations and allow teams to automate their design workflows.

    Since Penpot is open source and works under a culture of sharing as much as they can, as early as possible, you can check out their open Taiga board to see what the team is working on in real time and what’s coming up next.

    Conclusion

    Penpot’s design tokens are more than just a tool for managing visual consistency—they are a game-changer for how design and development teams collaborate. Whether you’re a junior UI designer trying to learn scalable design practices, a senior developer looking to streamline design implementation, or an enterprise team managing a complex design system, design tokens can help bring order to complexity.

    As Penpot continues to refine and expand this feature, now is the perfect time to explore the possibilities it offers.

    Give it a try!

    Are you excited about Penpot’s new design token feature? Check it out and explore the potential of scalable design, and stay tuned for updates. We look forward to see how you will start incorporating design tokens into your workflow!



    Source link

  • like Mermaid, but better. Syntax, installation, and practical usage tips &vert; Code4IT

    like Mermaid, but better. Syntax, installation, and practical usage tips | Code4IT


    D2 is an open-source tool to design architectural layouts using a declarative syntax. It’s a textual format, which can also be stored under source control. Let’s see how it works, how you can install it, and some practical usage tips.

    Table of Contents

    Just a second! 🫷
    If you are here, it means that you are a software developer.
    So, you know that storage, networking, and domain management have a cost .

    If you want to support this blog, please ensure that you have disabled the adblocker for this site.
    I configured Google AdSense to show as few ADS as possible – I don’t want to bother you with lots of ads, but I still need to add some to pay for the resources for my site.

    Thank you for your understanding.
    Davide

    When defining the architecture of a system, I believe in the adage that says that «A picture is worth a thousand words».

    Proper diagramming helps in understanding how the architecture is structured, the dependencies between components, how the different components communicate, and their responsibilities.

    A clear architectural diagram can also be useful for planning. Once you have a general idea of the components, you can structure the planning according to the module dependencies and the priorities.

    A lack of diagramming leads to a “just words” definition: how many times have you heard people talk about modules that do not exist or do not work as they were imagining?

    The whole team can benefit from having a common language: a clear diagram brings clear thoughts, helping all the stakeholders (developers, architects, managers) understand the parts that compose a system.

    I tried several approaches: both online WYSIWYG tools like Draw.IO and DSL like Structurizr and Mermaid. For different reasons, I wasn’t happy with any of them.

    Then I stumbled upon D2: its rich set of elements makes it my new go-to tool for describing architectures. Let’s see how it works!

    A quick guide to D2 syntax

    Just like the more famous Mermaid, when using D2, you have to declare all the elements and connections as textual nodes.

    You can generate diagrams online by using the Playground section available on the official website, or you can install it locally (as you will see later).

    Elements: the basic components of every diagram

    Elements are defined as a set of names that can be enriched with a label and other metadata.

    Here’s an example of the most straightforward configurations for standalone elements.

    service
    
    user: Application User
    
    job: {
      shape: hexagon
    }
    

    For each element, you can define its internal name (service), a label (user: Application User) and a shape (shape: hexagon).

    A simple diagram with only two unrelated elements

    Other than that, I love the fact that you can define elements to be displayed as multiple instances: this can be useful when a service has multiple instances of the same type, and you want to express it clearly without the need to manually create multiple elements.

    You can do it by setting the multiple property to true.

    apiGtw: API Gateway {
      shape: cloud
    }
    be: BackEnd {
      style.multiple: true
    }
    
    apiGtw -> be
    

    Simple diagram with multiple backends

    Grouping: nesting elements hierarchically

    You may want to group elements. You can do that by using a hierarchical structure.

    In the following example, the main container represents my e-commerce application, composed of a website and a background job. The website is composed of a frontend, a backend, and a database.

    ecommerce: E-commerce {
      website: User Website {
        frontend
        backend
        database: DB {
          shape: cylinder
        }
      }
    
      job: {
        shape: hexagon
      }
    }
    

    As you can see from the diagram definition, elements can be nested in a hierarchical structure using the {} symbols. Of course, you can still define styles and labels to nested elements.

    Diagram with nested elements

    Connections: making elements communicate

    An architectural diagram is helpful only if it can express connections between elements.

    To connect two elements, you must use the --, the -> or the <- connector. You have to link their IDs, not their labels.

    ecommerce: E-commerce {
        website: User Website {
            frontend
        backend
        database: DB {
            shape: cylinder
        }
        frontend -> backend
        backend -> database: retrieve records {
            style.stroke: red
        }
      }
    
      job: {
          shape: hexagon
      }
      job -> website.database: update records
    }
    

    The previous example contains some interesting points.

    • Elements within the same container can be referenced directly using their ID: frontend -> backend.
    • You can add labels to a connection: backend -> database: retrieve records.
    • You can apply styles to a connection, like choosing the arrow colour with style.stroke: red.
    • You can create connections between elements from different containers: job -> website.database.

    Connections between elements from different containers

    When referencing items from different containers, you must always include the container ID: job -> website.database works, but job -> database doesn’t because database is not defined (so it gets created from scratch).

    SQL Tables: represent the table schema

    An interesting part of D2 diagrams is the possibility of adding the description of SQL tables.

    Obviously, the structure cannot be validated: the actual syntax depends on the database vendor.

    However, having the table schema defined in the diagram can be helpful in reasoning around the dependencies needed to complete a development.

    serv: Products Service
    
    db: Database Schema {
      direction: right
      shape: cylinder
      userTable: dbo.user {
        shape: sql_table
        Id: int {constraint: primary_key}
        FirstName: text
        LastName: text
        Birthday: datetime2
      }
    
      productsTable: dbo.products {
        shape: sql_table
        Id: int {constraint: primary_key}
        Owner: int {constraint: foreign_key}
        Description: text
      }
    
      productsTable.Owner -> userTable.Id
    }
    
    serv -> db.productsTable: Retrieve products by user id
    

    Diagram with database tables

    Notice how you can also define constraints to an element, like {constraint: foreign_key}, and specify the references from one table to another.

    How to install and run D2 locally

    D2 is a tool written in Go.

    Go is not natively present in every computer, so you have to install it. You can learn how to install it from the official page.

    Once Go is ready, you can install D2 in several ways. I use Windows 11, so my preferred installation approach is to use a .msi installer, as described here.

    If you are on macOS, you can use Homebrew to install it by running:

    Regardless of the Operating System, you can have Go directly install D2 by running the following command:

    go install oss.terrastruct.com/d2@latest
    

    It’s even possible to install it via Docker. However, this approach is quite complex, so I prefer installing D2 directly with the other methods I explained before.

    You can find more information about the several installation approaches on the GitHub page of the project.

    Use D2 via command line

    To work with D2 diagrams, you need to create a file with the .d2 extension. That file will contain the textual representation of the diagrams, following the syntax we saw before.

    Once D2 is installed and the file is present in the file system (in my case, I named the file my-diagram.d2), you can use the console to generate the diagram locally – remember, I’m using Windows11, so I need to run the exe file:

    d2.exe --watch .\my-diagram.d2
    

    Now you can open your browser, head to the localhost page displayed on the shell, and see how D2 renders the local file. Thanks to the --watch flag, you can update the file locally and see the result appear on the browser without the need to restart the application.

    When the diagram is ready, you can export it as a PNG or SVG by running

    d2.exe .\my-diagram.d2 my-wonderful-design.png
    

    Create D2 Diagrams on Visual Studio Code

    Another approach is to install the D2 extension on VS Code.

    D2 extension on Visual Studio Code

    Thanks to this extension, you can open any D2 file and, by using the command palette, see a preview of the final result. You can also format the document to have the diagram definition tidy and well-structured.

    D2 extension command palette

    How to install and use D2 Diagrams on Obsidian

    Lastly, D2 can be easily integrated with tools like Obsidian. Among the community plugins, you can find the official D2 plugin.

    D2 plugin for Obsidian

    As you can imagine, Go is required on your machine.
    And, if necessary, you are required to explicitly set the path to the bin folder of Go. In my case, I had to set it to C:\Users\BelloneDavide\go\bin\.

    D2 plugin settings for Obsidian

    To insert a D2 diagram in a note generated with Obsidian, you have to use d2 as a code fence language.

    Practical tips for using D2

    D2 is easy to use once you have a basic understanding of how to create elements and connections.

    However, some tips may be useful to ease the process of creating the diagrams. Or, at least, these tips helped me write and maintain my diagrams.

    Separate elements and connections definition

    A good approach is to declare the application’s structure first, and then list all the connections between elements unless the elements are within the same components and are not expected to change.

    ecommerce: E-commerce {
      website: User Website {
        backend
        database: DB {
          shape: cylinder
        }
    
        backend -> database: retrieve records {
          style.stroke: red
        }
      }
    
      job -> website.database: update records
    }
    

    Here, the connection between backend and database is internal to the website element, so it makes sense to declare it directly within the website element.

    However, the other connection between the job and the database is cross-element. In the long run, it may bring readability problems.

    So, you could update it like this:

    ecommerce: E-commerce {
     website: User Website {
     backend
     database: DB {
     shape: cylinder
     }
    
     backend -> database: retrieve records {
     style.stroke: red
     }
     }
    
    - job -> website.database: update records
    }
    
    + ecommerce.job -> ecommerce.website.database: update records
    

    This tip can be extremely useful when you have more than one element with the same name belonging to different parents.

    Needless to say, since the order of the connection declarations does not affect the final rendering, write them in an organized way that best fits your needs. In general, I prefer creating sections (using comments to declare the area), and grouping connections by the outbound module.

    Pick a colour theme (and customize it, if you want!)

    D2 allows you to specify a theme for the diagram. There are some predefined themes (which are a set of colour palettes), each with a name and an ID.

    To use a theme, you have to specify it in the vars element on top of the diagram:

    vars: {
      d2-config: {
        theme-id: 103
      }
    }
    

    103 is the theme named “Earth tones”, using a brown-based palette that, when applied to the diagram, renders it like this.

    Diagram using the 103 colour palette

    However, if you have a preferred colour palette, you can use your own colours by overriding the default values:

    vars: {
      d2-config: {
        # Terminal theme code
        theme-id: 103
        theme-overrides: {
          B4: "#C5E1A5"
        }
      }
    }
    

    Diagram with a colour overridden

    You can read more about themes and customizations here.

    What is that B4 key overridden in the previous example? Unfortunately, I don’t know: you must try all the variables to understand how the diagram is rendered.

    Choose the right layout engine

    You can choose one of the three supported layout engines to render the elements in a different way (more info here).

    DAGRE and ELK are open source, but quite basic. TALA is more sophisticated, but it requires a paid licence.

    Here’s an example of how the same diagram is rendered using the three different engines.

    A comparison betweel DAGRE, ELK and TALA layout engines

    You can decide which engine to use by declaring it in the layout-engine element:

    vars: {
      d2-config: {
        layout-engine: tala
      }
    }
    

    Choosing the right layout engine can be beneficial because sometimes some elements are not rendered correctly: here’s a weird rendering with the DAGRE engine.

    DAGRE engine with a weird rendering

    Use variables to simplify future changes

    D2 allows you to define variables in a single place and have the same value repeated everywhere it’s needed.

    So, for example, instead of having

    mySystem: {
      reader: Magazine Reader
      writer: Magazine Writer
    }
    

    With the word “Magazine” repeated, you can move it to a variable, so that it can change in the future:

    vars: {
      entityName: Magazine
    }
    
    mySystem: {
      reader: ${entityName} Reader
      writer: ${entityName} Writer
    }
    

    If in the future you’ll have to handle not only Magazines but also other media types, you can simply replace the value of entityName in one place and have it updated all over the diagram.

    D2 vs Mermaid: a comparison

    D2 and Mermaid are similar but have some key differences.

    They both are diagram-as-a-code tools, meaning that the definition of a diagram is expressed as a text file, thus making it available under source control.

    Mermaid is already supported by many tools, like Azure DevOps wikis, GitHub pages, and so on.
    On the contrary, D2 must be installed (along with the Go language).

    Mermaid is quite a “close” system: even if it allows you to define some basic styles, it’s not that flexible.

    On the contrary, D2 allows you to choose a theme for the whole diagram, as well as choosing different layout engines.
    Also, D2 has some functionalities that are (currently) missing on Mermaid:

    Mermaid, on the contrary, allows us to define more types of diagrams: State Diagrams, Gantt, Mindmaps, and so on. Also, as we saw, it’s already supported on many platforms.

    So, my (current) choice is: use D2 for architectural diagrams, and use Mermaid for everything else.

    I haven’t tried D2 for Sequence Diagrams yet, so I won’t express an opinion on that.

    Further readings

    D2 is available online with a playground you can use to try things out in a sandboxed environment.

    🔗 D2 Playground

    All the documentation can be found on GitHub or on the official website:

    🔗 D2 documentation

    And, if you want, you can use icons to create better diagrams: D2 exposes a set of SVG icons that can be easily integrated into your diagrams. You can find them here:

    🔗 D2 predefined icons

    This article first appeared on Code4IT 🐧

    Ok, but diagrams have to live in a context. How can you create useful and maintainable documentation for your future self?

    A good way to document your architectural choices is to define ADRs (Architecture Decision Records), as explained here:

    🔗 Tracking decision with Architecture Decision Records (ADRs) | Code4IT

    And, of course, just the architectural diagram is not enough: you should also describe the dependencies, the constraints, the deployment strategies, and so on. Arc42 is a template that can guide you to proper system documentation:

    🔗 Arc42 Documentation, for a comprehensive description of your project | Code4IT

    Wrapping up

    I hope you enjoyed this article! Let’s keep in touch on LinkedIn, Twitter or BlueSky! 🤜🤛

    Happy coding!

    🐧





    Source link

  • 3 Facts Proving That Digital Spaces Are Increasingly More Valuable


    In today’s world of technology, the importance of digital spaces is continuing to rise. With advancements in technology and the widespread use of the internet, various aspects of our lives have transformed within the digital realm. This shift in the way we think has led to the realization that digital spaces hold a ton of value.

    What Exactly is Digital Transformation?

    The acceptable definition of digital transformation is the use of new, fast, and frequently changing digital technology to be able to solve problems. It involves the application of the latest technology but companies also have to adopt other new technologies to be able to fully reap the benefits of digital transformation while keeping in line with their actual company or organization.

    Digital transformation is more about the changing practices of a company or organization and its culture over time due to the changing world of technology. Digital transformation will be different for every company and organization, depending on the way they do things and what their needs are.

    What are Digital Platforms?

    There are many different types of digital platforms. When it comes to social media platforms, there are several to choose from, including Facebook, Instagram, TikTok, Twitter, Pinterest, LinkedIn, and many more. When it comes to platforms that provide users with knowledge about different topics, there are also several to choose from, such as Yahoo! Answers and Quora.

    There are also media-sharing platforms that people use often, which include Spotify, Vimeo, and YouTube. Service-oriented platforms include sites like Airbnb and Grubhub.

    3 Facts Proving That Digital Spaces Are Increasingly More Valuable

    1. Environmental Impact is Less

    According to The World Counts, almost 50% of paper used in the workplace ends up in the trash. This staggering statistic demonstrates the enormous toll that can happen to the environment due to the excessive use of paper. Digital platforms offer new space for individuals and companies to store their access information without having to use actual paper.

    This also allows users to easily share it with other users or to store it for long periods. Also, more companies are allowing workers to work remotely, which means there are fewer cars on the road, which helps decrease carbon emissions. This happens due to virtual meetings being the latest craze so that, once again, people do not drive as much.

    2. Professional Networking and Connectivity is Increasing

    Professional networking and connecting with others has never been easier, thanks to the digital age. For example, LinkedIn is considered to be the world’s largest professional networking platform. It has over 500 million members around the world and serves as a vital hub for business and career professionals. The platform allows individuals to connect, collaborate, and explore opportunities on a scale that was unimaginable in the pre-digital era.

    By utilizing LinkedIn’s features such as profile building, job searching, and content sharing, professionals can expand their networks, showcase their expertise, and establish their personal brand. The ability to connect with like-minded individuals and industry leaders worldwide enhances career prospects, facilitates knowledge sharing, and fosters professional growth. As digital spaces like LinkedIn continue to evolve, their value in promoting professional networking and connectivity only becomes more apparent.

    3. Web Design and First Impressions Matter

    In today’s digital landscape, the importance of a visually appealing and user-friendly website cannot be overstated. Research suggests 94% of first impressions are related to a site’s web design. A well-designed website instills confidence, credibility, and trust in visitors, positively influencing their perception of a brand or organization.

    Digital spaces allow businesses and individuals to create an impactful online presence through aesthetically pleasing designs, intuitive navigation, and engaging content. A thoughtfully crafted website enhances the user experience, increases conversion rates, and drives customer engagement. As more interactions and transactions occur in digital spaces, the significance of effective web design in leaving a positive impression becomes increasingly evident. The digital age is here to stay and is proving to be more valuable than ever for organizations and companies throughout the world.



    Source link

  • Nite Riot: Minimalism Gets a Wild Side

    Nite Riot: Minimalism Gets a Wild Side


    Nite Riot isn’t just one person, it’s a powerhouse team of creatives crafting
    high-voltage promos and commercials for the biggest names in music, fashion,
    and entertainment. The kind of work that makes your jaw drop and your brain
    scream, “Damn, that’s cool”! So, when we got the chance to build their digital
    playground, we knew one thing: it had to hit just as hard as their portfolio.

    It just so happened that while working on this project, I was deep into
    Louis Paquet’s Awwwards masterclass,
    Memorable UI Design For Interactive Experiences. I challenged myself to apply a whole new approach:
    “Big Idea”. It became the driving force behind everything
    that followed.

    Less Noise, More Punch

    Nite Riot’s work hits like a lightning bolt—loud, bold, and impossible to
    ignore. The website needed to do the opposite: create space for that energy to
    shine. We stripped away the noise and leaned into a minimal black-and-white
    aesthetic, relying on a dynamic grid layout and a Difference (Blend) Mode to
    do the heavy lifting.

    We went through multiple visual directions at the start: concepts were
    sketched, tested, and tossed. Only the strongest ideas made the cut, forming a
    clean yet bold design system.

    And we didn’t wait for the homepage to make a first impression. The preloader
    set the tone from the jump—not just functional, but atmospheric. It’s the
    handshake, the deep breath before the plunge. I always think of the preloader
    as the overture of the experience.

    Big Idea

    My guiding light? Difference Mode. It didn’t just influence the design; it
    became the heartbeat of the entire site.

    • Typography treatments
    • Imagery overlays
    • Video hovers
    • Case study rollovers
    • Page transitions
    • Scroll effects
    • The logo itself
    • Dark/Light theme toggling
    • Drag scroll on the Inspired page
    • Even the 404 page

    Enter the Difference Mode

    The goal wasn’t simply to layer on visual effects; instead, it was about
    crafting a rhythm. Difference Mode brought contrast and edge to every element
    it touched. Hover states, transitions, and page reveals all flowed together,
    each following the same beat.

    But the impact wasn’t confined to the visual side. On the technical front,
    Difference Mode allowed us to create a smooth dark/light theme experience
    without the need for redundant styles. With a single toggle, the entire color
    palette reversed seamlessly, ensuring both sharpness and performance.

    Design Index Page

    We experimented with multiple layouts to strike the perfect balance. The
    client didn’t want a fullscreen visual overload, but at the same time, they
    wanted a strong presence of imagery—all within a minimalist aesthetic. The
    result? A carefully structured design that offers a rich visual experience
    without overwhelming the user, maintaining the sleek and intentional feel of
    the site.

    Case Study: A Scrolling Cinematic Experience

    Case studies aren’t just pages on this site—they’re a journey. Forget the
    standard click-and-load experience; here, case studies unfold like a film
    reel, one seamless story rolling into the next.

    • On desktop, the layout moves horizontally—because why
      should scrolling always be up and down?
    • No matter if a title is one line or three, we made sure everything adapts
      beautifully.
    • We developed a multi-case format, so you’re never locked
      into just one story.
    • And the showstopper?
      The ultra-smooth case study transition. Instead of abruptly
      ending one project and making you manually start the next, we designed a
      flow where the next case subtly appears, teasing you into it. You can either
      click and dive in or keep scrolling, and like magic, you’re onto the next
      visual masterpiece.

    Inspired? You Will Be.

    Our favorite part? The Inspired page. Imagine a canvas where images float,
    shift, and react to your every move. Drag, drop, hold—boom, Difference Mode
    kicks in. It’s a playground for the restless creative mind, where inspiration
    isn’t just consumed—it’s interacted with.

    404, But Make It Rockstar

    Most 404 pages are where fun goes to die. Not here. Ours is a full-blown
    experience—an Easter egg waiting to be discovered. The kind of 404 that makes
    you want to get lost on purpose.

    Oh, and did we mention? We applied
    double Difference Mode here. Because why not?

    I accidentally duplicated a video layer that had Difference Mode on—and turns
    out, the number shapes had the same mode. That happy accident created a unique
    setup with a ton of character. And the best part? It was insanely easy to
    build in Webflow with just the native tools.

    Animation

    Most 404 pages are where fun goes to die. Not here. Ours is a full-blown
    experience—an Easter egg waiting to be discovered. The kind of 404 that makes
    you want to get lost on purpose.

    Every animation began in Figma. Once we nailed the tone and pacing, I moved it
    all into After Effects, tweaking easings and timings to hit that sweet spot
    between smooth and snappy.

    I leaned on three key easing patterns to shape the site’s movement:

    easeSlowStartFastEnd
    cubic-bezier(0.2, 0, 0.1, 1)
    
    easeFastStartSmoothEnd
    cubic-bezier(0.75, 0, 0, 1)
    
    easeHeadings
    cubic-bezier(0.75, 0, 0, 0.35)

    When it came to development, GSAP gave us the
    control and nuance to bring those animations to life on the web.

    Development Choices

    We didn’t have an unlimited budget, but we had a clear vision. So we chose
    tools that gave us flexibility without compromising on polish.

    We pushed Webflow and
    GSAP to their limits to bring this vision to
    life—fully custom interactions, smooth performance, and pixel-perfect
    precision across all devices. Every scroll, hover, and transition was
    carefully crafted to support the story.

    Stack Under the Hood:

    • Webflow: our base platform
    • GSAP: the animation engine
    • Barba.js: for seamless page transitions
    • Embla.js: smooth slider on
      the homepage
    • Lenis: buttery custom
      scroll experience
    • Glightbox: for
      full-screen video playback

    Barba.js and Lenis worked perfectly together for our infinite scroll effect
    and horizontal case study navigation.

    Tech Breakdown: From Stack to Story

    Global

    • Page transitions powered by barba.js +
      GSAP, including smooth element reveals on entry.

    Index Page

    • Case slider built with Embla Carousel for
      the title timeline and mobile image switching.
    • GSAP handles pagination animations and desktop image
      transitions.

    Inspired Page

    • Drag-to-explore canvas with floating images and color
      inversion using vanilla JS + CSS.als on
      entry.

    Work Page

    • List item hover effects with highlight and background
      transitions using JS + CSS + GSAP.

    About Page

    • Section overlap animation with background scaling and
      masked reveals powered by CSS + GSAP.
    • On-scroll reveal of text and imagery using
      GSAP ScrollTrigger.
    • Hover animations on cities (desktop) +
      auto image rotation (mobile) via
      JS + GSAP.
    • Smooth scrolling handled by lenis.js.

    Case Studies

    • Horizontal scroll experience using
      lenis.js + GSAP.
    • Pagination updates animated with
      JS + GSAP.
    • Parallax effects on H1, media, and next-case blocks powered
      by GSAP.
    • Tab transitions via barba.js + GSAP.
    • Scroll-based transition to the next case using
      JS + barba.js + GSAP.
    • Back button transition animated with
      JS + barba.js + GSAP.
    • Full-screen video block with smooth entry/exit animations
      using JS + GSAP + glightbox.

    404 Page

    • Scrolling text ticker via CSS animations.
    • Cursor-following 404 block on desktop using
      JS + GSAP.
    • Chaotic digit displacement animated with
      GSAP.
    • Motion-reactive number shift on mobile/tablet via
      JS + Device Orientation API.

    Visual Optimization

    Performance mattered—especially on case study pages packed with video previews
    and hi-res imagery. Our toolchain:

    • Handbrake for compressing videos
    • Picflow for bulk image optimization
    • tinypng for WebP polishing

    Picflow let us handle massive batches of photos way faster than Squoosh ever
    could. Big time-saver.

    Handbrake
    Picflow
    tinypng

    CMS

    We built everything in Webflow’s CMS. Super clean and fast to update. Adding a
    new case is as easy as filling out a form.

    Not Just a Portfolio. A Vibe.

    This wasn’t about making another nice-looking site. It was about building a
    space that feels alive. Every pixel, every transition, every weird, wonderful
    interaction was designed to make people feel something. Minimalism with an
    edge. Order with a dash of chaos. Just like Nite Riot.

    Oh, and speaking of hidden gems—let’s just say we have a soft spot for Easter
    eggs. If you hover over the Nite Riot logo, you might just stumble upon a
    couple of surprises. No spoilers, though. You’ll have to find them yourself.
    😉

    Click. Explore. Get Lost.

    This is not just a website. It’s an experience. A digital world built to be
    played with. So go ahead—dive in, mess around, and see what happens!

    Visit the Nite Riot Site

    Credits

    Creation Direction:
    BL/S®

    Art / Creative Director:
    Serhii Polyvanyi

    UI / UX Design:
    Vladyslav Litovka

    PM: Julia Nikitenko

    Dev Direction: V&M, Yevhenii Prykhodko





    Source link

  • How to log to Azure Application Insights using ILogger in ASP.NET Core &vert; Code4IT

    How to log to Azure Application Insights using ILogger in ASP.NET Core | Code4IT


    Application Insights is a great tool for handling high volumes of logs. How can you configure an ASP.NET application to send logs to Azure Application Insights? What can I do to have Application Insights log my exceptions?

    Table of Contents

    Just a second! 🫷
    If you are here, it means that you are a software developer.
    So, you know that storage, networking, and domain management have a cost .

    If you want to support this blog, please ensure that you have disabled the adblocker for this site.
    I configured Google AdSense to show as few ADS as possible – I don’t want to bother you with lots of ads, but I still need to add some to pay for the resources for my site.

    Thank you for your understanding.
    Davide

    Logging is crucial for any application. However, generating logs is not enough: you must store them somewhere to access them.

    Application Insights is one of the tools that allows you to store your logs in a cloud environment. It provides a UI and a query editor that allows you to drill down into the details of your logs.

    In this article, we will learn how to integrate Azure Application Insights with an ASP.NET Core application and how Application Insights treats log properties such as Log Levels and exceptions.

    For the sake of this article, I’m working on an API project with HTTP Controllers with only one endpoint. The same approach can be used for other types of applications.

    How to retrieve the Azure Application Insights connection string

    Azure Application Insights can be accessed via any browser by using the Azure Portal.

    Once you have an instance ready, you can simply get the value of the connection string for that resource.

    You can retrieve it in two ways.

    You can get the connection string by looking at the Connection String property in the resource overview panel:

    Azure Application Insights overview panel

    The alternative is to navigate to the Configure > Properties page and locate the Connection String field.

    Azure Application Insights connection string panel

    How to add Azure Application Insights to an ASP.NET Core application

    Now that you have the connection string, you can place it in the configuration file or, in general, store it in a place that is accessible from your application.

    To configure ASP.NET Core to use Application Insights, you must first install the Microsoft.Extensions.Logging.ApplicationInsights NuGet package.

    Now you can add a new configuration to the Program class (or wherever you configure your services and the ASP.NET core pipeline):

    builder.Logging.AddApplicationInsights(
    configureTelemetryConfiguration: (config) =>
     config.ConnectionString = "InstrumentationKey=your-connection-string",
     configureApplicationInsightsLoggerOptions: (options) => { }
    );
    

    The configureApplicationInsightsLoggerOptions allows you to configure some additional properties: TrackExceptionsAsExceptionTelemetry, IncludeScopes, and FlushOnDispose. These properties are by default set to true, so you probably don’t want to change the default behaviour (except one, which we’ll modify later).

    And that’s it! You have Application Insights ready to be used.

    How log levels are stored and visualized on Application Insights

    I have this API endpoint that does nothing fancy: it just returns a random number.

    [Route("api/[controller]")]
    [ApiController]
    public class MyDummyController(ILogger<DummyController> logger) : ControllerBase
    {
     private readonly ILogger<DummyController> _logger = logger;
    
        [HttpGet]
        public async Task<IActionResult> Get()
        {
            int number = Random.Shared.Next();
            return Ok(number);
        }
    }
    

    We can use it to run experiments on how logs are treated using Application Insights.

    First, let’s add some simple log messages in the Get endpoint:

    [HttpGet]
    public async Task<IActionResult> Get()
    {
        int number = Random.Shared.Next();
    
        _logger.LogDebug("A debug log");
        _logger.LogTrace("A trace log");
        _logger.LogInformation("An information log");
        _logger.LogWarning("A warning log");
        _logger.LogError("An error log");
        _logger.LogCritical("A critical log");
    
        return Ok(number);
    }
    

    These are just plain messages. Let’s search for them in Application Insights!

    You first have to run the application – duh! – and wait for a couple of minutes for the logs to be ready on Azure. So, remember not to close the application immediately: you have to give it a few seconds to send the log messages to Application Insights.

    Then, you can open the logs panel and access the logs stored in the traces table.

    Log levels displayed on Azure Application Insights

    As you can see, the messages appear in the query result.

    There are three important things to notice:

    • in .NET, the log level is called “Log Level”, while on Application Insights it’s called “severity level”;
    • the log levels lower than Information are ignored by default (in fact, you cannot see them in the query result);
    • the Log Levels are exposed as numbers in the severityLevel column: the higher the value, the higher the log level.

    So, if you want to update the query to show only the log messages that are at least Warnings, you can do something like this:

    traces
    | where severityLevel >= 2
    | order  by timestamp desc
    | project timestamp, message, severityLevel
    

    How to log exceptions on Application Insights

    In the previous example, we logged errors like this:

    _logger.LogError("An error log");
    

    Fortunately, ILogger exposes an overload that accepts an exception in input and logs all the details.

    Let’s try it by throwing an exception (I chose AbandonedMutexException because it’s totally nonsense in this simple context, so it’s easy to spot).

    private void SomethingWithException(int number)
    {
        try
        {
            _logger.LogInformation("In the Try block");
    
            throw new AbandonedMutexException("An exception message");
        }
        catch (Exception ex)
        {
            _logger.LogInformation("In the Catch block");
            _logger.LogError(ex, "Unable to complete the operation");
        }
        finally
        {
            _logger.LogInformation("In the Finally block");
        }
    }
    

    So, when calling it, we expect to see 4 log entries, one of which contains the details of the AbandonedMutexException exception.

    The Exception message in Application Insights

    Hey, where is the exception message??

    It turns out that ILogger, when creating log entries like _logger.LogError("An error log");, generates objects of type TraceTelemetry. However, the overload that accepts as a first parameter an exception (_logger.LogError(ex, "Unable to complete the operation");) is internally handled as an ExceptionTelemetry object. Since internally, it’s a different type of Telemetry object, and it gets ignored by default.

    To enable logging exceptions, you have to update the way you add Application Insights to your application by setting the TrackExceptionsAsExceptionTelemetry property to false:

    builder.Logging.AddApplicationInsights(
    configureTelemetryConfiguration: (config) =>
     config.ConnectionString = connectionString,
     configureApplicationInsightsLoggerOptions: (options) => options.TrackExceptionsAsExceptionTelemetry = false);
    

    This way, ExceptionsTelemetry objects are treated as TraceTelemetry logs, making them available in Application Insights logs:

    The Exception log appears in Application Insights

    Then, to access the details of the exception like the message and the stack trace, you can look into the customDimensions element of the log entry:

    Details of the Exception log

    Even though this change is necessary to have exception logging work, it is barely described in the official documentation.

    Further readings

    It’s not the first time we have written about logging in this blog.

    For example, suppose you don’t want to use Application Insights but prefer an open-source, vendor-independent log sink. In that case, my suggestion is to try Seq:

    🔗 Easy logging management with Seq and ILogger in ASP.NET | Code4IT

    Logging manually is nice, but you may be interested in automatically logging all the data related to incoming HTTP requests and their responses.

    🔗 HTTP Logging in ASP.NET: how to automatically log all incoming HTTP requests (and its downsides!) | Code4IT

    This article first appeared on Code4IT 🐧

    You can read the official documentation here (even though I find it not much complete and does not show the results):

    🔗 Application Insights logging with .NET | Microsoft docs

    Wrapping up

    This article taught us how to set up Azure Application Insights in an ASP.NET application.
    We touched on the basics, discussing log levels and error handling. In future articles, we’ll delve into some other aspects of logging, such as correlating logs, understanding scopes, and more.

    I hope you enjoyed this article! Let’s keep in touch on LinkedIn, Twitter or BlueSky! 🤜🤛

    Happy coding!

    🐧





    Source link