Integrating Tailwind CSS with Blazor

Creating An npm Project

Make sure that you have Node.js and npm CLI tools installed on your machine. Open the root directory of your Blazor Project.

npm init

Adding Tailwind CSS & Other Packages

npm install -D tailwindcss postcss autoprefixer postcss-cli

Configuring PostCSS

As mentioned earlier, POSTCSS will be responsible for transforming the tailwind.css to your own version. Create a new JS file in the root directory of the project and name it postcss.config.js.

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  }
}

Configuring Tailwind CSS

npx tailwindcss init

tailwind.config.js

module.exports = {
content: ["./**/*.html","./**/*.razor"],
theme: {
extend: {},
},
plugins: [],
}

In the wwwroot\css folder add a new CSS file and name it app.css. ( You could name it anything). This is what POSTCSS will use to generate your site’s CSS resource. Here we will be adding imports from the tailwind CSS library.

@tailwind base;
@tailwind components;
@tailwind utilities;

Building CSS With PostCSS CLI

Now, we need to build a script that can automate the postcss processing. Add the highlighted lines to your package.json file. What this script/command does is simple – It takes in app.css as the input and generates an app.min.css file in the same path. The newly generated file contains the complete tailwindcss content.

{
  "name": "blazorwithtailwindcss",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "buildcss": "postcss wwwroot/css/app.css -o wwwroot/css/app.min.css"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "autoprefixer": "^10.2.4",
    "postcss": "^8.2.6",
    "postcss-cli": "^8.3.1",
    "tailwindcss": "^2.0.3"
  }
}
npm run buildcss

This would have generated an app.min.css file in your root directory. You can notice that all the TailwindCSS styles are generated here.

Removing Unused CSS (See Configuring Tailwind CSS instead because purge is obsolete in version 3)

Open up your tailwind.config.js and modify it to match the following.

const colors = require('tailwindcss/colors');
module.exports = {
    purge: {
        enabled: true,
        content: [
            './**/*.html',
            './**/*.razor'
        ],
    },
    darkMode: false, 
    variants: {
        extend: {},
    },
    plugins: [],
}

PS, Make sure that you run the npm run buildcss command every time you make changes in any of the related js or CSS files. (In the next section, we will discuss post-build events that could automate running the npm command every time you build or rebuild the project.)

Configuring Post Build Events

Open your solution file and paste in the following highlighted snippet. This ensures that the dotnet build system runs the npm command once the project is built.

<Project Sdk="Microsoft.NET.Sdk.Web">
  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="npm run buildcss" />
  </Target>
  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>
</Project>

Adding The Stylesheet Reference

Finally, add the referend of the generated CSS file to your Blazor application. Since we have Server Project, you would probably want to add the following snippet to the _Host.cshml file. If you are on a WebAssembly project, Index.html is where you need to add the following.

<link href="~/css/app.min.css" rel="stylesheet" />

Optimizing for Production

npm install -D cssnano

If you’re using Tailwind CLI, you can minify your CSS by adding the --minify flag:

npx tailwindcss -o build.css --minify

If you’ve installed Tailwind as a PostCSS plugin, add cssnano to the end of your plugin list:

postcss.config.js

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
    cssnano: {preset: 'default'},
  }
}

References
https://codewithmukesh.com/blog/integrating-tailwind-css-with-blazor/
https://tailwindcss.com/docs/installation/using-postcss
https://tailwindcss.com/docs/optimizing-for-production

Response Compression in ASP.NET Core

The following code shows how to enable the Response Compression Middleware for default MIME types and compression providers (Brotli and Gzip):

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddResponseCompression();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseResponseCompression();
    }
}

Customize

public void ConfigureServices(IServiceCollection services)
{
    services.AddResponseCompression(options =>
    {
        options.Providers.Add<BrotliCompressionProvider>();
        options.Providers.Add<GzipCompressionProvider>();
        options.Providers.Add<CustomCompressionProvider>();
        options.MimeTypes = 
            ResponseCompressionDefaults.MimeTypes.Concat(
                new[] { "image/svg+xml" });
    });
}

