Implement Password-Protected Content for Static Pages (like Next.js)

🔐
engineeringdesign
Posted on June 21, 2025

I have some weird and ridiculous posts that I only want certain people to read, and projects that I only want recruiters with a password to view. But how do you hide content on a static site without losing all the benefits of static generation? 🤔

That's the problem I solved by building a password protection system for my Next.js website. It encrypts content server-side and only decrypts it when someone enters the right password. No server calls needed! While I built this for Next.js, the same approach works with any static site generator like Gatsby, Hugo, or Jekyll.

Here's how I built it:

Step 1: Encrypt Content During Build Time

First, I needed to make sure nobody could peek at the protected content by viewing the page source. The solution? Encrypt everything during build time! 🔒

I store my passwords in Notion (because I store everything in Notion 😅), and during the build process, I check if a post needs protection:

Now when someone views the page source, they just see a bunch of encrypted gibberish. Good luck making sense of that! 😈

Step 2: Decrypt Content When the Password Is Right

Now for the fun part! When someone visits a protected page, they'll need to enter a password. But how do we check if it's right without sending it to a server? 🤓

I used Zustand for state management (it's like Redux but way less boilerplate) and set up a simple store:

Then I created a component that tries to decrypt the content whenever the password changes:

Step 3: Build a Fancy Password Field

The default password input is boring and doesn't give users any visual feedback. I wanted something cooler—a field that shows individual character slots and gives visual feedback as you type. 👌

Here's the trick: I created a layered input where the actual input is invisible, and what the user sees is a custom UI that reacts to the input's state.

The magic happens because the real input is positioned absolutely on top of our visual layer but is transparent. It captures all keyboard events while our custom UI shows what's happening. This gives us complete control over the appearance while maintaining all the native input behavior. 🧙‍♂️

Putting It All Together

In the page component, we combine these elements to create a complete password protection system:

Security Considerations

While this approach provides a good level of protection, it's important to note some limitations:

  1. The encryption is only as strong as the password used
  2. If someone obtains both the encrypted content and the password, they can decrypt it
  3. This approach is best for content that needs casual protection, not highly sensitive information

For truly sensitive data, server-side authentication with proper session management would be more appropriate.

Why I Love This Approach

This password protection system gives me the best of both worlds:

  1. Static site benefits - My site stays blazing fast with all the SEO benefits
  2. No server needed - Everything happens client-side, so no complex auth servers
  3. Great UX - The custom password field makes the whole experience feel polished

Plus, there's something satisfying about implementing a clever solution that doesn't require a complete architecture overhaul. Sometimes the simplest solutions are the most elegant! ✨

Now I can keep posting my weird content without worrying about just anyone stumbling across it. If you want to see it, you'll need the secret password - and no, it's not "password123"! 😄

Remember that the level of security should match the sensitivity of your content. For most use cases, this implementation strikes a good balance between protection and convenience.

If you found this helpful, consider supporting my work

Buy me a coffee

Give your reaction

Or wanna share your thoughts?

Suggestion