All Projects → saasforge → Open Source Saas Boilerpate

saasforge / Open Source Saas Boilerpate

Licence: mit
Free SaaS boilerplate (Python/PostgreSQL/ReactJS/Webpack)

Programming Languages

javascript
184084 projects - #8 most used programming language
python
139335 projects - #7 most used programming language
python3
1442 projects

Projects that are alternatives of or similar to Open Source Saas Boilerpate

Yii2 Angular Boilerplate
Yii2 REST API + Angular10 Boilerplate (Frontend/Backend)
Stars: ✭ 194 (-66.67%)
Mutual labels:  jwt, boilerplate, dashboard
Xboot
基于Spring Boot 2.x的一站式前后端分离快速开发平台XBoot 微信小程序+Uniapp 前端:Vue+iView Admin 后端:Spring Boot 2.x/Spring Security/JWT/JPA+Mybatis-Plus/Redis/Elasticsearch/Activiti 分布式限流/同步锁/验证码/SnowFlake雪花算法ID 动态权限 数据权限 工作流 代码生成 定时任务 社交账号 短信登录 单点登录 OAuth2开放平台 客服机器人 数据大屏 暗黑模式
Stars: ✭ 3,432 (+489.69%)
Mutual labels:  jwt, dashboard
Flask jsondash
🐍 📊 📈 Build complex dashboards without any front-end code. Use your own endpoints. JSON config only. Ready to go.
Stars: ✭ 3,215 (+452.41%)
Mutual labels:  flask, dashboard
Beauty Vuejs Boilerplate
❤️ Real world base Vue.js app. Access/refresh tokens auth, api services, http client, vuex modules
Stars: ✭ 583 (+0.17%)
Mutual labels:  jwt, boilerplate
Flask Boilerplate
Simple flask boilerplate with Postgres, Docker, and Heroku/Zeit now
Stars: ✭ 251 (-56.87%)
Mutual labels:  flask, boilerplate
Modular Admin Html
ModularAdmin - Free Dashboard Theme Built On Bootstrap 4 | HTML Version
Stars: ✭ 2,875 (+393.99%)
Mutual labels:  boilerplate, dashboard
Express Rest Api Boilerplate
Express REST API with JWT Authentication and support for sqlite, mysql, and postgresql
Stars: ✭ 384 (-34.02%)
Mutual labels:  jwt, boilerplate
Saas Base
SaaS base application (Flask, Vue, Bootstrap, Webpack)
Stars: ✭ 208 (-64.26%)
Mutual labels:  flask, dashboard
Full Stack
Full stack, modern web application generator. Using Flask, PostgreSQL DB, Docker, Swagger, automatic HTTPS and more.
Stars: ✭ 451 (-22.51%)
Mutual labels:  flask, jwt
Flask Empty
An empty project skeleton / boilerplate for flask projects. Powered by CookieCutter.
Stars: ✭ 569 (-2.23%)
Mutual labels:  flask, boilerplate
Laravel Vue Boilerplate
🐘 A Laravel 6 SPA boilerplate with a users CRUD using Vue.js 2.6, GraphQL, Bootstrap 4, TypeScript, Sass, and Pug.
Stars: ✭ 472 (-18.9%)
Mutual labels:  jwt, boilerplate
Flask Base
A simple Flask boilerplate app with SQLAlchemy, Redis, User Authentication, and more.
Stars: ✭ 2,680 (+360.48%)
Mutual labels:  flask, boilerplate
Slapdash
Boilerplate for bootstrapping scalable multi-page Dash applications
Stars: ✭ 225 (-61.34%)
Mutual labels:  flask, boilerplate
Flask Api Starter Kit
Start a Flask API in less than 5 minutes
Stars: ✭ 296 (-49.14%)
Mutual labels:  flask, boilerplate
Authlib
The ultimate Python library in building OAuth, OpenID Connect clients and servers. JWS,JWE,JWK,JWA,JWT included.
Stars: ✭ 2,854 (+390.38%)
Mutual labels:  flask, jwt
Koa Vue Notes Api
🤓 This is a simple SPA built using Koa as the backend, Vue as the first frontend, and React as the second frontend. Features MySQL integration, user authentication, CRUD note actions, and async/await.
Stars: ✭ 342 (-41.24%)
Mutual labels:  jwt, boilerplate
Fastapi React
🚀 Cookiecutter Template for FastAPI + React Projects. Using PostgreSQL, SQLAlchemy, and Docker
Stars: ✭ 501 (-13.92%)
Mutual labels:  jwt, boilerplate
Flask Restless Security
Concise skeleton for development of Flask, Flask-Restless, SQLAlchemy, JWT based REST APIs.
Stars: ✭ 159 (-72.68%)
Mutual labels:  flask, jwt
Ssis Dashboard
HTML5 SQL Server Integration Services Dashboard
Stars: ✭ 206 (-64.6%)
Mutual labels:  flask, dashboard
Flasksaas
A great starting point to build your SaaS in Flask & Python, with Stripe subscription billing 🚀
Stars: ✭ 412 (-29.21%)
Mutual labels:  flask, boilerplate

