DEV Community

loading...
Cover image for Building a SaaS Product in Public - Update 1

Building a SaaS Product in Public - Update 1

Andrew Jones
Web, apps, and web-apps
・3 min read

Welcome to this new series! I'm a frontend developer who recently had an idea for a SaaS product, so I'm going to write this series to share my development process publicly.

Since I've mostly done frontend in the past, I'll be learning more about backend development as I work on this project, and sharing it here!

This first post will have a lot of writing, but the next one will have a lot more coding and implementation :)

The Idea

The idea came from an issue my team ran into at work - what's the best way to sync environment variables across our team? If someone adds a new environment variable to the project, how do we make sure everyone adds that variable to their .env?

After doing some research I found an open source project that allows teams to self-host an env variable distribution server. However that requires a lot of set up and self-hosting capabilities. There is also the Vercel CLI, but that only supports one environment per project and requires teams to use Vercel. This project will be more flexible.

My plan is to create a simple web console with accompanying CLI commands and libraries which allow teams to automate syncing of environment variables across local and production systems.

Selecting an Architecture

Next.js

I've followed Next.js for almost two years and developed a bunch of projects based on it. As a frontend developer, this felt like a natural platform to start from. It supports frontend React pages, and backend API routes, giving me everything I need to create my fullstack project.

Trying Blitz.js

Since I didn't really know where to start with authentication and backend integration, I started by testing out Blitz.js, a fullstack framework for React apps built as an extension of Next.js. Blitz allows developers to quickly generate frontend and backend code based on database models.

After generating a project and going through the starter tutorial, I decided not to move ahead with Blitz. I felt like it generated too much boilerplate without reducing the work required enough, because I still had to manually write forms and connect them to the database. I wanted to keep this project lightweight and clean. (No hate against Blitz! They have a great community and it's still in development, it just wasn't right for this project.)

Prisma & PostgreSQL

Looking at Blitz did lead me to one technology I didn't know about before: Prisma! Prisma is an awesome tool for developers with a frontend background. You define an easily-understandable model file, and then it automatically generates all of the database tables needed for that model, and it also generates Typescript-typed JavaScript functions for developers to easily interact with the database.

This is an example schema. If you've ever used GraphQL, you'll find it familiar:

model User {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now())
  email     String   @unique
  name      String?
}
Enter fullscreen mode Exit fullscreen mode

With this schema, Prisma would generate functions like prisma.user.create to create users in the database, and prisma.user.findMany to list users from the database, so you don't need to write SQL queries yourself:

const newUser = await prisma.user.create({
  data: {
    name: 'Alice',
    email: 'alice@prisma.io',
  },
})

const users = await prisma.user.findMany()
Enter fullscreen mode Exit fullscreen mode

This is a super powerful tool for frontend developers who aren't SQL experts, or anyone who wants to reduce the boilerplate code involved in fullstack apps.

I chose PostgreSQL as my database because it's one of Prisma's recommended databases and I know that it's a powerful, popular database option. I have used NoSQL databases in the past, which are similar to large JSON databases, but I decided to use a SQL database on this project for its scalability and schema safety.

Conclusion

Thanks for following along! Hopefully you can learn something from everything I'm learning :)

In the next post, we'll get to implementation.

Thanks for reading along! Follow me here or on Twitter for more updates and other content

Discussion (4)

Collapse
jverce profile image
Jay Vercellone

Hi! I have a few questions about your use cases:

  • Is sharing env variables only intended for development purposes? Or also during deployment?
  • Have you looked at other platforms like HashiCorp Vault?
  • How will it work? Do users pull the env variables from the service and use them locally? Or will the env variables be retrieved by the project's build system? One case that could happen is a user retrieving variables, then changing them and using those changed ones.
Collapse
ajones_codes profile image
Andrew Jones Author

Hey! Thanks for the questions.

  1. Both! I’m planning on supporting multiple environments per project.
  2. Yes. One competitor is Vercel’s CLI, which lets teams manually pull env variables, but it only supports one environment and of course requires you to use Vercel. HashiCorp Vault does have a lot of similar features, but I’m planning a simpler workflow than their CLI, and cheaper pricing, although I’ll need to figure that out once I’ve developed the service further.
  3. Plan right now is that the variables will be pulled at buildtime and/or runtime and dynamically injected in-memory, plus there will be an override system based on the traditional .env file. Proper logging and CLI output will help clear up confusion around overrides.
Collapse
rafaelrozon profile image
Rafael Rozon

Very often env variables have sensitive information. How are you planning to handle that?
Nice problem to solve, btw.

Collapse
ajones_codes profile image
Andrew Jones Author

Thank you!

In terms of securing access to the service, at the moment I'm planning on the request for the env vars require an API key, which the user could keep in their local .env. The benefit is that there could be one unchanging API key per user, so teams don't need to sync that variable, and the service will do the rest.

In terms of what to do with the env vars after the service pulls them to a user's local, I'm thinking of writing them to a gitignored .env.sync file or something along those lines.