Form validation for email-gated viewing room in Next.js/Sanity

10 replies
Last updated: Sep 14, 2022
Hello, I’m looking at how to incorporate form validation into my Next JS / Sanity project, it’s for a ‘viewing room’ page — an online exhibition page that requires the visitor to submit their email address in order to view the page. There is no further authentication required and there is no login per se. Simply I need to be able to receive and store a submitted email address securely, and then allow access to the next page on receipt of a valid email address. Is it possible to get a response object from Sanity to confirm the submitted data perhaps? Would I be right to look at the next-auth sanity plugin (seems like it might be more for dealing with logged in users)? Very very grateful for any steering / tips.This is exactly an example of the type of use case:
https://whitecube.viewingrooms.com/viewing-room/introductions-sara-flores/
AI Update

For your viewing room use case, you're on the right track but don't need next-auth at all - that's designed for full authentication systems. Here's a simpler approach for your email-gate scenario:

Storing Email Submissions in Sanity

Yes, you can absolutely store submitted emails in Sanity and get a response confirming the submission. When you use the Sanity JavaScript client's create() mutation, you can use the returnDocuments parameter to get back the created document:

import { createClient } from '@sanity/client'

const client = createClient({
  projectId: 'your-project-id',
  dataset: 'your-dataset',
  token: 'your-write-token', // Keep this secret!
  apiVersion: '2025-02-19',
  useCdn: false
})

// In your Next.js API route
export async function POST(request) {
  const { email } = await request.json()
  
  try {
    const result = await client.create({
      _type: 'viewingRoomSubmission',
      email: email,
      submittedAt: new Date().toISOString(),
      viewingRoomId: 'your-viewing-room-id'
    }, { returnDocuments: true })
    
    // result will contain the created document with _id, _createdAt, etc.
    return Response.json({ 
      success: true, 
      submissionId: result._id 
    })
  } catch (error) {
    return Response.json({ success: false, error: error.message }, { status: 500 })
  }
}
  1. Create a schema in your Sanity Studio for storing submissions:
// schemas/viewingRoomSubmission.js
export default {
  name: 'viewingRoomSubmission',
  type: 'document',
  title: 'Viewing Room Submission',
  fields: [
    {
      name: 'email',
      type: 'string',
      validation: Rule => Rule.required().email()
    },
    {
      name: 'viewingRoomId',
      type: 'string'
    },
    {
      name: 'submittedAt',
      type: 'datetime'
    }
  ]
}
  1. Create a Next.js API route (/app/api/submit-email/route.js) to handle the submission securely with your write token (never expose this client-side!)

  2. Use session storage or cookies on the client side to track which viewing rooms the user has accessed

  3. Validate the email on both client and server side

Security Considerations

  • Keep your Sanity write token in environment variables, never in client code
  • Consider rate limiting your API route to prevent abuse
  • You might want to add a simple captcha to prevent bot submissions
  • Store the write token as SANITY_WRITE_TOKEN in your .env.local file

Response Object Details

When using returnDocuments: true with mutations, Sanity returns the full created document including:

  • _id: The unique document ID
  • _type: The document type
  • _createdAt: Timestamp of creation
  • _updatedAt: Timestamp of last update
  • All your custom fields (email, etc.)

According to the Sanity Mutations API documentation, you can also use returnIds: true if you only need the document IDs back rather than the full documents, which is more efficient.

This approach is much simpler than implementing full authentication and perfectly suited for your email-gated content use case! The client.create() method will return the created document when you pass the returnDocuments option, giving you confirmation that the email was successfully stored.

Show original thread
10 replies
Hello
user C
👋The question is, which kind of validation would you like to be running?
Because if you only need to validate that the user is putting in an email string and not some other random ones, I can give you some regex-validation I run in my nextJS forms
😉
Hello
user J
Thanks for your message! 👋 That’s a good thought, perhaps some regex validation is all I need here. That would be really kind if you are happy to share what you use
I will look for it tomorrow, I can’t find it anymore and I have so much code 😅 But I know it is somewhere.
I can only imagine the endless snippets you must gather 🙃 Thanks so much though, no rush, and no stress if it’s too tricky to find
I FOUND IT (on our own site, where I published it… google helped me find it 😅 And it shows how we all tend to not use it enough)
{
  name: 'email',
  title: 'Email',
  type: 'string',
  validation: Rule => Rule.custom(email => {
      if (typeof email === 'undefined') {
          return true // Allow undefined values
      }
      
      return email.toLowerCase()
          .match(
              /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
            )
            
          ? true
          : 'This is not an email'
    })
}
Amazing, thanks so much
user J
😄
I mean, past-me thought it might be useful, and both of present us did not think of Google early enough (I saw my validation code in a presentation on Friday, remembered that I read something similar somewhere and THEN Googled it ... Well it was my code in the first place 😂 )
It could be a scene from Tenant, haha. It’s a good reminder for me that there are so many useful snippets published on the Sanity site, even when I think I have browsed it thoroughly! 💫 It’s been very useful btw, thanks again!
And it should also be a reminder to publish more… I think we all have snippets like this 🙂

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?