SaaS-Boilerpate

SaaS application boilerplate

This free boilerplate allows creating a working SaaS web application. Please file all the information on our website: https://www.saasforge.dev

Technologies

  • Python (Flask) - backend
  • PostgreSQL - database
  • ReactJS - frontend
  • CSS/SCSS for styling
  • Fontawesome
  • Webpack/Babel - frontend building

System requirements

Currently, the boilerplate works with Python 3.5.

Features

User authentication

  • Email authentication (with email confirmation)
  • User registration, login, logout
  • Simple user profile page

Interface

Project structure

All features/functions are put into separate structures, often front-end and back-end side-by-side. The whole project is divided into the following parts:

Blueprints (back-end applications)

Based on Flask blueprint, it allows separating parts of an application that are significantly different each from another and requires a different level of authentication/authorization.

Modules

Modules are the code that can't be decoupled and should go together: front-end and back-end. They both belong to the same functionality and front-end often calls endpoints from the same module's back-end.

The API endpoints will be imported and registered in the dashboard blueprint automatically.

If back-end requires to initialize some extension using init_api() this function should be provided at the .py code and will be called automatically.

Auth

Contains the server-side API and ReactJS components.

Server-side part
  1. API, user registration/email confirmation logic.
  2. The authentication is implemented with using JWT.
Front-end part
  1. Component with routes working as a SPA (single page application)
  2. Responsive design
  3. Pages:
  • register
  • login
  • finish registration info page
  • confirmation page (with automatic redirection to the login page)
Screenshots

Registration page on a normal computer screen

Registration page on a normal computer screen

Registration page on a mobile screen

Registration page on a mobile screen

Confirmation page on a mobile screen

Confirmation page on a mobile screen

JWT

Is used for the token authentication. The component has the API server-side part and JS file with functions called automatically. In our implementation we use cookie-based token as for it's most safe method of using tokens at the moment.

Server-side API