References
https://docs.microsoft.com/en-us/aspnet/core/performance/response-compression?view=aspnetcore-6.0

Run a Wine installed application from command line

If you are using wine installed from the repositories then wine related files is stored in a folder called ~/.wine

Windows programs are stored within this folder – for example :

~/.wine/drive_c/program_files/Internet Explorer

You can start a windows program in a similar way as from a command line in windows but prefix it with wine

wine "c:\program files\internet explorer\iexplore.exe"

References
https://askubuntu.com/questions/65487/invoke-a-wine-installed-application-from-command-line

Configuring IP Networking with ifcfg Files

Configuring an Interface with Static Network Settings Using ifcfg Files
For example, to configure an interface with static network settings using ifcfg files, for an interface with the name enp1s0, create a file with the name ifcfg-enp1s0 in the /etc/sysconfig/network-scripts/ directory, that contains:

DEVICE=enp1s0
BOOTPROTO=none
ONBOOT=yes
PREFIX=24
IPADDR=10.0.1.27

Configuring an Interface with Dynamic Network Settings Using ifcfg Files

DEVICE=em1
BOOTPROTO=dhcp
ONBOOT=yes

References
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/networking_guide/sec-configuring_ip_networking_with_ifcg_files

Use the Angular project template with ASP.NET Core

Create a new app

dotnet new angular -o my-new-app
cd my-new-app

Add pages, images, styles, modules, etc.

The ClientApp directory contains a standard Angular CLI app

Run ng commands

remove package-lock.json then :

cd ClientApp
npm install

Install npm packages

cd ClientApp
npm install --save <package_name>

Run “ng serve” independently

cd ClientApp
npm start

Use npm start to launch the Angular CLI development server, not ng serve, so that the configuration in package.json is respected. To pass additional parameters to the Angular CLI server, add them to the relevant scripts line in your package.json file.

In your Startup class, replace the spa.UseAngularCliServer invocation with the following:

spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");

References
https://docs.microsoft.com/en-us/aspnet/core/client-side/spa/angular?view=aspnetcore-6.0&tabs=visual-studio

Controlling Dell Laptop Keyboard Backlight in Linux

Show the configured brightness

cat /sys/devices/platform/dell-laptop/leds/dell\:\:kbd_backlight/brightness
0

See the maximum brightness

cat /sys/devices/platform/dell-laptop/leds/dell\:\:kbd_backlight/max_brightness
4

Set the desired level of brightness

$ echo 4 | sudo tee /sys/devices/platform/dell-laptop/leds/dell\:\:kbd_backlight/brightness

References
https://askubuntu.com/questions/1076393/dell-keyboard-backlight-is-not-working
https://www.unixtutorial.org/controlling-dell-laptop-keyboard-backlight-from-command-line/

Create a Samba share on Fedora

sudo dnf install samba
sudo systemctl enable smb --now
firewall-cmd --get-active-zones
sudo firewall-cmd --permanent --zone=FedoraWorkstation --add-service=samba
sudo firewall-cmd --reload

Samba does not use the operating system users for authentication, so your user account must be duplicated in Samba. So if your account is jane on the host, the user jane must also be added to Samba. While the usernames must match, the passwords can be different.

sudo smbpasswd -a jane
mkdir /home/jane/share
sudo semanage fcontext --add --type "samba_share_t" ~/share
sudo restorecon -R ~/share
sudo nano /etc/samba/smb.conf
[share]
        comment = My Share
        path = /home/jane/share
        writeable = yes
        browseable = yes
        public = yes
        create mask = 0644
        directory mask = 0755
        write list = user
sudo systemctl restart smb

Disable SELinux if required

sudo nano /etc/selinux/config
SELINUX=disabled
sudo reboot

References
https://docs.fedoraproject.org/en-US/quick-docs/samba/
https://www.cyberciti.biz/faq/disable-selinux-on-centos-7-rhel-7-fedora-linux/