nextjs
mdx
framer-motion
tailwind

first article from MDX editor

8
5 min read
J
Jagadhiswaran Devaraj
Full-Stack Developer

My first article from MDX editor

Building a custom MDX editor has been a game-changer for my content workflow. In this article, I'll share how I built a powerful, user-friendly MDX editor that allows me to write and publish articles with just one click – directly to my portfolio site.

Why I built a custom MDX editor

As a developer who frequently publishes content, I found my existing workflow inefficient:

  1. Opening VS Code
  2. Creating new MDX files
  3. Writing frontmatter manually
  4. Previewing changes required local development server
  5. Publishing required git commits, pushes, and waiting for deployments

I wanted a streamlined solution that would let me focus on writing while handling the technical aspects automatically. That's when I decided to build my own MDX editor.

The tech stack

I built the editor using these modern technologies:

  • Next.js 15 - For the application framework
  • TailwindCSS - For styling the UI
  • CodeMirror - For the text editor component
  • NextAuth - For GitHub authentication
  • Zustand - For state management
  • React Hook Form - For form validation
  • GitHub API - For publishing directly to repositories
  • Sonner - For toast notifications

Key features

1. Rich MDX editing experience

The editor provides a full-featured writing experience with:

  • Syntax highlighting for markdown and code blocks
  • Toolbar with common formatting options
  • Split-screen preview mode
  • Support for all MDX features (components, imports, etc.)
// Example of the CodeMirror implementation
<CodeMirror
  value={currentArticle.content}
  onChange={handleContentChange}
  extensions={[
    markdown({
      codeLanguages: languages
    }),
    EditorView.lineWrapping
  ]}
  theme={isDarkTheme ? 'dark' : 'light'}
  className="h-full border-0"
/>

2. Real-time preview

One of the most valuable features is the real-time preview that renders MDX content as you type. This gives immediate visual feedback on how your article will look once published.

MDX Editor Preview

I implemented this using a custom rendering pipeline that:

  1. Strips frontmatter
  2. Processes markdown with a lightweight renderer
  3. Shows the rendered content alongside or in place of the editor

3. One-click publishing to GitHub

The most powerful feature is the ability to publish directly to my GitHub repository with a single click. Here's how it works:

  1. Authenticate with GitHub using OAuth
  2. Select the target repository and branch
  3. Set the file path and commit message
  4. Click "Publish"

The editor then:

  • Creates or updates the MDX file in the selected repository
  • Triggers a GitHub Action to rebuild my portfolio site
  • Displays a success message with a link to the published article

Implementation challenges

Authentication issues

Getting NextAuth to work correctly with GitHub's OAuth was tricky. I encountered errors with callbacks and tokens:

TypeError: callback is not a function. (In 'callback(...args)', 'callback' is an instance of Object)

The solution was to simplify my NextAuth configuration and use the correct parameter structure for callbacks:

// Fixed NextAuth configuration
const authConfig: NextAuthConfig = {
  providers: [
    GithubProvider({
      clientId: process.env.GITHUB_CLIENT_ID!,
      clientSecret: process.env.GITHUB_CLIENT_SECRET!,
      authorization: {
        params: {
          scope: 'read:user user:email repo workflow'
        }
      }
    })
  ],
  callbacks: {
    async jwt({ token, account }) {
      if (account) {
        token.accessToken = account.access_token;
      }
      return token;
    },
    async session({ session, token }) {
      if (session) {
        session.accessToken = token.accessToken as string;
      }
      return session;
    }
  },
  secret: process.env.NEXTAUTH_SECRET
};

MDX preview rendering

Creating a live preview that accurately reflects how the MDX will render on my site was challenging. Initially, I tried using fumadocs for rendering, but encountered Node.js dependency issues in the browser context.

I solved this by creating a lightweight client-side markdown processor that works without server-side dependencies:

const processMarkdown = async (markdown: string): Promise<string> => {
  // Basic markdown processing
  let html = markdown
    // Headers
    .replace(/^### (.*$)/gm, '<h3>$1</h3>')
    .replace(/^## (.*$)/gm, '<h2>$1</h2>')
    .replace(/^# (.*$)/gm, '<h1>$1</h1>')
    
    // Bold and Italic
    .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
    .replace(/\*(.*?)\*/g, '<em>$1</em>')
    
    // Links and more processing...
    
  return html;
};

GitHub publishing workflow

Building the GitHub publishing workflow required careful integration with GitHub's APIs:

  1. Creating the correct commit structure
  2. Handling file paths and branch selection
  3. Setting up a GitHub Action to respond to the published content

The GitHub Action workflow automatically processes newly published articles:

name: Process Published MDX
on:
  repository_dispatch:
    types: [publish-article]

jobs:
  process-article:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
      
      # More steps for processing the article...
      
      - name: Deploy site
        run: # Deploy commands

Future improvements

I'm planning to add several features to make the editor even more powerful:

  1. Image uploads - Direct image uploading with optimization
  2. Draft management - Save and manage draft articles
  3. SEO analysis - Built-in SEO recommendations for content
  4. Analytics integration - View article performance directly in the editor
  5. Collaborative editing - Allow multiple authors to work on the same article

Conclusion

Building this MDX editor has transformed my content workflow. I've gone from a multi-step process that took minutes to a streamlined experience that lets me focus on writing. The ability to publish with one click removes friction and encourages me to write more frequently.

This is just the first article published with my new editor, but it represents the beginning of a more productive content creation process. If you're interested in the code, I'll be open-sourcing the project soon on my GitHub.

Happy writing!

J

Jagadhiswaran Devaraj

Full-Stack Developer

Let's Connect & Code

Follow me for in-depth technical insights on JavaScript, Full-Stack Development, AI, and System Architecture. Let's explore the fascinating world of modern web development together!

Find me online

Comments & Discussion

Share your thoughts and join the conversation

Comments

💡Insight
Question
🔥Appreciate
💬General