Learn to build a Next.js Application.
Following our previous project — Build a Markdown Editor Using Electron, ReactJS, Vite, CodeMirror, and Remark, let us re-create this markdown editor app using Next.js, TypeScript, and TailwindCSS, and lastly host this web app. Hope you will enjoy this simple tutorial.
If you want to have access to the full code, please check out the Nextjs Markdown Editor on GitHub.
Tech Stack
- Next.js: A widely-used framework for building React applications
- TypeScript: A typed JavaScript
- CodeMirror 6: An extensible code editor for the web
- react-markdown: React component to render markdown
- remark-gfm: Add support for GitHub-flavored markdown support
- react-syntax-highlighter: Syntax highlighting component for react with
prismjs
orhighlightjs
using inline styles - Neovim: Vim-based text editor
Create a New Next.JS Application
Create a new project from this template:
GitHub – amy-juan-li/Next.js-typescript-tailwindcss-template: A template for Next.js app
This is a Next.js project bootstrapped with create-next-app. First, run the development server: Open…github.com
Or you could create on your own by following this article:
Set Up a Next.js Application Workflow Using Neovim, TypeScript, and TailwindCSS
Set up an efficient workflow for your new Next.js application.amy-juan-li.medium.com
Project Structure
Run the app in development mode
yarn dev
Output
Build Markdown Editor Using CodeMirror 6
CodeMirror 6 is a new code editor library for the web, a from-scratch implementation based on the experience of building and maintaining versions 1 to 5 for the past 13 years. It aims to be more extensible and accessible than previous versions.
by Marijn Haverbeke
Tip: Please refer to CodeMirror 6 migration guide.
Install Dependencies
Three core parts for creating a Markdown (or any other language) Editor using CodeMirror 6:
- Create the editor state
- Create the editor view
- Create the parent (HTML) element for the editor
Create React Hook to Provide Editor View Component
A React Hook allows us to reuse the code in different places, allowing us to expand our app much easier in the future.
./components/use-codemirror.tsx
Consume the React Hook by Providing State Handler and Parent Element for the Editor
./components/editor.tsx
Implement the Editor component (./components/editor.tsx) in the Home component (./index.tsx)
Use TailwindCSS to style the container.
Output
Create Markdown Preview in React Using react-markdown
There are other ways to use markdown in React out there so why use react-markdown?
The two main reasons are that they often rely on
dangerouslySetInnerHTML
or have bugs with how they handle markdown.react-markdown
uses a syntax tree to build the virtual Dom which allows for updating only the changing DOM instead of completely overwriting.react-markdown
is 100% CommonMark compliant and has plugins to support other syntax extensions (such as GFM).
Source: https://github.com/remarkjs/react-markdown#when-should-i-use-this
Install Dependencies
yarn add react-markdown
Create Preview Component and Implement ReactMarkdown Component
./components/preview.tsx
Implement Preview Component in Home Component
./index.tsx
Output
yarn dev
Yet, if we write code block using markdown, although it’s highlighted inside our markdown editor in the left panel, but not in the preview area on the right panel. Let’s fix this in the next.
Highlight Code Syntax Inside React Component
Install Dependencies
yarn add react-syntax-highlighter
Use It Inside Preview Component
The error occurs inside our text editor
Could not find a declaration file for the module react-syntax-highlighter.
as well as in the output on the browser:
Fix
yarn add @types/react-syntax-highlighter
And replace
import { prism } from ‘react-syntax-highlighter/dist/esm/styles/prism’
with
import { prism } from ‘react-syntax-highlighter/dist/cjs/styles/prism’
Then, let’s continue to the next step.
Output
Now the code syntax on the preview area is highlighted.
Enable Users to Copy and Paste the Code
One of the use cases could be that a blogging website with a built-in markdown editor for the writers renders the blog posts in React components. Then, in that case, having a feature allowing users to copy the code from the blog and use it somewhere else.
Create a Copy to Clipboard Button
./components/copy-btn.tsx
Use It
./components/preview.tsx
Output
Copy to the clipboard button on the top right corner of the code block in the markdown preview area.
Test the App When Running in Development Environment
Issue: the Some markdown elements such as the list don’t render properly.
Fix
Not sure why that happens. After some research, I figure out to override the element style with CSS code as below.
./styles/markdown.module.css
Then use the CSS inside the Preview component:
The Result
Up to now, our app seems to be working fine in the development environment. Let’s move on to the next building stage.
Prepare the App for the Deployment to the Production Environment
Although our app works on our machine, there are some Type errors we need to fix before deployment. There are three ways to find out these errors — one is simply from our LSP-configured Vim-based text editor, one is through building our app on our machine by running yarn build
, and another one is through building our app during the deployment process on the cloud hosting services. The last one is the most expensive. We should try to find out any Type errors and fix them during the app development process.
Type error #1
./components/copy-btn.tsx
Diagnostics:
typescript: Element implicitly has an ‘any’ type
The same error occurs when building the app locally.
You would see the same complaints if you try to deploy this app to the hosting service by skipping the step of building the app locally.
As I mentioned before that we better do a cheap way of finding out Type errors and starting to fix them at the stage of app development, rather than at the stage of releasing to production.
Fix
Update the CopyBtn component(./components/copy-btn.tsx):
Now the Type error disappears.
If we build our app again, we don’t see that Type error occurring in the CopyBtn component, but we do see another Type error inside the Preview component. Let’s keep fixing this different Type error.
Type error #2
./components/preview.tsx
Diagnostics:
Type '{[key, string]: CSSProperties;} | CSSProperties' is not assignable to '{[key, string]: CSSProperties;} | undefined'. Type 'CSSProperties' is not assignable to '{[key, string]: CSSProperties;}'
Investigate
Very strange, because we notice that the type for prism
is {[key, string]: CSSProperties;}
rather than '{[key, string]: CSSProperties;} | CSSProperties'
Luckily I find the explanation and solution for the issue about Typescript incompatibility with the prop style
#47:
The type mismatch error occurs because the
style
defined inCodeProps
ofreact-markdown
and thestyle
defined inSyntaxHighlighterProps
are different types.
Fix the — using style
defined in CodeProps
First import CodeProps
from react-markdown/lib/ast-to-react
Then apply CodeProps
as the type of the argument passed in the code
function:
The style
will be used in SyntaxHighlighter
.
Now what the updated Preview component looks like:
Successful Building
Note: We can ignore the error related to ESLint for now as it doesn’t impact our production results.
It’s time to deploy our Next.js app to the production environment.
Deploy the App
We are using Vercel as the hosting service for this Next.js web application.
Step 1: Add a New Project from the Vercel dashboard
Step 2: Import the Target Git Repository
Select your project git repo:
Step 3: Start Deploying
Compile error:
Do not pass children as props, nest children between the opening and closing tag
Investigation
When using JSX, the children should be nested between the opening and closing tags. When not using JSX, the children should be passed as additional arguments to
React.createElement
.
Source: Rules about eslint-plugin-react
Fix the Issue
Nesting children between the opening and closing tags of SyntaxHighlighter
Once committing our change, the rebuilding process inside Vercel deployment pipeline starts automatically.
Successful Deployment
Open our app from the browser by clicking the generated app link to check out its performance in the production environment:
Welcome to try out the app. Please leave any comments or suggestions for the future development of this app.
Conclusion
This article has covered the whole process of creating a new Next.js app, integrating new packages, fixing Type errors, testing every functionality on the development environment, building the app to prepare for deploying to the production environment, and finally deploying the app. And you might notice that this article is not intended to provide you with every step with the correct code from the beginning. We keep learning from our mistakes and growing to be better than yesterday. By the way, you cannot ignore the fun parts of trying to figure out a solution, investigating the root cause of bugs, fixing bugs, etc. especially when we are challenged to build a completely new project.
Thanks for reading!
Happy coding! ☺️
Read Further
Build a Markdown Editor Using Electron, ReactJS, Vite, CodeMirror, and Remark
Markdown Editor and Preview page with code syntax highlighting.amy-juan-li.medium.com
Build Next.js Applications
amy-juan-li.medium.com