It has just 4 functions:

  • init_app (Inits JWT-Flask manager and add needed config variables to the application)
  • login_create_tokens(creates a token on user's login and add attach the corresponding cookies to the response object)
  • logout(unset cookies from the response on user's logout)
  • token_refresh(updates the access' token on demand).
Frond-end functions

This file is referred in the Auth jsx component and it's only purpose is to add the interceptor in all the following requests done by axios. You don't need to call it directly.

ComponentsDemo

Contains demo views for alerts.

ErrorPages

Currently, only one error (404, file not found) is currently handled. When a user enters a non-existing URL (for example, /app/blabla), the error will be shown:

404 error

Profile

API

Contains one endpoint /app/api/profile with 2 methods:

  • GET (login required): returns the current user data
  • POST (login required): updates the current user profile (username)
Profile view

Simple view to update the current user's username: Profile saved

Components (in alphabetical order)

Components are ReactJS piece of code, sometimes accompanied by CSS. Doesn't have any back-end part. Note. This is just description of components, all documentation can be found for each component in its folder.

Alert

Styled block with and icon and text. There are 4 types of alerts:

  • Success
  • Info
  • Warning
  • Error

Alerts

Tip You can set up if you want an alert to disappear after a required number of seconds (see documentation for details).

Dropdown menu

Dropdown menu is used in the header of the dashboard. It's based on a simple JSON structure, for example this data

const topMenu = [
    {title: 'Profile', url: '/app/profile', component: lazy(() => import('@src/modules/profile/ProfileView'))},
    {title: 'Change password', url: '/app/password', component: lazy(() => import('@src/modules/password/ChangePasswordUI'))},
    {divider: true},
    {title: 'Logout', url: '/api/auth/logout', method: 'post', redirectUrl: '/auth/login'}
];

will generate the following menu:

Example top menu

Features
  • Specify data in the human-friendly JSON data structure
  • You can specify divider
  • You can specify method if it's not POST
  • You can specify redirectURL if you don't need to load any component but rather redirect user to the different page
  • You don't need to import components anywhere else, all routes will be generated automatically

Left menu

Responsive, collapsible menu with any amount of items on each level. You create it just filling up the JSON data file:

    {
        groupTitle: 'Demo',
        items: [
            {
                title: 'Alerts', 
                icon: 'exclamation-triangle',
                color: 'yellow',
                url: '/app/demo/alerts',
                component: lazy(() => import('@src/modules/componentsDemo/AlertDemoView'))
            }
        ]
    }

Note. If you prefer you can import component separately and assign it excplicitly in the menu data structure.

Menu when expanded and collapsed

Menu when expanded and collapsed

Menu on the small screen

Menu on the small screen

Features
  • Specify data in the human-friendly JSON data structure
  • You can specify icon (Fontawesome) and color for items (if you don't the default icon and colors will be used for the collapsed version)
  • You can specify url and lazy loaded component for better performance
  • You don't need to import components anywhere else, all routes will be generated automatically

Maker brand

Just small piece of HTML containing link to our website (SaaSForge). You may remove it but you can't replace it wit your own brand.

Services

Email

Can be used for the sending transactional email. Example of using:

from src.shared.services.email import service as email_service

email_service.send_email(user.email, get_config_var('COMPANY_NAME') + ': Confirm your registration', 
                        text_body, 
                        html_body, 
                        get_config_var('COMPANY_NAME'),
                        get_config_var('MAIL_DEFAULT_SENDER'))

Utils

Some important utils are located in /src/shared/utils folder.

DB scaffolding functions

Contains functions to update database based on the current db_models. Automatically finds all models. Don't call this function directly, it can be called implicitly using the following script:

flask dbupdate

Extensions

Contains the instances of extensions to be used in different files. All of them are inited in the app factory.

Global functions

Contains several functions used globally. Some of them are also available for using in jinja.

get_config_var

Safely returns the corresponding app.config[var_name] if found, else None. Example of using in jinja HTML layout:

<title>{{get_config_var('COMPANY_NAME')}}</title>
flat_validation_errors(errors_object)

Takes an errors object (like {'error1': 'Text of error 1', 'error2': 'Error 2'}) and returns a single string containing all the error texts.

Server error handler

If some error (non-handled exception) occured it handles and returns the following page:

Server-side error page

User authentication wrappers

@loginrequired wrapper

To protect endpoints and make them accessible only if user is authenticated, use this wrapper. Currently, it wraps JWT wrapper, but you can easily change it to anything else. Example of using:

from src.shared.utils.user_auth_wrapper import login_required

@profile_api.route('/')
class retrieve_user_profile(Resource):
    @login_required
    def get(self):
        ...
get_current_user_id wrapper function

This function wraps JWT get_jwt_identity and returns the current user's id what can be easily used for getting any data associated with the current user:

from src.shared.utils.user_auth_wrapper import get_current_user_id

@profile_api.route('/')
class retrieve_user_profile(Resource):
    @login_required
    def get(self):
        current_user_id = get_current_user_id()
        current_user = db_user_service.get_user_by_id(current_user_id)
        ...

Database models

Contains the following tables:

  • User
  • Role
  • Account
  • AccountHistory

When done any changes to the tables including adding new tables run the following command from the terminal:

flask dbupdate

Note. Make sure your environment variables has the following var: FLASK_APP=application else it wount work.

Note 2. Don't forget to add db_url variable with URL to your database to the environment variables.

Tip. When this command runs for the first time it creates all the tables as well as 2 roles: User and Admin.

Dev's features and tips

  • All features are now divided into units and components. Frontend and backend are put side-by-side for easier reference and development.
  • Handling 404 and 500 errors
  • AWS Beanstalk-friendly (you don't need to change any files' names to start deploying the project there)
  • Automatic importing APIs, namespaces (when add a new API you don't need to import it explicitly, you just need to name it api.py)
  • All styles in one folder what allows to change and create a new theme fast (see /src/shared/theme)
  • ES6
  • Refer @src as a root source folder in you JSX and JS code

Conventions / tips

Common

  • While creating components with backend Python code and if you want to provide any API endpoints (like '/app/api/whatever'), put them into api.py file. It will be found and imported automatically.
  • If you API file needs to register some extension provide the init_app(app) function and it will be called automatcally. For example:
def init_app(app):
    jwt.init_app(app)
  • If you would like to create a sevice to be called from the server-side code (not by the front-end using endpoint) create a new folder (file) in the /src/shared/services folder.

Note. If you need to use some extension there, the same create a function init_app that will be called automatically.

Custom static files

Using in Python (in html files): For example, to specify path to a resource in some component:

<link rel="icon" type="image/x-icon" href="{{ url_for("custom_static", 
    filename="shared/components/media_component/favicon.ico") }}" />

Services/functions

Config: how to securely configure your variables

  1. Add the variable in config.py directly and assign its value (only if it's not sensitive, like a flag to use SSL or TLS)
  2. Sensitive data put into the environment variables. It could be done in 2 ways:
  • Add them into venv/scripts/activate script
  • add them into .env file in the project folder.
  1. In the code always call get_config_var:
from src.shared.utils.global_functions import get_config_var
get_config_var('var_name')

This function also can be safely used in jinja HTML files:

<title>{{get_config_var('COMPANY_NAME')}}</title>

Making requests from the front-end code

Use axios(link) for making requests. For example (asynchronous way):

import axios from 'axios';
...
componentDidMount = async()=> {
    // Load user data
    try {
        let response = await axios.get('/app/api/profile');
        if (response.data.result){
            this.setState({ username: response.data.username});
        } else {
            this.setState({ status: 'error', message: response.data.error || 'Some error occured during this request... please try again.' });
        }
    } catch {
        this.setState({ status: 'error', message: 'Some error occured during this request... please try again.' });
    }
}

Installation

Prerequisites

Before start make sure you have installed Python 3 and Node.js. Please follow the official instructions. Also, you need to have a PostgreSQL database handy. If you don't want to install it you can use ElephantSQL service, they have a free plan: https://www.elephantsql.com/plans.html.

Steps to follow

  1. Download the full zip or pull code from the repository, find full instruction in Github documentation

  2. Add necessarily environment variables (you can add them into /venv/scripts/activate file or into .env in the root folder):

  • FLASK_APP=application
  • db_url='postgres://user:[email protected]:port/database'
  • JWT_SECRET_KEY='your jwt secret key'
  • SECRET_KEY='your secret key'
  • MAIL_SERVER = 'mail server'
  • MAIL_PORT = Number (like 465)
  • MAIL_USE_SSL = Bool (True of False)
  • MAIL_USE_TLS = Bool (True of False)
  • MAIL_USERNAME = 'your email'
  • MAIL_PASSWORD = 'your password'
  • ADMIN_EMAIL = 'your admin email'
  • MAIL_DEFAULT_SENDER = 'the same as your email'

Note. At least 2 first variables MUST be set up (FLASK_APP and db_url) else the installation script wont' work.

JWT_SECRET_KEY and SECRET_KEY are just strings that not easy to guess, for example, it may be 'My Co0LServ_ice'.

Tip. If you are puzzled how and why .env is used please read this explanation on Stackoverflow

  1. Run the command (Windows):
init

(Mac):

./init.sh

For any problem happening during execution of this command please see the section Troubleshooting below.

⚠️ Warning! This command will first drop ALL tables in your database. (You can comment this part if you wish, see /src/shared/utils/db_scaffold, line 25.)

  1. If everything is going fine you will see the following text in your terminal:
* Serving Flask app "application"
* Environment: production
  WARNING: Do not use the development server in a production environment.
  Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

If you prefer to go through the installation process manually, please refer steps from the according version of init file in the root folder.

Updating database

After you change something in your database models you should update the database itself. It can be done easily with the following command:

flask dbupdate

Note. If you added some code including changes done into your model, and then run flask dbupdate and see some weird errors like Error: no such command "dbupdate" it means you have a compilation error. Try to run your code and see if there any errors, fix them and try to update the database again. To make sure there are not compilation errors, run the following command:

flask run

Note 2. Another reason for this error can be that you didn't add the following environment variable:

FLASK_APP=application

⚠️ Warning. If you work on the same codebase from different computers and update the same database you will experience Alembic migration conflicts. The error usually says

alembic.util.exc.CommandError: Target database is not up to date. 

or

alembic.util.exc.CommandError: Can't locate revision identified by 'somenumber' 

If you experience such errors:

  1. In the database remove the record from alembic_version table
  2. Remove any files from your computer under app/migrations.

Troubleshooting

Sometimes, if you use Mac OS you can experience some problems with installing the boilerplate.

  • When you try to execute init.sh if you see the following error "init.sh: Command not found" go to the boilerplate's root folder and run
./init.sh

Then, if you see "./init.sh permission denied" run:

sudo chmod 755 'init.sh'
  • When the script is running you may see the error during installation some Python packages like "Error: pg_config executable not found."

You need to fix this problem because script won't execute beyond. To fix this problem run

brew install postgresql
  • If you see any other problem with installation packages it can prevent from working script normally so you have to fix all this problems.

  • If you build and run the project but then you see the following exception: ImportError: No module named 'psycopg2._psycopg' uninstall and install the module back:

pip uninstall psycopg2
pip install psycopg2
  • If you are trying to update database and see something like "dbupdate no such command", check your virtual environment. Check venv/Lib/site-packages folder to see if installation still exists (sometimes if you move the root folder the files may be presented on the disc but the current virtual environment just doesn't see them, so reinstall all packages from scratch.)

Running with Docker

  1. Add or override necessary environment variables using .env.
  2. Run with docker-compose:
docker-compose up

Setting your own data

Company name

There are 2 places to set up your company name:

  1. Config.py - change COMPANY_NAME variable
  2. /src/shared/globalVars.js - change globalVars object

Author

This free SaaS app boilerplate was create by SaaS Forge Inc. https://www.saasforge.dev

License

MIT License Copyright (c) 2019 SaaS Forge Inc. https://www.saasforge.dev.

Feedback and support

If you experience any difficulties, or have any questions on using of this product, or find a bug please open an issue or drop us a line at [email protected].

Disclaimer of Warranties

We provide this boilerplate as is, and we make no promises or guarantees about it.

Would you like to support us?

There are many ways to do it:

  • Star this repository
  • Support us as sponsors, see details here: https://github.com/sponsors/saasforge
  • Create your own SaaS based on this boilerplate and tell us and everyone about it. We will add it to our gallery of fame!
  • Add any functionality or fix bugs and create a pull request
  • Follow our Twitter and tweet about the boilerplate and your experience
  • Follow our Facebook page and like it

Our supportive sponsors:

Sergio Rovira @sgr0691

❤️ THANKS! ❤️

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].