Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c64fbd1
Set up Prisma 5 with MySQL at Planetscale
commitwiz Oct 10, 2023
1f4d0e1
Merge pull request #1 from pjborowiecki/main
commitwiz Oct 21, 2023
4ebcb43
Update .env.example and README
commitwiz Oct 21, 2023
81b1b61
Update README and .env.example
commitwiz Oct 21, 2023
ecc1837
Configure PlanetScale MySQL database connection, define databas schem…
commitwiz Oct 21, 2023
e3c08e3
Update README, db scripts and database schema
commitwiz Oct 21, 2023
4565639
Optimize prisma schema for PlanetScale MySQL database
commitwiz Oct 21, 2023
15be976
Update README
commitwiz Oct 21, 2023
54efc60
Remove Prisma
commitwiz Oct 21, 2023
c5ed8c8
Set up Neon connection, configure drizzle, add initial auth database …
commitwiz Oct 22, 2023
34f2c08
Update schemas and add relations; update package.json scripts, append…
commitwiz Oct 22, 2023
4c13aa3
Update schema to add additional indices; define prepared statements r…
commitwiz Oct 22, 2023
181e79a
Work in progress; switching from prisma to drizzle
commitwiz Oct 23, 2023
6af6390
Work in progress; switching from Prisma to Drizzle
commitwiz Oct 23, 2023
04b2cb1
Replace Prisma with Drizzle ORM; work in progress
commitwiz Oct 23, 2023
9434e9c
Switch from Prisma to Drizzle; work in progress
commitwiz Oct 23, 2023
80b53c0
Set up the base for next-auth-drizzle-planetscale-mysql configuration
commitwiz Oct 24, 2023
394daa4
Update auth schema to emulate relations
commitwiz Oct 24, 2023
b85ce30
Update auth schema for password authentication, password resetting an…
commitwiz Oct 24, 2023
9a903f2
Update auth data schema
commitwiz Oct 24, 2023
663c50f
Update server actions and logic to work with PlanetScale MySQL database
commitwiz Oct 24, 2023
9f17eae
Update README
commitwiz Oct 24, 2023
1040433
Update configuration; upgrade to Next 14; add newsletter, contact for…
commitwiz Nov 10, 2023
6982f6d
Fix a typo
commitwiz Nov 10, 2023
43447c3
Update server actions, drizzle configuration and database schema
commitwiz Nov 11, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,24 @@
NODE_ENV="development"
NEXT_PUBLIC_APP_URL="https://localhost:3000"


# AUTHENTICATION (@ NEXT-AUTH)
# Secret can be generated with `openssl rand -base64 32`
# Follow instructions at https://codevoweb.com/nextjs-add-google-and-github-oauth2-using-nextauth-js/ to obtain client ids and secrets
NEXTAUTH_URL=""
NEXTAUTH_URL="https://localhost:3000"
AUTH_SECRET=""
JWT_SECRET_KEY=""
AUTH_GOOGLE_ID=""
AUTH_GOOGLE_SECRET=""
AUTH_GITHUB_ID=""
AUTH_GITHUB_SECRET=""


# DATABASE (POSTGRES @ NEON)
# Ensure you append `sslmode=required` after the question mark in your connection string
DATABASE_URL=""
GOOGLE_ID=""
GOOGLE_SECRET=""
GITHUB_ID=""
GITHUB_SECRET=""

# EMAIL (@ RESEND)
RESEND_API_KEY=""
RESEND_EMAIL_FROM=""
RESEND_EMAIL_TO=""

# DATABASE (MYSQL @ PLANETSCALE)
DATABASE_URI=""
DATABASE_HOST=""
DATABASE_USERNAME=""
DATABASE_PASSWORD=""
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# next.js
/.next/
/out/
next-env.d.ts

# production
/build
Expand All @@ -23,6 +24,7 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local
Expand All @@ -36,4 +38,7 @@ yarn-error.log*
next-env.d.ts

# certificates
certificates
certificates

# content
.contentlayer
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v18.17.0
115 changes: 45 additions & 70 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,87 +1,62 @@
# [Next 13 starters with authentication and database set up](https://saasyland.com)
# [Next 14 starters with authentication and database set up](https://saasyland.com)

