The Bulletproof SaaS Boilerplate is a fully scalable, production-grade foundation for building SaaS applications. It follows best practices, enforces strong security, and integrates essential third-party services to accelerate development and deployment.
- No longer have to hardcode business logic to mock the minimum viable product.
- No relying on 3rd parties for authentication. 100% owenership of your data.
- Standardized API responses.
- Built using battle-tested technologies.
- Testing pre-configured.
- Scalable project structure.
- Global app, header, configs.
- Auth baked in with best practices.
- User activity history.
- System Inactivity Timeout.
- Admin Dashboard
- Financial Dashboard
- OpenAPI Swagger documentation
- Robust Error Handling
{
"status": "success",
"message": "Users fetched successfully",
"meta": {
"totalRecords": 2500,
"limit": 50,
"offset": 100,
"currentPage": 3,
"totalPages": 50,
"sortBy": "createdAt",
"sortOrder": "asc",
"hasNextPage": true,
"hasPreviousPage": true,
"nextOffset": 150,
"previousOffset": 50,
"nextPage": "/api/users?offset=150&limit=50",
"previousPage": "/api/users?offset=50&limit=50"
},
"data": [
{
"id": 101,
"name": "John Doe",
"email": "john.doe@example.com",
"role": "admin",
"createdAt": "2024-02-17T12:34:56Z",
"profile": {
"age": 30,
"location": "New York, USA",
"avatarUrl": "https://example.com/avatars/101.jpg"
}
},
{
"id": 102,
"name": "Jane Smith",
"email": "jane.smith@example.com",
"role": "user",
"createdAt": "2024-01-05T08:12:30Z",
"profile": {
"age": 28,
"location": "Los Angeles, USA",
"avatarUrl": "https://example.com/avatars/102.jpg"
}
}
]
}
/summary/annual# Annual summary
/summary/quarterly # Quarterly summary
/summary/monthly # Monthly summary
/earnings/quarterly earnings # Quarterly earnings
/earnings/monthly # Monthly earnings
/earnings/weekly # Weekly earnings
- Monthly Recurring Revenue
- Average Revenue Per User
- Gross Margin
- Monthly Unique Visitors
- Customer Conversion Rate
- Customer Retention Rate
- Customer Lifetime Value
- Recurring Monthly Revenue
- Churn Rate
- Product Sign Up Rate
- Product Referral Rate Per Influencer
// TODO
Customer Acquisition Cost
Support Ticket Creation Rate
Customer Feedback Rate
πΉ PostgreSQL for: β User Accounts β Emails, passwords (hashed), usernames β Authentication & Authorization β Roles, permissions β Subscriptions & Payments β Stripe/PayPal integration β Orders & Transactions β E-commerce, invoices β Relationships between data β Users & orders, followers, etc. β Reports & Analytics β If data is structured and relational
πΉ MongoDB for: β User Activity Logs β Tracking user logins, errors, analytics β Audit Logs β Storing system events (e.g., password changes) β CMS / Blog Content β Storing articles, comments, etc. β Product Catalog β E-commerce product listings β Notifications / Messages β Storing chat messages, in-app notifications β IoT / Sensor Data β When real-time, unstructured data is needed
πΉ Redis for: β Session Management β Store user sessions, login tokens β Caching β Cache frequently accessed API responses β Rate Limiting β Prevent abuse by limiting API requests β Leaderboard / Ranking Systems β Store real-time game scores β Background Jobs / Queues β Use with BullMQ to manage tasks
Response Time | Rating | Notes |
---|---|---|
Sub-10ms | π Excellent | Unusually fast, likely serving cached content or simple HTML |
10-50ms | π₯ Very Good | Well-optimized SSR with efficient rendering |
50-200ms | β Good | Normal range for SSR, including API/database calls |
200-500ms | Potential slow middleware, DB queries, or API bottlenecks | |
500ms+ | β Bad | Poor performance; needs major fixes |
{
"level": "info", // Log level (e.g., info, warn, error)
"message": "Request Log", // A label for the log entry
"method": "GET", // The HTTP method used for the request
"url": "http://localhost:3000/users?id=123&name=JohnDoe", // The full request URL with query parameters
"headers": {
// HTTP headers sent with the request
"host": "localhost:3000",
"connection": "keep-alive",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36",
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
"accept-encoding": "gzip, deflate, br",
"accept-language": "en-US,en;q=0.9",
"cookie": "sessionId=abc123; userId=456"
},
"query": {
// Parsed query parameters from the URL
"id": "123",
"name": "JohnDoe"
},
"body": {}, // Parsed request body (empty for GET requests)
"cookies": {
// Cookies sent with the request
"sessionId": "abc123",
"userId": "456"
},
"ip": "::1", // The client's IP address
"protocol": "http", // The request protocol (HTTP or HTTPS)
"hostname": "localhost", // The hostname of the server handling the request
"originalUrl": "/users?id=123&name=JohnDoe", // The original request URL
"params": {}, // Route parameters (if applicable)
"secure": false, // Indicates if the request was made over HTTPS
"subdomains": [], // List of subdomains extracted from the request
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36", // User-Agent string from headers
"customHeaders": {
// Custom application headers like request ID or authentication tokens
"X-Request-ID": "abc123456",
"X-Auth-Token": "Bearer [REDACTED]" // Mask sensitive parts
},
"cacheHeaders": {
// Headers related to cache control
"Cache-Control": "no-cache",
"If-None-Match": "W/\"123abc\"",
"If-Modified-Since": "Mon, 05 Jul 2024 07:28:00 GMT"
},
"referrer": "http://example.com", // The referrer URL from which the request originated
"origin": "http://example.com", // The origin of the request
"sessionId": "s12345", // Unique session identifier
"sessionData": {
// Metadata about the session, if available
"user": {
"id": "u123",
"name": "John Doe"
}
},
"userAgentDetails": {
// Parsed User-Agent details (browser, OS, device)
// This can be done using libraries like `useragent` or `ua-parser-js`
"browser": "Chrome",
"os": "Windows 10",
"device": "Desktop"
},
"geoLocation": {
// Estimated geo-location based on IP lookup
// This requires a third-party API (e.g., MaxMind, IPStack).
"country": "US",
"region": "CA",
"city": "San Francisco"
},
"responseStatus": 200, // Response HTTP status code
"responseContentType": "application/json", // Content type of the response
"responseSize": "256", // Size of the response in bytes (if available)
"timestamp": "2024-09-03T12:34:56.789Z" // Timestamp when the log entry was created
}
If your application uses authorization or authentication mechanisms, logging related headers such as Authorization
or Cookie
might be useful. Be cautious about logging sensitive information like tokens or credentials.
authorization: req.get('Authorization'), // Be careful with sensitive info
You might also want to strip out sensitive parts of the authorization header, like:
authorization: req.get('Authorization') ? 'Bearer [REDACTED]' : null,
Depending on your application, you might have custom context or metadata that you want to log, such as a user ID (if the user is authenticated), request ID (if you are tracking requests across microservices), or other application-specific data.
userId: req.user ? req.user.id : null,
requestId: req.get('X-Request-ID'),
- If an error occurs during the request, logging details about the error can be very helpful for debugging. This can include the error message, stack trace, and any relevant request data.
app.use((err, req, res, next) => {
logger.error("Request Error", {
errorMessage: err.message,
errorStack: err.stack,
method: req.method,
url: fullUrl,
body: req.body,
headers: req.headers,
ip: req.ip,
});
next(err);
});
Frontend unit tests are conducting using Jest and Testing Library (formerly known as React Testing Library).
Frontend End-to-end tests are conducted using Playwright with a11y testing with the playwright axe integration.
Frontend performance tested using Google's Lighthouse CLI. The congif file is preset to 90 as a passing score on each metric.
Test users and test data are setup and pre-configured to test user permision, authentication, api resources.
Backend unit tests are conducting using Jest and Supertest.
Integration tests are conducted using the Arrange-Act-Assert pattern.
describe("User Service", () => {
it("Should create a user given correct data", async () => {
// 1. Arrange - prepare the data, create any objects you need
const mockUser = {
// ...
};
const userService = createUserService(mockLogger, mockQueryBuilder);
// 2. Act - execute the logic that you're testing
const result = userService.create(mockUser);
// 3. Assert - validate the expected result
expect(mockLogger).toHaveBeenCalled();
expect(mockQueryBuilder).toHaveBeenCalled();
expect(result).toEqual(/** ... */);
});
});
Load tests are ran using Artillery. See the artillery.yml file.
git clone https://github.com/xxxxx/xxxxxx
cd xxxxx
command
command
command
If you'd like to contribute, please fork the repository and open a pull request to the main
branch.