Creating Your SaaS Guide

A simple guide to building features inside this boilerplate.

1. General

When deploying your application, refer to the deployments.md file. This file contains optimal server configurations to ensure efficient resource utilization, along with estimated concurrent user counts to help you choose the right server for your needs.

Need Help? If you encounter any issues, please don't hesitate to contact me. I'll respond as quickly as possible, and your feedback helps improve the documentation for future users.

2. Authentication Middleware

By default, this boilerplate uses Django's built-in authentication middleware (introduced in newer Django versions) that requires users to be logged in to access all pages. This provides a secure-by-default approach for SaaS applications where most functionality should be behind authentication.

Default Behavior

All pages require authentication: Users must be logged in to access any view in your application.

  • • Unauthenticated users are automatically redirected to the login page
  • • This applies to all views across your entire application
  • • Provides secure-by-default behavior for SaaS applications
  • • Eliminates the need to add @login_required to every view

Making Pages Public

If you need some pages to be accessible without authentication (e.g., landing pages, pricing, contact), you have two options:

Option 1: Remove Authentication Middleware (Recommended for Public Sites)

Remove the authentication middleware from your settings and manually add decorators to protected views:

  1. Comment out or remove the authentication middleware in config/settings/base.py
  2. Add @login_required decorator to views that need authentication
  3. Use @method_decorator(login_required) for class-based views
# Example: Protecting a view manually from django.contrib.auth.decorators import login_required @login_required def protected_view(request): # This view requires authentication pass

Option 2: Use Login Not Required Decorator

Keep the authentication middleware active but use the @login_not_required decorator on specific views that should be publicly accessible. This approach maintains the secure-by-default behavior while allowing specific public pages.

# Example: Making a view public
from django.contrib.auth.decorators import login_not_required

@login_not_required
def public_view(request):
# This view is accessible without authentication
pass

Use this decorator on landing pages, pricing pages, contact forms, or any other views that should be publicly accessible.

Important: When removing the authentication middleware, remember to protect sensitive views with appropriate decorators. Don't forget views that handle user data, admin functionality, or payment processing.

3. Stripe Configuration

To ensure proper payment processing, you'll need both a webhook secret and a Stripe secret key. First, create a Stripe account and switch to sandbox mode to obtain your test secret key.

Setting up Stripe CLI

Install the Stripe CLI and run the following command to generate your webhook secret:

stripe listen --forward-to localhost:8000/payments/webhook

This command will generate a webhook secret. Copy this secret and add it to the WEBHOOK_SECRET variable in .envs/local/django.env. After adding the secrets, rebuild your container to apply the environment changes.

Setting Up Price ID

In addition to the secret key and webhook secret, you'll need a price_id. To obtain one:

  1. Create a product in your Stripe dashboard
  2. Copy the generated price ID
  3. Search for TODO comments in the codebase that indicate where to add it

The price ID tells Stripe which product or subscription package the user is purchasing.

⚠️ Important: Production Environment

In production, you must use Stripe's live environment (not sandbox mode) and add your production secrets to .envs/production/django.env.

To obtain your production webhook secret, refer to the Stripe webhook documentation. Your webhook endpoint must listen for the following events:

  • checkout.session.completed - Grants membership after successful payment
  • checkout.session.async_payment_succeeded - Handles delayed payment confirmations
  • customer.subscription.deleted - Removes membership when subscription ends
  • customer.subscription.updated - Updates membership status based on subscription changes
  • customer.subscription.paused - Pauses membership access
  • customer.subscription.resumed - Resumes membership access
  • charge.dispute.created - Handles chargebacks by pausing membership
  • invoice.upcoming - Optional: For sending payment reminders

Your production webhook endpoint will be: https://yourdomain.com/payments/webhook

4. AI-Assisted Coding

Before starting with your AI assistant, ensure it follows the guidelines in the AGENTS.md or CLAUDE.md file.

Important: While AI agents can access these files, they may not always follow them consistently. When this happens, you'll need to add the instructions directly to your AI assistant's configuration.

Configuration Examples

  • For Cursor: Add this rule: "You must always follow the AGENTS.md guide"
  • For prompts: Begin with: "Following the AGENTS.md file, implement [feature name]"

Recommended: Run your AI agent inside the dev container for best results. Code editors like Cursor handle this automatically. For Claude, install Claude Code directly in the container and launch it from there.

5. Coding by Yourself

If you prefer to code without AI assistance, you should have at least basic Django knowledge. If you're new to Django (beyond knowing it's Python-based), start with the official Django documentation or explore tutorial videos on YouTube to build foundational skills.

Creating New Features

Before building a feature, determine whether it warrants its own Django app. For example, when creating a todo CRUD feature:

  1. Create a new app: python manage.py startapp todo
  2. Register it in config/settings/base.py

Template Organization

By default, all templates are centralized in the project_name/templates folder. To store templates within individual apps instead, set APP_DIRS = True in the templates configuration in base.py.

Database Migrations

After modifying any models.py file, apply the changes to your database:

python manage.py makemigrations
python manage.py migrate

Always run makemigrations first to create migration files, then run migrate to apply them to the database.

6. Social Login Integration

Adding social login to your application improves user experience by allowing quick sign-up and sign-in through existing accounts. This guide covers integrating Google authentication with Django using the django-allauth package.

Step 1: Configure Django Settings

Add the following to your config/settings/base.py:

# Add to INSTALLED_APPS
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.google', # For Google

# Provider specific settings
SOCIALACCOUNT_PROVIDERS = {
    'google': {
        'SCOPE': [
            'profile',
            'email',
        ],
        'AUTH_PARAMS': {
            'access_type': 'online',
        }
    }
}

Step 2: Google OAuth Setup

  1. Go to Google Cloud Console
  2. Create a new project or select an existing one
  3. Enable the Google+ API for your project
  4. Navigate to "Credentials" → "Create Credentials" → "OAuth 2.0 Client ID"
  5. Configure the OAuth consent screen:
    • Add your application name and support email
    • Add authorized domains (localhost for development, your domain for production)
  6. Create OAuth 2.0 credentials:
    • Application type: Web application
    • Authorized redirect URIs: http://localhost:8000/accounts/google/login/callback/ (development)
    • For production: https://yourdomain.com/accounts/google/login/callback/
  7. Copy the Client ID and Client Secret - you'll add these in Django admin in the next step

Step 3: Admin Setup

Run migrations and configure the social app in Django admin:

python manage.py migrate

# Create superuser if not exists
python manage.py createsuperuser

Then, in Django Admin (/admin):

  1. Go to Sites and ensure your domain is correct
  2. Navigate to Social Applications → Add Social Application
  3. Fill in:
    • Provider: Google
    • Name: Google OAuth
    • Client ID: Your Google Client ID (from step 2)
    • Secret Key: Your Google Client Secret (from step 2)
    • Sites: Select your site
  4. Save the configuration

Security Considerations

  • • Always use HTTPS in production for OAuth callbacks
  • • Consider adding CAPTCHA for traditional sign-up to prevent bot registrations
  • • Regularly rotate OAuth client secrets
  • • Monitor for suspicious login patterns

GitHub Authentication Setup

Here's how to set up GitHub authentication alongside Google:

Step 1: Update Django Settings

Add GitHub provider to your config/settings/base.py:

# Add to INSTALLED_APPS
'allauth.socialaccount.providers.github', # Add this line

# Update SOCIALACCOUNT_PROVIDERS
SOCIALACCOUNT_PROVIDERS = {
    'google': {
        'SCOPE': ['profile', 'email'],
        'AUTH_PARAMS': {'access_type': 'online'},
        'APP': {
            'client_id': env('GOOGLE_CLIENT_ID', default=''),
            'secret': env('GOOGLE_CLIENT_SECRET', default=''),
            'key': ''
        }
    },
    'github': {
        'SCOPE': ['user:email'],
        'APP': {
            'client_id': env('GITHUB_CLIENT_ID', default=''),
            'secret': env('GITHUB_CLIENT_SECRET', default=''),
        }
    }
}

Step 2: GitHub OAuth App Setup

  1. Go to GitHub Developer Settings
  2. Click "New OAuth App"
  3. Fill in the application details:
    • Application name: Your app name
    • Homepage URL: http://localhost:8000 (development)
    • Authorization callback URL: http://localhost:8000/accounts/github/login/callback/
    • For production: https://yourdomain.com/accounts/github/login/callback/
  4. Copy the Client ID and Client Secret

Step 3: Add GitHub Credentials to Admin

In Django Admin, create another Social Application:

  • Provider: GitHub
  • Name: GitHub OAuth
  • Client ID: Your GitHub Client ID
  • Secret Key: Your GitHub Client Secret
  • Sites: Select your site

Adding Other Providers

Django-allauth supports many social providers. To add others like Facebook, Twitter, or LinkedIn:

  1. Add the provider to INSTALLED_APPS: 'allauth.socialaccount.providers.github'
  2. Configure provider settings in SOCIALACCOUNT_PROVIDERS
  3. Set up OAuth app with the provider and get credentials
  4. Add the social application in Django admin
  5. Update login template with provider button: {% provider_login_url 'github' %}

Tip: For more detailed social account configurations and a complete list of supported providers, check out the django-allauth guide. The documentation covers advanced features like custom providers, OAuth scopes, and provider-specific settings.

Ready to Deploy?

Before deploying, ensure you have generated the lock file for uv by running:

docker compose -f docker-compose.local.yml run --rm django uv lock

After generating the lock file, check the Deployment Guide for step-by-step instructions on deploying your SaaS to production.

You're All Set!

This provides the basics, now it's your time to build. If you encounter issues, don't hesitate to contact me.

Need Help?

If you encounter any issues while building your SaaS or have questions about implementing features, I'm here to help!

I typically respond within 24 hours. Include details about your development environment and any error messages for faster troubleshooting.