A Step-by-Step Guide to Configuring LSP in Neovim for Coding in Next.js (React), TypeScript, and TailWindCSS
Intelligent Code Completion, Beautiful Diagnostics, Auto Formatting, etc.

It’s easier to understand the different Neovim add-ons when combined with a realistic project. So, in this article, we will slowly configure LSP in Neovim to meet our requirements for coding a Next.js project with TypeScript and TailwindCSS.
Table of Content
- Create a New Next.js Project
- LSP Configuration With nvim-lspconfig
- Set Up the Language Server for Lua
- Set Up the Language Server for TypeScript
- Manage LSP Language Server in a Better Way — Mason.nvim
- Root Directory for the Lspconfig — Problem & Solution
- Set Up the Language Server for TailwindCSS
- Enable Code Formatting Using Null-ls and Prettier
- Enable Beautiful and Easy-to-Read Inline Diagnostics
- Improve the LSP UI Using Lspsaga Plugin
- Wrap Up
Create a New Next.js Project
Initiate a Next.js project:

You can also follow this article to quickly create an application using Next.js, TypeScript, and TailwindCSS.
Run the following commands from the terminal:
$ yarn create next-app --typescript my-app
$ cd my-app# Install tailwindcss$ yarn add -D tailwindcss postcss autoprefixer
$ npx tailwindcss init -pNow open a file to test whether typescript or typescriptreact is recognized in the Neovim.
nvim pages/index.tsx
Besides .tsx, sometimes we also need to create .ts.

In order to work beautifully with file types of .ts or .tsx.in our Next.js project using TypeScript, we need to set up thetsserver through LSP config as well as enable the Intelligent Code Completion. Let’s move on to the next section.
LSP Configuration With nvim-lspconfig
Nvim supports the Language Server Protocol (LSP), which means it acts as a client to LSP servers and includes a Lua framework `vim. lsp` for building enhanced LSP tools.
LSP facilitates features like go-to-definition, find-references, hover, completion, rename, format, refactor, etc., using semantic whole-project analysis.
So, what is nvim-lspconfig?
de>nvim-lspconfig is Configs for the Nvim LSP client.
Install nvim-lspconfig Plugin

Create the lspconfig.lua file with the initial setup including importing nvim-lspconfig and enable formatting when buffer is saved.

Set Up the Language Server for Lua
As we’re using Lua language throughout our Neovim configuration process, so it’s not a bad idea to first have a nice working environment with Lua.
Before the Setup of the Lua Language Server
Here is what looks like without setting up the Lua language server:
No autocompletion and no AutoFormat when saving the Lua file with :w.

Install the Language Server
brew install lua-language-serverEnable the Language Server

Then running:luafile % to apply the changes
After the Setup of the Lua Language Server
Now autocompletion is configured, as well as AutoFormat when saving the file with:w.

Set Up the Language Server for TypeScript
Install the Language Server — ‘tsserver’
See server_configurations.md from the nvim-lspconfig doc(: help lspconfig-all from Nvim) for the full list of configs for each language server. In our case, we need to set up the language server for TypeScript — typescript-language-server, which depends on the typescript. Both packages can be installed via npm:
npm install -g typescript typescript-language-serverEnable the Language Server — tsserver
Set filetypes = { “typescript”, “typescriptreact”, “typescript.tsx” }
See the nvim-lspconfig README for details.
Enable the Autocompletion
Manual, triggered completion is provided by Nvim’s builtin omnifunc. For autocompletion, a general purpose autocompletion plugin is required.
So, let’s introduce a completion plugin for neovim coded in Lua — hrsh7th/nvim-cmp.

LSP configuration for the plugin:

Set up nvim-cmp:

Demo the Auto-completion in Typescript (typescript file — ‘.ts’)

Demo the Auto-completion in React TypeScript (typescriptreact file — ‘.tsx’)

Demo the Auto-completion in React

Manage LSP Language Server in a Better Way Using Mason LspConfig
In the above, we have applied several ways to install language servers:
// TtypeScript Language Server
npm install -g typescript typescript-language-server// Lua Language Server
brew install lua-language-serverIt’s not easy to manage LSP servers in such way. So let’s introduce another mason.nvim, which is a portable package manager for Neovim that runs everywhere Neovim runs. It can easily install and manage LSP servers, DAP servers, linters, and formatters. Please refer the available lsp servers for this mason-lspconfig.nvim
Installation Using Packer
use {
"williamboman/mason.nvim",
"williamboman/mason-lspconfig.nvim",
"neovim/nvim-lspconfig",
}Important: you must set up the plugins in the following order:
mason.nvimmason-lspconfig.nvim- Set up servers via
lspconfig
Mason Config
require("mason").setup()require("mason-lspconfig").setup({
ensure_installed = { "sumneko_lua", "tsserver", "tailwindcss" }
})ensure_installed indicates a list of servers to be automatically installed if they’re not already installed. So, the above configuration will install Lua language server(sumneko_lua), TypeScript language server (tsserver), and the TailwindCSS language server (tailwindcss) if we haven’t installed yet.
Or manually install the provided servers via :LspInstall [<server>...] .
such as :LspInstall tsserver .
Notice tsserver takes care of JavaScript.

You can find detailed documention for mason-lspconfig.nvim on its GitHub page:

