All in dirs (#154)

* Split the project into template and opensaas-sh (demo app (diff) + docs).

* fix
This commit is contained in:
Martin Šošić
2024-06-04 13:24:32 +02:00
committed by GitHub
parent 496480509a
commit 04553cd60c
265 changed files with 22081 additions and 70 deletions

View File

@@ -0,0 +1,227 @@
---
title: Getting Started
banner:
content: |
⚠️ Open SaaS is now running on <a href='https://wasp-lang.dev'>Wasp v0.13</a>! If you're running an older version of Open SaaS, please follow the
<a href="https://wasp-lang.dev/docs/migrate-from-0-12-to-0-13">migration instructions here</a> ⚠️
---
This guide will help you get your new SaaS app up and running.
## Install Wasp
### Pre-requisites
You must have Node.js (and NPM) installed on your machine and available in `PATH` to use Wasp.
Your version of Node.js must be >= 18.
To switch easily between Node.js versions, we recommend using [nvm](https://github.com/nvm-sh/nvm).
:::note[Installing and using nvm]
<details>
<summary>
Need help with nvm?
</summary>
<div>
Install nvm via your OS package manager (`apt`, `pacman`, `homebrew`, ...) or via the [nvm](https://github.com/nvm-sh/nvm#install--update-script) install script.
Then, install a version of Node.js that you need:
```shell
nvm install 20
```
Finally, whenever you need to ensure a specific version of Node.js is used, run:
```shell
nvm use 20
```
to set the Node.js version for the current shell session.
You can run
```shell
node -v
```
to check the version of Node.js currently being used in this shell session.
Check NVM repo for more details: https://github.com/nvm-sh/nvm.
</div>
</details>
:::
### Linux and macOS
Open your terminal and run:
```shell
curl -sSL https://get.wasp-lang.dev/installer.sh | sh
```
:::caution[Bad CPU type in executable]
<details>
<summary>
Are you getting this error on a Mac (Apple Silicon)?
</summary>
Given that the wasp binary is built for x86 and not for arm64 (Apple Silicon), you'll need to install <a href='https://support.apple.com/en-us/HT211861'>Rosetta on your Mac</a> if you are using a Mac with Mx (M1, M2, ...). Rosetta is a translation process that enables users to run applications designed for x86 on arm64 (Apple Silicon). To install Rosetta, run the following command in your terminal
```bash
softwareupdate --install-rosetta
```
Once Rosetta is installed, you should be able to run Wasp without any issues.
:::
</details>
### Windows
In order to use Wasp on Windows, you need to install WSL2 (Windows Subsystem for Linux) and a Linux distribution of your choice. We recommend using Ubuntu.
**You can refer to this [article](https://wasp-lang.dev/blog/2023/11/21/guide-windows-development-wasp-wsl) for a step by step guide to using Wasp in the WSL environment.** If you need further help, reach out to us on [Discord](https://discord.gg/rzdnErX).
Once in WSL2, run the following command in your **WSL2 environment**:
```sh
curl -sSL https://get.wasp-lang.dev/installer.sh | sh
```
:::caution[WSL2 and file system issues]
<details>
<summary>
Are you getting file system issues using WSL2?
</summary>
If you are using WSL2, make sure that your Wasp project is not on the Windows file system, <b>but instead on the Linux file system</b>. Otherwise, Wasp won't be able to detect file changes, due to this <a href='https://github.com/microsoft/WSL/issues/4739'>issue in WSL2</a>.
</details>
:::
### Finalize Installation
Run the following command to verify that Wasp was installed correctly:
```shell
wasp version
```
Also be sure to install the Wasp VSCode extension to get the best DX, e.g. syntax highlighting, code scaffolding, autocomplete, etc.
:::tip[Installing the Wasp VSCode Extension]
You can install the Wasp VSCode extension by searching for "Wasp" in the Extensions tab in VSCode, or by visiting the 🐝 [Wasp VSCode Extension](https://marketplace.visualstudio.com/items?itemName=wasp-lang.wasp) 🧑‍💻 homepage
:::
## Setting up your SaaS app
### Cloning the OpenSaaS template
From the directory where you'd like to create your new project run:
```sh
wasp new
```
Then select option `[3] saas` from the list of templates after entering the name of your project.
This will clone a **clean copy of the Open SaaS template** into a new directory! 🎉
### Start your DB
Before you start your app, you need to have a Postgres Database connected and running. With Wasp, that's super easy!
First, make sure you have **Docker installed and running**. If not, download and install it [here](https://www.docker.com/products/docker-desktop/)
With Docker running, open a new terminal window/tab and position yourself in the `app` directory:
```sh
cd app
```
Then run:
```sh
wasp start db
```
This will start and connect your app to a Postgres database for you. No need to do anything else! 🤯 Just make sure to leave this terminal window open in the background while developing. Once you terminate the process, your DB will no longer be available to your app.
Now let's create our very first database migration, to ensure the database has a correct schema. Open a new terminal tab/window and run the following command:
```sh
wasp db migrate-dev
```
This might take a bit since this is the first time you are running it and it needs to install all the
dependencies for your Wasp project.
In the future, you will also want to run `wasp db migrate-dev` whenever you make changes to your Prisma schema (Entities),
to apply those schema changes to the database.
Additionally, if you want to see or manage your DB via Prisma's DB Studio GUI, run:
```sh
wasp db studio
```
### Start your app
At this point, you should be positioned in the `app/` directory and have the database running in another terminal session.
Next, copy the `.env.server.example` file to `.env.server`.
```sh
cp .env.server.example .env.server
```
`.env.server` is where API keys for services like Stripe, email sender, and similar go, and this is where you will want to put them in later.
For now, you can leave it as it is (dummy API keys), this will be enough to run the app.
Then run:
```sh
wasp start
```
This will install all the dependencies and start the app (client and server) for you :)!
If the app doesn't open automatically in your browser, you can open it manually by visiting `http://localhost:3000` in your browser.
At this point, you should have:
- your database running in one terminal session, likely on port `5432`.
- your app running in another terminal session, the client likely on port `3000`, and the server likely on port `3001`.
#### Run Blog and Docs
This SaaS app comes with a docs and blog section built with the [Starlight template on top of the Astro](https://starlight.astro.build) framework. You can use this as a starting point for your own blog and documentation, if necessary.
If you do not need this, you can simply delete the `blog` folder from the root of the project.
If you want to run the Starlight docs and blog, first navigate to the `blog` folder:
```sh
cd ../blog
```
Then run:
```sh
npm install
```
Then start the development server:
```sh
npm run dev
```
Check the instructions in the terminal for the link to open the blog, it will typically be `https://localhost:4321/`.
## What's next?
Awesome! We have our new app ready and we know how to run both it and the blog/docs! Now, in the next section, we'll give you a quick "guided tour" of the different parts of the app we created and understand how it works.
:::tip[Star our Repo on GitHub! 🌟]
We've packed in a ton of features and love into this SaaS starter, and offer it all to you for free!
If you're finding this template and its guides useful, consider giving us [a star on GitHub](https://github.com/wasp-lang/wasp)
:::

View File

@@ -0,0 +1,265 @@
---
title: Guided Tour
banner:
content: |
⚠️ Open SaaS is now running on <a href='https://wasp-lang.dev'>Wasp v0.13</a>! If you're running an older version of Open SaaS, please follow the
<a href="https://wasp-lang.dev/docs/migrate-from-0-12-to-0-13">migration instructions here</a> ⚠️
---
Let's get to know our new SaaS app.
First, we'll take a look at the project's file structure, then dive into its main features and how you can get started customizing them.
:::caution[HOLD UP! ✋]
If you haven't already, now would be the right time to [explore our demo app](https://opensaas.sh) in your browser:
- [ ] explore the landing page
- [ ] log in to the demo app
- [ ] make a test purchase
- [ ] check out the admin dashboard
- [ ] check out your account settings
- [ ] check out the blog
:::
## Getting acquainted with the codebase
Now that you've gotten a feel for the app and how it works, let's dive into the codebase.
At the root of our project, you will see two folders:
```sh
.
├── app
└── blog
```
`app` contains the Wasp project files, which is your full-stack React + NodeJS + Prisma app along with a Wasp config file, `main.wasp`, which will be explained in more detail below.
`blog` contains the [Astro Starlight template](https://starlight.astro.build/) for the blog and documentation section.
Let's check out what's in the `app` folder in more detail:
:::caution[v0.11 and below]
If you are using a version of the OpenSaaS template with Wasp `v0.11.x` or below, you may see a slightly different file structure. But don't worry, the vast majority of the code and features are the same! 😅
:::
```sh
.
├── main.wasp # Wasp Config file. You define your app structure here.
├── .wasp/ # Output dir for Wasp. DON'T MODIFY THESE FILES!
├── public/ # Public assets dir, e.g. www.yourdomain.com/banner.png
├── src/ # Your code goes here.
│   ├── client/ # Your client code (React) goes here.
│   ├── server/ # Your server code (NodeJS) goes here.
│   ├── shared/ # Your shared (runtime independent) code goes here.
│   └── .waspignore
├── .env.server # Dev environment variables for your server code.
├── .env.client # Dev environment variables for your client code.
├── .prettierrc # Prettier configuration.
├── tailwind.config.js # TailwindCSS configuration.
├── package.json
├── package-lock.json
└── .wasproot
```
:::tip[File Structure]
Note that since Wasp v0.12, the `src` folder does not need to be organized between `client` and `server` code. You can organize your code however you like, e.g. by feature, but we've chosen to keep the traditional structure for this template.
:::
### The Wasp Config file
This template at its core is a Wasp project, where [Wasp](https://wasp-lang.dev) is a full-stack web app framework that lets you write your app in React, NodeJS, and Prisma and will manage the "boilerplatey" work for you, allowing you to just take care of the fun stuff!
[Wasp's secret sauce](https://wasp-lang.dev/docs) is its use of a config file (`main.wasp`) and compiler which takes your code and outputs the client app, server app and deployment code for you.
In this template, we've already defined a number of things in the `main.wasp` config file, including:
- Auth
- Routes and Pages
- Prisma Database Models
- Operations (data read and write functions)
- Background Jobs
- Email Sending
By defining these things in the config file, Wasp continuously handles the boilerplate necessary with putting all these features together. You just need to focus on the business logic of your app.
Wasp abstracts away some things that you would normally be used to doing during development, so don't be surprised if you don't see some of the things you're used to seeing.
:::note
It's possible to learn Wasp's feature set simply through using this template, but if you find yourself unsure how to implement a Wasp-specific feature and/or just want to learn more, a great starting point is the intro tutorial in the [Wasp docs](https://wasp-lang.dev/docs) which takes ~20 minutes.
:::
### Client
The `src/client` folder contains all the code that runs in the browser. It's a standard React app, with a few Wasp-specific things sprinkled in.
```sh
.
└── client
   ├── admin # Admin dashboard pages and components
  ├── app # Your user-facing app that sits behind the paywall/login.
  ├── auth # All auth-related pages and components.
  ├── components # Your shared React components.
  ├── hooks # Your shared React hooks.
   ├── landing-page # Landing page related code
   ├── static # Assets that you need access to in your code, e.g. import logo from 'static/logo.png'
   ├── App.tsx # Main app component to wrap all child components. Useful for global state, navbars, etc.
   └── Main.css
```
### Server
The `src/server` folder contains all the code that runs on the server. Wasp compiles everything into a NodeJS server for you.
All you have to do is define your server-side functions in the `main.wasp` file, write the logic in a function within `src/server` and Wasp will generate the boilerplate code for you.
```sh
└── server
   ├── auth # Some small auth-related functions to customize the auth flow.
  ├── file-upload # File upload utility functions.
  ├── payments # Payments utility functions.
  ├── scripts # Scripts to run via Wasp, e.g. database seeding.
  ├── webhooks # The webhook handler for Stripe.
  ├── workers # Functions that run in the background as Wasp Jobs, e.g. daily stats calculation.
  ├── actions.ts # Your server-side write/mutation functions.
   ├── queries.ts # Your server-side read functions.
   └── types.ts
```
## Main Features
### Auth
This template comes with a fully functional auth flow out of the box. It takes advantages of Wasp's built-in [Auth features](https://wasp-lang.dev/docs/auth/overview), which do the dirty work of rolling your own full-stack auth for you!
```js title="main.wasp"
auth: {
userEntity: User,
methods: {
email: {
//...
},
google: {},
github: {},
},
onAuthFailedRedirectTo: "/",
},
```
By defining the auth structure in your `main.wasp` file, Wasp manages all the necessary code for you, including:
- Email verified login with reset password
- Social login with Google and/or GitHub
- Auth-related databse entities for user credentials, sessions, and social logins
- Custom-generated AuthUI components for login, signup, and reset password
- Auth hooks for fetching user data
<!-- TODO: add pic of AuthUI components -->
We've set the template up with Wasp's `email`, `google`, and `gitHub` methods, which are all battle-tested and suitable for production.
You can get started developing your app with the `email` method right away!
:::caution[Dummy Email Provider]
Note that the `email` method relies on an `emailSender` (configured at `app.emailSender` in the `main.wasp` file), a service which sends emails to verify users and reset passwords.
For development purposes, Wasp provides a `Dummy` email sender which Open SaaS comes with as the default. This provider *does not* actually send any confirmation emails to the specified email address, but instead logs all email verification links/tokens to the console! You can then follow these links to verify the user and continue with the sign-up process.
```tsx title="main.wasp"
emailSender: {
provider: Dummy, // logs all email verification links/tokens to the server's console
defaultFrom: {
name: "Open SaaS App",
email: "me@example.com"
},
},
```
:::
We will explain more about these auth methods, and how to properly integrate them into your app, in the [Authentication Guide](/guides/authentication).
### Subscription Payments with Stripe
No SaaS is complete without payments, specifically subscription payments. That's why this template comes with a fully functional Stripe integration.
Let's take a quick look at how payments are handled in this template.
1. a user clicks the `BUY` button and a **Stripe Checkout session** is created on the server
2. the user is redirected to the Stripe Checkout page where they enter their payment info
3. the user is redirected back to the app and the Stripe Checkout session is completed
4. Stripe sends a webhook event to the server with the payment info
5. The app server's **webhook handler** handles the event and updates the user's subscription status
The logic for creating the Stripe Checkout session is defined in the `src/server/actions.ts` file. [Actions](https://wasp-lang.dev/docs/data-model/operations/actions) are your server-side functions that are used to write or update data to the database. Once they're defined in the `main.wasp` file, you can easily call them on the client-side:
a) define the action in the `main.wasp` file
```js title="main.wasp"
action stripePayment {
fn: import { stripePayment } from "@src/server/actions.js",
entities: [User]
}
```
b) implement the action in the `src/server/actions.ts` file
```js title="src/server/actions.ts"
export const stripePayment = async (tier, context) => {
//...
}
```
c) call the action on the client-side
```js title="src/client/app/SubscriptionPage.tsx"
import { stripePayment } from "wasp/client/operations";
const handleBuyClick = async (tierId) => {
const stripeResults = await stripePayment(tierId);
};
```
The webhook handler is defined in the `src/server/webhooks/stripe.ts` file. Unlike Actions and Queries in Wasp which are only to be used internally, we define the webhook handler in the `main.wasp` file as an API endpoint in order to expose it externally to Stripe
```js title="main.wasp"
api stripeWebhook {
fn: import { stripeWebhook } from "@src/server/webhooks/stripe.js",
httpRoute: (POST, "/stripe-webhook")
entities: [User],
}
```
Within the webhook handler, we look for specific events that Stripe sends us to let us know which payment was completed and for which user. Then we update the user's subscription status in the database.
To learn more about configuring the app to handle your products and payments, check out the [Stripe Integration guide](/guides/stripe-integration).
:::tip[Star our Repo on GitHub! 🌟]
We've packed in a ton of features and love into this SaaS starter, and offer it all to you for free!
If you're finding this template and its guides useful, consider giving us [a star on GitHub](https://github.com/wasp-lang/wasp)
:::
### Analytics and Admin Dashboard
Keeping an eye on your metrics is crucial for any SaaS. That's why we've built an administrator's dashboard where you can view your app's stats, user data, and Stripe revenue all in one place.
<!-- TODO: add pic of admin dash -->
To do that, we've leveraged Wasp's [Jobs feature](https://wasp-lang.dev/docs/advanced/jobs) to run a cron job that calculates your daily stats. The app stats, such as page views and sources, can be pulled from either Plausible or Google Analytics. All you have to do is create a project with the analytics provider of your choice and import the respective pre-built helper functions!
```js title="main.wasp"
job dailyStatsJob {
executor: PgBoss,
perform: {
fn: import { calculateDailyStats } from "@src/server/workers/calculateDailyStats.js"
},
schedule: {
cron: "0 * * * *" // runs every hour
},
entities: [User, DailyStats, Logs, PageViewSource]
}
```
For more info on integrating Plausible or Google Analytics, check out the [Analytics guide](/guides/analytics).
## What's next?
And that concludes our guided tour! For next steps, we recommend ...