Starter templates for Next.js 13 full-stack projects. Built with Tailwind CSS, ShadCn, authentication, and database. Several branches contain several different configurations, including serverless databases like PostgreSQL with Neon, or MySQL with PlanetScale, Drizzle ORM, Prisma ORM v.5 (serverless-compatible), but also MongoDB and Supabase. The project is written in TypeScript, styled with [Tailwind CSS](https://tailwindcss.com) and [ShadCn](https://shadcn.com). All users are stored in a database, regardless of whether they signed up with email and password, magic link, or via an OAuth provider.
#### See the live demo [here](https://saasyland.com)

**The project is currently under active development. Please check back soon**
## Description:

![public/images/screenshots/screenshot_1](./public/images/screenshots/screenshot_1.png)

![public/images/screenshots/screenshot_2](./public/images/screenshots/screenshot_2.png)

![public/images/screenshots/screenshot_3](./public/images/screenshots/screenshot_3.png)

![public/images/screenshots/screenshot_3](./public/images/screenshots/screenshot_4.png)

## Available configurations:

- ### [next-auth-drizzle-neon-postgres](https://github.com/pjborowiecki/SAASY-LAND-Next-13-Starters-With-Authentication-And-Database-Implemented/tree/next-auth-drizzle-planetscale-mysql)

Under construction

- ### [next-auth-drizzle-planetscale-mysql](https://github.com/pjborowiecki/SAASY-LAND-Next-13-Starters-With-Authentication-And-Database-Implemented/tree/next-auth-drizzle-planetscale-mysql)

Under construction

- ### [next-auth-prisma5-serverless-neon-postgres](https://github.com/pjborowiecki/SAASY-LAND-Next-13-Starters-With-Authentication-And-Database-Implemented/tree/next-auth-prisma5-serverless-neon-postgres)
Starter templates for [Next.js 14](https://nextjs.org/) full-stack projects. Built with [TypeScript](https://www.typescriptlang.org/), [Tailwind CSS](https://tailwindcss.com/), [ShadCn/ui](https://ui.shadcn.com/), authentication, and database. Several branches contain several different configurations, including serverless databases like PostgreSQL with [Neon](https://neon.tech), or MySQL with [PlanetScale](https://planetscale.com), [Drizzle ORM](https://orm.drizzle.team/), [Prisma ORM v.5](https://www.prisma.io/) (serverless-compatible), but also [MongoDB Atlas](https://www.mongodb.com/atlas/database), [Supabase](https://supabase.com/), and even [Nest.js](https://nestjs.com/), [Express (MERN stack)](https://expressjs.com/), or [Django](https://www.djangoproject.com/). All users are stored in a database, regardless of whether they signed up with email and password, magic link, or via an OAuth provider.

This branch contains a Next.js 13 starter with Next-Auth authentication using JSON Web Tokens (JWT), and a PostgreSQL database set up at [Neon](https://neon.tech). The database is connected via [Prisma](https://prisma.io) v.5, which is serverless-compatible. OAuth authentication is also set up for GitHub and Google. The set up contains email verification and password reset functionality, both set up with [Resend](https://resend.com) and [React Email](https://react.email/).
### MySQL at [PlanetScale](https://planetscale.com) with [Drizzle](https://orm.drizzle.team/)

- ##### TODO:
This branch contains a Next.js 14 starter with Next-Auth authentication using JSON Web Tokens (JWT), and a MySQL database set up at [PlanetScale](https://planetscale.com). The database is connected with [Drizzle ORM](https://orm.drizzle.team/), which is serverless-compatible. OAuth authentication is also set up for GitHub and Google providers. The set up contains email verification and password reset functionality, both set up with [Resend](https://resend.com) and [React Email](https://react.email/).

- [x] Implement sign up with email and password
- [x] Implement sign in with email and password
- [x] Implement sign out functionality
- [x] Set up OAuth sign in with GitHub and Google
- [x] Set up email verification
- [x] Set up password reset
- [x] Set up sign in with magic link
- [x] Improve email templates with [React Email](https://react.email/)
- [x] Fix linting warnings
- [ ] Set up a user profile page with a form to update user information
- [ ] Set up file upload for user profile pictures
- [ ] Complete the landing page sections and footer
- [ ] Add terms of service and privacy policy pages
- [ ] Set up a newsletter sign up
- [ ] Add contact form
- [ ] Implement payments with [Stripe](https://stripe.com)
- [ ] Set up blogging with Markdown and MDX (or [Payload 2](https://payloadcms.com/) and [Lexical](https://lexical.dev/))
<br />

- ### [next-auth-prisma5-serverless-planetscale-mysql](https://github.com/pjborowiecki/SAASY-LAND-Next-13-Starters-With-Authentication-And-Database-Implemented/tree/next-auth-prisma5-serverless-planetscale-mysql)
> **Warning**
> This project is still in active development.
>
> It uses new technologies (server actions, serverless database connection, etc. ), which are subject to change and may break your application.
> It is not recommended to use this project in production yet.

Under construction
<br />

- ### [next-auth-docker-local-postgres-drizzle](https://github.com/pjborowiecki/SAASY-LAND-Next-13-Starters-With-Authentication-And-Database-Implemented/tree/next-auth-docker-local-postgres-drizzle)
## Features:

Under construction
- [x] Authentication with NextAuth
- [x] Database and ORM set up
- [x] Magic link authentication
- [x] OAuth authentication
- [x] Email and password authentication
- [x] Email verification
- [x] Password reset
- [x] Email templates with React Email
- [x] Functional contact form
- [x] Functional newsletter sign up
- [x] Functional blog with Contentlayer and MDX
- [x] Functional and styled landing page with pricing, features, testimonials, and FAQ sections
- [x] Functional and styled sign in and sign up pages
- [x] Input validation with Zod
- [x] Rigorous linting and TypeScript type checking

- ### [next-auth-docker-local-postgres-prisma](https://github.com/pjborowiecki/SAASY-LAND-Next-13-Starters-With-Authentication-And-Database-Implemented/tree/next-auth-docker-local-postgres-prisma)
<br />

Under construction
- [ ] Documentation pages
- [ ] Stripe payments integration
- [ ] Opt out from newsletter
- [ ] User profile and settings pages
- [ ] Custom loading pages with skeleton loaders
- [ ] Custom error pages
- [ ] Add pages for menu items
- [ ] Improve MDX blog styling
- [ ] Improve performance and make Edge compatible
- [ ] Add tests

- ### [next-auth-mongoose-mongodb](https://github.com/pjborowiecki/SAASY-LAND-Next-13-Starters-With-Authentication-And-Database-Implemented/tree/next-auth-mongoose-mongodb)
<br />

Under construction

- ### [nestjs-nextjs-next-auth-prisma-sqlite](https://github.com/pjborowiecki/SAASY-LAND-Next-13-Starters-With-Authentication-And-Database-Implemented/tree/nestjs-nextjs-next-auth-prisma-sqlite)

Under construction

- ### [nestjs-nextjs-next-auth-drizzle-sqlite](https://github.com/pjborowiecki/SAASY-LAND-Next-13-Starters-With-Authentication-And-Database-Implemented/tree/nestjs-nextjs-next-auth-drizzle-sqlite)

Under construction

- ### [mern-nextjs-redux](https://github.com/pjborowiecki/SAASY-LAND-Next-13-Starters-With-Authentication-And-Database-Implemented/tree/mern-nextjs-redux)

Under construction

- ### [next-auth-supabase-postgres](https://github.com/pjborowiecki/SAASY-LAND-Next-13-Starters-With-Authentication-And-Database-Implemented/tree/next-auth-supabase-postgres)

Under construction

- ### [supabase-postgres](https://github.com/pjborowiecki/SAASY-LAND-Next-13-Starters-With-Authentication-And-Database-Implemented/tree/supabase-postgres)
![public/images/screenshots/screenshot_1](./public/images/screenshots/screenshot_1.png)

Under construction
![public/images/screenshots/screenshot_2](./public/images/screenshots/screenshot_2.png)

- ### [django-rest-djoser-digital-ocean-spaces-aws-ses-next-redux](https://github.com/pjborowiecki/SAASY-LAND-Next-13-Starters-With-Authentication-And-Database-Implemented/tree/django-rest-djoser-digital-ocean-spaces-aws-ses-next-redux)
![public/images/screenshots/screenshot_3](./public/images/screenshots/screenshot_3.png)

# Under construction
![public/images/screenshots/screenshot_4](./public/images/screenshots/screenshot_4.png)
136 changes: 136 additions & 0 deletions contentlayer.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { defineDocumentType, makeSource } from "contentlayer/source-files"
import rehypePrettyCode from "rehype-pretty-code"
import rehypeSlug from "rehype-slug"

/** @type {import('contentlayer/source-files').ComputedFields} */
const computedFields = {
slug: {
type: "string",
resolve: (doc) => `/${doc._raw.flattenedPath}`,
},
slugAsParams: {
type: "string",
resolve: (doc) => doc._raw.flattenedPath.split("/").slice(1).join("/"),
},
readingTime: {
type: "number",
resolve: (doc) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const content = String(doc.body.raw)
const wordsPerMinute = 200
const numberOfWords = content.split(/\s/g).length
const minutes = numberOfWords / wordsPerMinute
return Math.ceil(minutes)
},
},
}

export const Post = defineDocumentType(() => ({
name: "Post",
filePathPattern: `blog/**/*.mdx`,
contentType: "mdx",
fields: {
title: {
type: "string",
required: true,
},
description: {
type: "string",
},
date: {
type: "date",
required: true,
},
published: {
type: "boolean",
default: true,
},
image: {
type: "string",
required: true,
},
authors: {
type: "list",
of: { type: "string" },
required: true,
},
},
computedFields,
}))

export const Author = defineDocumentType(() => ({
name: "Author",
filePathPattern: `authors/**/*.mdx`,
contentType: "mdx",
fields: {
title: {
type: "string",
required: true,
},
description: {
type: "string",
},
avatar: {
type: "string",
required: true,
},
twitter: {
type: "string",
required: true,
},
},
computedFields,
}))

export const Page = defineDocumentType(() => ({
name: "Page",
filePathPattern: `pages/**/*.mdx`,
contentType: "mdx",
fields: {
title: {
type: "string",
required: true,
},
description: {
type: "string",
},
},
computedFields,
}))

export default makeSource({
contentDirPath: "./src/content",
documentTypes: [Post, Author, Page],
mdx: {
rehypePlugins: [
rehypeSlug,
[
rehypePrettyCode,
{
theme: { dark: "github-dark", light: "github-light" },

/**
* @param {{ children: string | any[]; }} node
*/
onVisitLine(node) {
if (node.children.length === 0) {
node.children = [{ type: "text", value: " " }]
}
},
/**
* @param {{ properties: { className: string[]; }; }} node
*/
onVisitHighlightedLine(node) {
node.properties.className.push("line--highlighted")
},
/**
* @param {{ properties: { className: string[]; }; }} node
*/
onVisitHighlightedWord(node) {
node.properties.className = ["word--highlighted"]
},
},
],
],
},
})
13 changes: 13 additions & 0 deletions drizzle.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as dotenv from "dotenv"
import type { Config } from "drizzle-kit"

dotenv.config()

export default {
schema: ["./src/db/schema/index.ts"],
out: "./src/db/migrations",
driver: "mysql2",
dbCredentials: {
uri: process.env.DATABASE_URI || "",
},
} satisfies Config
29 changes: 29 additions & 0 deletions next.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { withContentlayer } from "next-contentlayer"

import("./src/env.mjs")

/** @type {import("next").NextConfig} */
const nextConfig = {
reactStrictMode: true,
experimental: {
webpackBuildWorker: true,
},
images: {
remotePatterns: [
{
protocol: "https",
hostname: "avatars.githubusercontent.com",
},
{
protocol: "https",
hostname: "lh3.googleusercontent.com",
},
{
protocol: "https",
hostname: "uploadthing.com",
},
],
},
}

export default withContentlayer(nextConfig)
Loading