Check out the mason-lspconfig.nvim documentation. GIF by Amy Li.Show the UI for Mason — Visualize All the Installed Servers
Run :Mason to display the installed servers, and all the available ones you can choose to install.

As always, the:help command from your Neovim terminal comes in handy whenever you want to refresh your knowledge about the plugins we just learned.

Root Directory for the Lspconfig — Problem & Solution
It’s necessary to understand how the language servers are automatically launched (attached to the current buffer).
In order to automatically launch a language server, lspconfig searches up the directory tree from your current buffer to find a file matching the
root_dirpattern defined in each server's configuration. For pyright, this is any directory containing ".git", "setup.py", "setup.cfg", "pyproject.toml", or "requirements.txt"). Language servers require each project to have arootin order to provide completion and search across symbols that may not be defined in your current file, and to avoid having to index your entire filesystem on each startup.
Here is our lspconfig for tsserver so far:
require'lspconfig'.tsserver.setup{
filetypes = { "javascript",", "typescript", "typescriptreact", "typescript.tsx" }
}If we try to work with a JavaScript file in a project directory where there is no package.json , tsconfig.json,jsconfig.json, and .git, an error message will pop up when running:LspInfo from the current buffer.

And you will not see Intelligent code feature:

Two ways of fixing the problem:
- Any one of the missing files to your project directory
- Allow Lsp for JavaScript to run in any directory by adding the code in bold to
lspconfig:
require'lspconfig'.tsserver.setup{
filetypes = { "javascript", "typescript", "typescriptreact", "typescript.tsx" },
root_dir = function() return vim.loop.cwd() end
}Result — TypeScript Language Server Is Finally Attached to Current Buffer
Run ‘:LspInfo’ to show the attached clients to current buffer (a JavaScript file). We notice tsserver supports several file types we have defined via the lspconfig before — javascript, javascriptreact, javascript.jsx, typescript, typescriptreact, andtypescript.tsx.

Demo the Problem and Solution
Tip: Run command:LspInfo to see the attached language server client to current file buffer.

Set Up the Language Server for TailwindCSS
Install Tailwincss Language Server
As mentioned in the above section, you could install it by adding it to the ensure_installed list as below:
require("mason").setup()require("mason-lspconfig").setup({
ensure_installed = { "tailwindcss" }
})Or run command :LspInstall taillwindcss .
Make sure you have it installed by running the command: Mason.
Tailwincss Language Server Config
After we installed the tailwindcss language server in Neovim, let’s configure it via lspconfig :
local nvim_lsp = require "lspconfig"
nvim_lsp.tailwindcss.setup {}Demo the Auto-completion in TailWindCSS

Enable Code Formatting Using Null-ls and Prettier
The AutoFormat for Lua has been enabled via LSP config. However, to have the same auto-formatting feature for file types of javascript, javascriptreact, typescript, and typescriptreact, we need to use the other two neovim plugins — null-ls and prettier.
jose-elias-alvarez/null-ls.nvim: “Use Neovim as a language server to inject LSP diagnostics, code actions, formatting, hover, and completion.”
MunifTanjim/prettier.nvim: “Prettier plugin for Neovim’s built-in LSP client.”
Install the Plugins
use('neovim/nvim-lspconfig')
use('jose-elias-alvarez/null-ls.nvim')
use('MunifTanjim/prettier.nvim')We also need to install prettierd to run prettier fast in our editor:
npm install -g @fsouza/prettierd
# or use homebrew to install
brew install fsouza/prettierd/prettierdExample Configs


Enable Beautiful and Easy-to-Read Inline Diagnostics
The Problem With the Current Inline Diagnostics
Inline diagnostics are enabled automatically after our previous setup with the language server through LSP config, e.g. syntax errors or warnings will be annotated in the buffer.
However, the inline diagnostics are easily out of the screen. We have to zoom out of the screen to see the whole message, which makes it hard to read.

.tsx file but are not user-friendly. GIF by Amy LiSolution — Showing the Inline Diagnostics Automatically in the Hover Window
Add the below code to our lspconfig. lua file:

Demo the Inline Diagnostics That Automatically Shows Up in the Hover Window

Further Improvement on Inline Diagnostics by Adding Diagnostic Symbols in the Sign Column
Here is what the current diagnostic symbols look like in the Sign Column:

Let’s add four types of diagnostic symbols — Error, Warn, Hint, and Info.

The diagnostic symbols are displayed in the Sign Column on the left:

Improve the LSP UI Using Lspsaga Plugin
Lspsaga is a lightweight LSP plugin based on neovim’s built-in LSP with a highly performant UI. (source: glepnir/lspsaga.nvim)
Lspsaga provides a bunch of highly performant UIs for LSP-related features including hover doc, peek definition, rename in preview, and much more.
Install Lspsaga Plugin Using Packer

Lspsaga Config
You can find some detailed example config in its GitHub Doc.
Example config:

Demo the Highly Performant UI for LSP

Wrap Up
We have thoroughly discussed these useful plugins for Neovim built-in LSP support: nvim-lspconfig, null-ls, lspsaga, and nvim-cmp. With proper configurations, we could achieve Intelligent Code Completion, user-friendly inline diagnostics, etc. easily in Neovim.
Thanks for reading. I hope you find this article helpful for your Next.js project using a Neovim-based text editor.
Please check out my GitHub Repo for the configuration of nvim in Lua.





