mirror of
https://github.com/wasp-lang/open-saas.git
synced 2025-11-29 07:58:28 +01:00
All in dirs (#154)
* Split the project into template and opensaas-sh (demo app (diff) + docs). * fix
This commit is contained in:
227
opensaas-sh/blog/src/content/docs/start/getting-started.md
Normal file
227
opensaas-sh/blog/src/content/docs/start/getting-started.md
Normal 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)
|
||||
:::
|
||||
265
opensaas-sh/blog/src/content/docs/start/guided-tour.md
Normal file
265
opensaas-sh/blog/src/content/docs/start/guided-tour.md
Normal 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 let’s 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 ...
|
||||
Reference in New Issue
Block a user