### Install Project Dependencies Source: https://saasrock.com/docs/articles/quick-start Installs all necessary packages for the project using npm. This is the first step in setting up the development environment. ```bash npm install ``` -------------------------------- ### Copy Environment Configuration Source: https://saasrock.com/docs/articles/quick-start Duplicates the example environment file to create a new configuration file for the project. This file will store sensitive and environment-specific settings. ```bash cp .env.example .env ``` -------------------------------- ### Start Development Server Source: https://saasrock.com/docs/articles/quick-start Launches the SaaS-Rock application in development mode. After running this command, the application will be accessible at localhost:3000. ```bash npm run dev ``` -------------------------------- ### Manually Push and Seed Database Source: https://saasrock.com/docs/articles/quick-start Provides alternative commands to push database changes and seed the database manually if the initial migration fails. This is a fallback option for database setup. ```bash npx prisma db push npx prisma db seed ``` -------------------------------- ### Employee API Endpoints Source: https://saasrock.com/docs/articles/quick-start-v0-2-6 This section details the available endpoints for interacting with employee data, including GET, POST, PUT, and DELETE operations. ```APIDOC ## GET /api/employees ### Description Retrieves a list of all employees. ### Method GET ### Endpoint /api/employees ### Parameters #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - **employees** (array) - A list of employee objects. #### Response Example ```json { "employees": [ { "id": "1", "name": "John Doe", "email": "john.doe@example.com" } ] } ``` ## GET /api/employees/:id ### Description Retrieves a specific employee by their ID. ### Method GET ### Endpoint /api/employees/:id ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the employee to retrieve. #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - **employee** (object) - The employee object. #### Response Example ```json { "employee": { "id": "1", "name": "John Doe", "email": "john.doe@example.com" } } ``` ## POST /api/employees ### Description Creates a new employee. ### Method POST ### Endpoint /api/employees ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **name** (string) - Required - The name of the employee. - **email** (string) - Required - The email address of the employee. ### Request Example ```json { "name": "Jane Smith", "email": "jane.smith@example.com" } ``` ### Response #### Success Response (200) - **message** (string) - A success message. - **employee** (object) - The newly created employee object. #### Response Example ```json { "message": "Employee created successfully", "employee": { "id": "2", "name": "Jane Smith", "email": "jane.smith@example.com" } } ``` ## PUT /api/employees/:id ### Description Updates an existing employee. ### Method PUT ### Endpoint /api/employees/:id ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the employee to update. #### Query Parameters None #### Request Body - **name** (string) - Optional - The updated name of the employee. - **email** (string) - Optional - The updated email address of the employee. ### Request Example ```json { "name": "Jane Doe", "email": "jane.doe.updated@example.com" } ``` ### Response #### Success Response (200) - **message** (string) - A success message. - **employee** (object) - The updated employee object. #### Response Example ```json { "message": "Employee updated successfully", "employee": { "id": "1", "name": "Jane Doe", "email": "jane.doe.updated@example.com" } } ``` ## DELETE /api/employees/:id ### Description Deletes an employee by their ID. ### Method DELETE ### Endpoint /api/employees/:id ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the employee to delete. #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - **message** (string) - A success message. #### Response Example ```json { "message": "Employee deleted successfully" } ``` ``` -------------------------------- ### Clean Install Project Dependencies Source: https://saasrock.com/docs/articles/quick-start Resets the project's dependencies by clearing the npm cache, removing existing lock files and node modules, and then reinstalling everything. This is useful for resolving dependency conflicts. ```bash npm cache clean --force rm -rf package-lock.json node_modules npm cache verify npm install ``` -------------------------------- ### Create and Seed Database Source: https://saasrock.com/docs/articles/quick-start Generates database migrations and seeds the database with initial data. This command is crucial for setting up the database schema and populating it with default content. ```bash npx prisma migrate dev --name init npx prisma db seed ``` -------------------------------- ### Seed Database (Prisma) Source: https://saasrock.com/docs/articles/quick-start-v0-2-6 Applies database migrations and seeds the database with initial data using Prisma. This command ensures the database is ready for use with default configurations. ```bash npx prisma migrate dev --name init ``` -------------------------------- ### Example Markdown Content Source: https://saasrock.com/docs/articles/publish-a-blog-post This snippet provides an example of markdown content that can be used for a blog post. It includes a main title, a subtitle, and a paragraph of lorem ipsum text, along with a list. ```markdown # Title ## Subtitle Lorem ipsum... ``` ```markdown * Item 1 * _Item 2_ * `**Item 3** ` ``` -------------------------------- ### Configure Postmark From Email Source: https://saasrock.com/docs/articles/quick-start-v0-2-6 Sets the Postmark sender signature or domain in the environment variables for transactional emails. This defines the 'from' address for emails sent by the application. ```bash # Set the POSTMARK_FROM_EMAIL env variable ``` -------------------------------- ### Configure Stripe Secret Key Source: https://saasrock.com/docs/articles/quick-start-v0-2-6 Sets the Stripe secret key in the environment variables to enable subscription plan functionality. The application needs to be restarted after setting this variable. ```bash # Set the STRIPE_SK env variable and restart the app. ``` -------------------------------- ### Example Workflow Execution Output Source: https://saasrock.com/docs/articles/workflows A sample output from a 'GPT Simulator' workflow, showcasing the structure with parameters, session, variables, and outputs from 'waitForInput', 'if', and 'gpt' blocks. ```json { "$params": {}, "$session": { "tenant": null, "user": null }, "$vars": { "gptModel": "gpt-3.5-turbo" }, "waitForInput": { "input": "Hi" }, "if": { "condition": false, "expression": "{{waitForInput.input}} Equals bye" }, "gpt": { "result": "Hello! How can I assist you today?" } } ``` -------------------------------- ### Configure Postmark Email Server Token Source: https://saasrock.com/docs/articles/quick-start-v0-2-6 Sets the Postmark server API token in the environment variables for transactional emails. This is required for sending emails from the application. ```bash # Set the POSTMARK_SERVER_TOKEN env variable ``` -------------------------------- ### Set Up New Widget Project with SaasRock Source: https://saasrock.com/docs/articles/widget-based-saas-apps These commands demonstrate the process of creating a new widget project by cloning the `saasrock-widget` repository, installing dependencies, and configuring environment variables. The `.env` file is crucial for setting the API URL and widget ID. ```bash git clone https://github.com/AlexandroMtzG/saasrock-widget.git cd saasrock-widget npm i cp .env.example .env code . VITE_API_URL=http://localhost:3000 # your saasrock instance VITE_WIDGET_ID={YOUR_CREATED_WIDGET_ID} ``` -------------------------------- ### package.json Scripts for Remix Build and Start Source: https://saasrock.com/docs/articles/deploy-remix-to-aws-lightsail-containers-with-docker This snippet shows the relevant scripts within a Remix application's package.json file. It defines the commands for building the application using Vite and starting the production server using 'remix-serve'. These scripts are crucial for both local development and Docker image construction. ```json { "...": "...", "scripts": { "build": "remix vite:build", "start": "remix-serve ./build/index.js" }, "dependencies": { "...": "..." }, "devDependencies": { "...": "..." } } ``` -------------------------------- ### Dockerfile for Remix App Source: https://saasrock.com/docs/articles/deploy-remix-to-aws-lightsail-containers-with-docker This Dockerfile sets up a production environment for a Remix application. It installs Node.js, dependencies, generates Prisma schemas, builds the Remix app, and copies necessary files for runtime. It uses multi-stage builds for efficiency. The final image runs the application using a start script. ```dockerfile #!/bin/bash FROM --platform=linux/amd64 node:18-bookworm-slim as base ENV NODE_ENV production RUN apt-get update && apt-get install -y openssl FROM base as deps WORKDIR /myapp ADD package.json ./ RUN npm install --production=false --legacy-peer-deps FROM base as production-deps WORKDIR /myapp COPY --from=deps /myapp/node_modules /myapp/node_modules ADD package.json ./ RUN npm prune --production --legacy-peer-deps FROM base as build WORKDIR /myapp COPY --from=deps /myapp/node_modules /myapp/node_modules ADD prisma . RUN npx prisma generate ADD . . RUN npm run build FROM base ENV PORT="8080" ENV NODE_ENV="production" WORKDIR /myapp COPY --from=production-deps /myapp/node_modules /myapp/node_modules COPY --from=build /myapp/node_modules/.prisma /myapp/node_modules/.prisma COPY --from=build /myapp/build /myapp/build COPY --from=build /myapp/public /myapp/public COPY --from=build /myapp/package.json /myapp/package.json COPY --from=build /myapp/start.sh /myapp/start.sh COPY --from=build /myapp/prisma /myapp/prisma RUN chmod +x /myapp/start.sh CMD ["./start.sh"] ``` -------------------------------- ### Page Blocks for Visual Page Building (TypeScript) Source: https://context7.com/context7/saasrock/llms.txt This snippet demonstrates the structure and usage of the page block system for creating visual content like landing pages and documentation. It includes an example of a custom page configuration with various block types, supported block types, and instructions for editing and SEO configuration. ```typescript // Page configuration const customPage = { slug: "features", title: "Our Features", published: true, isPublic: true, blocks: [ { type: "banner", content: { text: "Limited Time Offer - 40% Off", position: "top", style: "warning" } }, { type: "header", content: { logo: "/logo.svg", links: [ { title: "Features", href: "/features" }, { title: "Pricing", href: "/pricing" }, { title: "Blog", href: "/blog" } ] } }, { type: "hero", content: { topText: "The Complete SaaS Solution", headline: "Build Your SaaS in Days, Not Months", subheadline: "Everything you need to launch a production-ready SaaS", cta: { primary: { text: "Start Free Trial", href: "/register" }, secondary: { text: "View Demo", href: "/demo" } } } }, { type: "features", content: { title: "Everything You Need", items: [ { title: "Entity Builder", description: "No-code database with autogenerated API", icon: "database" }, { title: "Workflow Engine", description: "Automate complex business logic", icon: "workflow" } ] } }, { type: "pricing", content: { title: "Simple, Transparent Pricing" } } ] }; // Supported block types (20+ types): // - banner, header, footer // - hero, features, testimonials // - logo-clouds, gallery, video // - community, faq, newsletter // - pricing, blog-posts, blog-post // - content (HTML/Markdown) // Edit mode // Add ?edit=true to URL to enable block editing // /features?edit=true // Override default pages // Navigate to /admin/settings/pages // Edit blocks, save changes to database // SEO configuration per page { "title": "Features - SaasRock", "description": "Discover all features", "image": "/og-image.png", "keywords": ["saas", "features", "remix"] } // Create new page // POST /admin/settings/pages/new { "slug": "about", "title": "About Us", "published": true, "isPublic": true } ``` -------------------------------- ### Configure package.json for Prisma Generation Source: https://saasrock.com/docs/articles/deploy-remix-to-vercel This snippet shows how to add a 'postinstall' script to your package.json file. This ensures that the Prisma Client is generated after package installation, which is crucial for compatibility when deploying to Vercel. This is a common requirement for Node.js applications using Prisma. ```json { "scripts": { "postinstall": "prisma generate" } } ``` -------------------------------- ### Blogging Platform Post Structure and Management (TypeScript) Source: https://context7.com/context7/saasrock/llms.txt Defines the structure for a blog post, including SEO fields, author details, content, and metadata. It also outlines API routes for managing posts and examples of post URLs. Dependencies: None explicitly mentioned, assumed to be part of a larger TypeScript project. ```typescript // Blog post structure const blogPost = { // SEO fields title: "10 Tips for Building SaaS", slug: "10-tips-building-saas", description: "Learn the best practices for building SaaS applications", image: "/blog/saas-tips.jpg", // Details author: { id: "author-123", name: "Alex Martinez", avatar: "/avatars/alex.jpg" }, category: "Tutorials", tags: ["saas", "development", "best-practices"], publishedAt: "2024-01-15T10:00:00Z", readingTime: 8, // minutes published: true, // Content content: "# Introduction\n\nBuilding a SaaS...", contentType: "markdown" // or "wysiwyg" }; // Create blog post // POST /admin/blog/posts { "title": "New Post", "slug": "new-post", "content": "Post content here", "contentType": "markdown", "published": false } // Blog routes // List posts: /blog // View post: /blog/:slug // Manage posts: /admin/blog/posts // Blog dashboard features // - Draft/publish management // - SEO preview // - Reading time calculation // - Category and tag organization // - Analytics per post // Example blog post URL // https://yourdomain.com/blog/10-tips-building-saas ``` -------------------------------- ### start.sh for Remix Application Source: https://saasrock.com/docs/articles/deploy-remix-to-aws-lightsail-containers-with-docker A simple shell script to start the Remix application. It ensures compatibility across different operating systems by using '#!/bin/sh'. This script is executed by the Docker container's CMD instruction. ```shell #!/bin/sh npm run start ``` -------------------------------- ### Implement Caching with cachified and Redis in TypeScript Source: https://context7.com/context7/saasrock/llms.txt This section demonstrates how to implement a caching system using the 'cachified' library with Redis as the cache store. It outlines cache key structures, provides examples for inspecting and clearing cache entries via API endpoints, and shows a practical example of using 'cachified' to fetch tenant data, reducing database load. ```typescript // Cache configuration using cachified // Supports lru-cache, redis, and more // https://github.com/epicweb-dev/cachified // Cache management // Navigate to /admin/settings/cache // Cache keys structure const cacheKeys = { page: "page:slug", appConfiguration: "appConfiguration", tenant: "tenant:id", tenantBySlug: "tenant:slug", tenantSimple: "tenantSimple:id", user: "user:id", roles: "roles:type", userRole: "userRole:userId:tenantId", tenantSubscription: "tenantSubscription:tenantId", tenantIdOrSlug: "tenantIdOrSlug:tenant", kbArticle: "kb-article:${knowledgeBaseId}:${slug}:${language}" }; // Cache inspection example // GET /admin/settings/cache?key=appConfiguration { "key": "appConfiguration", "value": { "app": { "name": "SaasRock", "version": "0.9.5" }, "subscription": { "required": false }, "portals": { "enabled": true } }, "ttl": 3600, "createdAt": "2024-01-15T10:30:00Z" } // Clear specific cache // POST /admin/settings/cache/clear { "key": "tenant:acme-corp" } // Clear all cache // POST /admin/settings/cache/clear-all // Cache usage in code import { cachified } from "@epic-web/cachified"; async function getTenant(id: string) { return cachified({ key: `tenant:${id}`, cache: redisCache, ttl: 60 * 60, // 1 hour getFreshValue: () => db.tenant.findUnique({ where: { id } }) }); } ``` -------------------------------- ### Affiliate Program Rewardful Configuration (TypeScript) Source: https://context7.com/context7/saasrock/llms.txt Illustrates the configuration for integrating Rewardful, an affiliate marketing platform, within the application's server-side configuration. It details the necessary API key and URL setup. Dependencies: `AppConfiguration` type. ```typescript // Rewardful configuration in appConfiguration.db.server.ts const conf: AppConfiguration = { affiliates: { rewardful: { url: "https://yourdomain.getrewardful.com/signup", apiKey: "rw_live_abc123xyz..." } } }; // Setup steps: // 1. Create Rewardful account // 2. Configure in app/utils/db/appConfiguration.db.server.ts // 3. Set affiliates.rewardful.url (signup URL) // 4. Set affiliates.rewardful.apiKey (from Rewardful settings) // 5. Create campaign in Rewardful dashboard // 6. Add affiliates // 7. Test with affiliate link + subscription // Affiliate link example // https://yourdomain.getrewardful.com/signup?via=affiliate-code // Registration flow with affiliate tracking // 1. User clicks affiliate link // 2. Cookie/localStorage stores referral ID // 3. User subscribes to plan // 4. Stripe customer created with metadata // 5. Rewardful tracks commission // Stripe customer metadata { "customerId": "cus_abc123", "metadata": { "rewardful_referral": "ref_xyz789", "rewardful_affiliate": "aff_456" } } // Commission tracking // View in Rewardful dashboard: // - Total referrals // - Conversion rate // - Commission earned // - Payment status ``` -------------------------------- ### Autogenerated REST API Operations (Bash) Source: https://context7.com/context7/saasrock/llms.txt Demonstrates how to interact with the autogenerated REST API for entity management using cURL. It covers GET, POST, PUT, and DELETE operations for entity rows, including examples for retrieving all rows, creating a new row, getting a specific row, updating a row, and deleting a row. The response format for a successful operation is also shown. API documentation endpoints like Swagger and Postman collections are also noted. ```bash # Get all entity rows curl -X GET https://yourdomain.com/api/employees \ -H "X-Api-Key: your-api-key" # Create new entity row curl -X POST https://yourdomain.com/api/employees \ -H "X-Api-Key: your-api-key" \ -H "Content-Type: application/json" \ -d '{ "name": "John Doe", "email": "john@example.com", "department": "Engineering", "salary": 85000 }' # Get specific entity row curl -X GET https://yourdomain.com/api/employees/emp-001 \ -H "X-Api-Key: your-api-key" # Update entity row curl -X PUT https://yourdomain.com/api/employees/emp-001 \ -H "X-Api-Key: your-api-key" \ -H "Content-Type: application/json" \ -d '{ "salary": 90000, "department": "Senior Engineering" }' # Delete entity row curl -X DELETE https://yourdomain.com/api/employees/emp-001 \ -H "X-Api-Key: your-api-key" # Response format (success) { "success": true, "data": { "id": "emp-001", "name": "John Doe", "email": "john@example.com", "department": "Engineering", "salary": 85000, "createdAt": "2024-01-15T10:30:00Z" } } # Swagger documentation available at # GET /api/docs # OpenAPI specification # GET /swagger # Postman collection # GET /postman_collection.json ``` -------------------------------- ### Entity Builder Configuration (TypeScript) Source: https://context7.com/context7/saasrock/llms.txt Provides a TypeScript example for configuring a custom entity using SaasRock's Entity Builder. It defines the entity's name, slug, prefix, API enablement, and a list of properties with their types, validation rules, and display settings. It also lists supported property types and notes the autogenerated routes for the entity. ```typescript // Entity configuration example // Navigate to /admin/settings/entities to create via UI // Entity structure const employeeEntity = { name: "Employee", slug: "employee", prefix: "EMP", hasApi: true, properties: [ { name: "name", title: "Full Name", type: "TEXT", isRequired: true, showInCreate: true }, { name: "email", title: "Email", type: "TEXT", isRequired: true, pattern: "email", showInCreate: true }, { name: "salary", title: "Annual Salary", type: "NUMBER", isRequired: false, minimum: 0, showInCreate: true }, { name: "hireDate", title: "Hire Date", type: "DATE", isRequired: true, showInCreate: true }, { name: "department", title: "Department", type: "SELECT", options: ["Engineering", "Sales", "Marketing", "HR"], showInCreate: true } ] }; // Supported property types: // TEXT, NUMBER, DATE, BOOLEAN, SELECT, MULTI_SELECT, MULTI_TEXT // MEDIA, ENTITY (relations), NUMBER_RANGE, DATE_RANGE // MONACO_EDITOR, WYSIWYG // Autogenerated routes: // List view: /app/:tenant/employees // Create: /app/:tenant/employees/new // Details: /app/:tenant/employees/:id // API: /api/employees/* // API usage logs available at: // Admin: /admin/api/logs // Tenant: /app/:tenant/api/logs ``` -------------------------------- ### Troubleshoot Container Permissions Source: https://saasrock.com/docs/articles/deploy-remix-to-aws-lightsail-containers-with-docker This section addresses the 'permission denied' error when starting a container. It shows how to grant execute permissions to a script (e.g., start.sh) using chmod, rebuilding the Docker image, and running the container with the correct permissions. ```bash chmod +x start.sh docker build -t saasrock-dev . docker run -p 8080:8080 --rm --env-file .env saasrock-dev:latest ``` -------------------------------- ### API Rate Limiting Configuration and Usage (TypeScript, Shell) Source: https://context7.com/context7/saasrock/llms.txt This snippet details the configuration of API rate limiting, including default limits, plan-specific overrides, and cache key generation. It also shows how to handle rate limit exceeded responses and provides examples for testing rate limits using curl and viewing rate limit logs. ```typescript // Default rate limits in rateLimitService.ts const DEFAULT_RATE_LIMIT_PER_MINUTE = 60; const DEFAULT_RATE_LIMIT_PER_SECOND = 5; function getCacheKey(apiKey: string, period: string, timestamp: number): string { return `rateLimit:${apiKey}:${period}:${timestamp}`; } // Rate limit override via plan features const planWithCustomLimits = { features: [ { name: "rate-limit-per-minute", value: 120 }, { name: "rate-limit-per-second", value: 10 } ] }; // Rate limit exceeded response // Status: 429 Too Many Requests { "error": "Rate limit exceeded", "message": "Too many requests per second", "retryAfter": 1, "limit": 5, "remaining": 0 } // Cache keys created per request: // rateLimit:apiKeyId:second:timestamp (TTL: 60s) // rateLimit:apiKeyId:minute:timestamp (TTL: 1s) ``` ```shell // Testing rate limits curl -X GET https://yourdomain.com/api/usage \ -H "X-Api-Key: your-api-key" \ --retry 10 --retry-delay 1 // View rate limit logs // Admin: /admin/api/logs // Tenant: /app/:tenant/api/logs ``` -------------------------------- ### Configure Git Remotes for SaasRock Upgrades Source: https://saasrock.com/docs/articles/releases These commands configure your local Git repository to track the SaasRock releases. It involves removing the default 'origin' remote and adding your private repository as the new 'origin', then adding the SaasRock repository as an 'upstream' remote. This setup allows you to pull updates from SaasRock without affecting your own development branch directly. ```bash git remote remove origin git remote add origin {YOUR_GITHUB_URL} ``` ```bash git remote add upstream https://github.com/AlexandroMtzG/saasrock.git ``` ```bash git remote add upstream https://github.com/AlexandroMtzG/saasrock-pro.git ``` ```bash git remote set-url --push upstream no_push ``` ```bash git remote -v ``` -------------------------------- ### Override Vercel Build Command for Legacy Peer Dependencies Source: https://saasrock.com/docs/articles/deploy-remix-to-vercel This example demonstrates how to override the default Vercel build command. It's specifically useful when using React canary versions that might require installing with '--legacy-peer-deps' to resolve dependency conflicts during the build process on Vercel. ```bash npm install --legacy-peer-deps ``` -------------------------------- ### Deploy Application to Fly.io Source: https://saasrock.com/docs/articles/deploy-to-fly-io The command to deploy your application to Fly.io. Before running this, ensure that the 'postinstall' script in your package.json does not contain 'prisma generate' to avoid deployment issues. ```bash fly deploy ``` -------------------------------- ### Track Credit Usage (TypeScript) Source: https://saasrock.com/docs/articles/tutorial-credits-management Demonstrates how to use the `CreditsServer.create` function to log credit usage for a specific tenant and user. It requires the tenant ID, user ID, credit type, and the object ID associated with the usage. ```typescript await CreditsServer.create({ tenantId, userId, type: creditType, // "credit-project-creation" or "credit-task-creation" objectId: `/app/${tenantId}/{createdResourcePath}`, }); ``` -------------------------------- ### Grant Permissions in Dockerfile Source: https://saasrock.com/docs/articles/deploy-remix-to-aws-lightsail-containers-with-docker This Dockerfile snippet demonstrates how to grant execute permissions to a script within the image during the build process. This ensures the script can be run when the container starts. ```dockerfile ... RUN chmod +x /myapp/start.sh ENTRYPOINT [ "./start.sh" ] ``` -------------------------------- ### Get Container Service URL Source: https://saasrock.com/docs/articles/deploy-remix-to-aws-lightsail-containers-with-docker This command retrieves the public URL for your deployed container service on AWS Lightsail. Once the deployment is complete, this URL will point to your running application. ```bash aws lightsail get-container-services --region us-east-1 --query "containerServices[].url" ``` -------------------------------- ### Open Prisma Studio Source: https://saasrock.com/docs/articles/extend-existing-models This command launches Prisma Studio, a GUI tool for browsing and manipulating your database. It's useful for inspecting the `JobPosts` model and its associated rows. ```bash npx prisma studio ``` -------------------------------- ### Subscription Management Pricing Plan Configuration (TypeScript) Source: https://context7.com/context7/saasrock/llms.txt Illustrates the structure for configuring a subscription pricing plan, including plan details, billing periods, prices, and feature limits. It details various feature limit types and available billing periods. ```typescript // Pricing plan configuration // Navigate to /admin/settings/pricing const subscriptionPlan = { title: "Professional", description: "For growing teams", badge: "POPULAR", prices: [ { billingPeriod: "MONTHLY", price: 49.99, currency: "USD" }, { billingPeriod: "YEARLY", price: 499.99, currency: "USD" } ], features: [ { name: "users", title: "Team Members", type: "MAX", value: 10 }, { name: "employees", title: "Employee Records", type: "MONTHLY", value: 100, accumulated: false }, { name: "prioritySupport", title: "Priority Support", type: "INCLUDED" }, { name: "apiAccess", title: "API Access", type: "INCLUDED" } ] }; // Feature limit types: // - MAX: Maximum allowed (e.g., 10 team members) // - MONTHLY: Monthly quota (e.g., 100 API calls/month) // - INCLUDED: Boolean feature flag // - NOT_INCLUDED: Feature not available // - UNLIMITED: No limits // Subscription API endpoints // Get current subscription: GET /app/:tenant/subscription // Upgrade/downgrade: POST /app/:tenant/subscription/update // Cancel subscription: POST /app/:tenant/subscription/cancel // Pricing models supported: // 1. Flat-rate: Fixed monthly/yearly fee // 2. Per-seat: Price per user/seat // 3. Usage-based: Pay per usage metric // 4. One-time: Single payment // Billing periods: // MONTHLY, YEARLY, QUARTERLY, SEMI_ANNUALLY ``` -------------------------------- ### Get AWS Lightsail Container Service Status Command Source: https://saasrock.com/docs/articles/deploy-remix-to-aws-lightsail-containers-with-docker This AWS CLI command retrieves the status of a specific container service on Amazon Lightsail. It targets the 'saasrock-dev-service' in the 'us-east-1' region and queries for the 'state' of the container services. ```bash aws lightsail get-container-services --region us-east-1 --service-name saasrock-dev-service --query "containerServices[].state" ``` -------------------------------- ### Update Task API Request (JSON Body) Source: https://saasrock.com/docs/articles/use-the-custom-entity-api This JSON body is used to update an existing task via a PUT request. Currently, it only supports updating the task's name. The URL must contain the specific task ID to be updated. ```json { "name": "New task name" } ``` -------------------------------- ### Create Fly.io App using Fly CLI Source: https://saasrock.com/docs/articles/deploy-to-fly-io Command to create a new application on Fly.io using the fly CLI. Replace 'YOUR_APP_NAME' with the desired name for your application. ```bash fly apps create YOUR_APP_NAME ``` -------------------------------- ### Workflow Engine API Execution and Context Structure (TypeScript) Source: https://context7.com/context7/saasrock/llms.txt Demonstrates how to execute a workflow via API and illustrates the structure of the workflow context, including parameters, session data, variables, and conditional logic. It also shows a sample JSON schema for input validation. ```typescript // Workflow execution via API curl -X POST https://yourdomain.com/api/workflows/run/workflow-id \ -H "X-Api-Key: your-api-key" \ -H "Content-Type: application/json" \ -d '{ "id": 10, "action": "approve" }' // Workflow context structure { "$params": { "id": 10, "action": "approve" }, "$session": { "tenant": { "id": "tenant-123", "name": "Acme Corp", "slug": "acme" }, "user": { "id": "user-456", "email": "admin@acme.com" } }, "$vars": { "gptModel": "gpt-4", "maxRetries": 3 }, "if": { "condition": true, "expression": "{{$params.action}} Equals approve" }, "httpRequest": { "status": 200, "data": { "approved": true } }, "gpt": { "result": "Request approved successfully" } } // Input validation using Ajv JSON schema { "type": "object", "properties": { "id": { "type": "number" }, "action": { "type": "string", "enum": ["approve", "reject", "pending"] } }, "required": ["id", "action"] } ``` -------------------------------- ### Create Task API Request (JSON Body) Source: https://saasrock.com/docs/articles/use-the-custom-entity-api This is the JSON payload required to create a new task via the API. It includes project ID, order, name, due date, priority, completion status, and attachments. Ensure the 'project' ID is valid. ```json { "project": "cl3tlewvp2739e7hsz7apld93", "order": 2, "name": "Task 2", "dueDate": "2022-12-31", "priority": "High", "completed": false, "attachments[]": [ { "name": "My image.png", "type": "image/png", "title": "My image", "file": "https://via.placeholder.com/1000x500.png?text=My%20image" } ] } ``` -------------------------------- ### Configure fly.toml for Fly.io Deployment Source: https://saasrock.com/docs/articles/deploy-to-fly-io This snippet shows how to configure the 'app' name and 'primary_region' in the fly.toml file. The primary region should align with your database's region for optimal performance. Ensure you replace 'YOUR_APP_NAME' with your actual application name. ```toml app = "YOUR_APP_NAME" ... primary_region = "iad" ``` -------------------------------- ### Implement Analytics Tracking in TypeScript Source: https://context7.com/context7/saasrock/llms.txt This code demonstrates how to track user activity, including page views and custom events, using an in-built analytics system or SimpleAnalytics integration. It shows examples of sending POST requests to '/api/analytics/page-views' and '/api/analytics/events' with relevant data. The analytics dashboard is accessible at '/admin/analytics'. ```typescript // Analytics configuration // Enterprise edition only // Alternative: SimpleAnalytics integration // Track page view fetch("/api/analytics/page-views", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ url: window.location.href, referrer: document.referrer, portalId: "portal-123" }) }); // Track custom event fetch("/api/analytics/events", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: "button_clicked", category: "engagement", properties: { buttonId: "cta-primary", page: "/pricing" } }) }); // Analytics dashboard // View at: /admin/analytics // Public demo: https://saasrock.com/analytics // Tracked metrics: // - Unique visitors // - Page views // - Custom events // - Portal-specific analytics (B2B2C) // Portal analytics integration // Portal server -> Base server API call // POST /api/analytics/page-views ``` -------------------------------- ### Report Usage for Billing (TypeScript) Source: https://saasrock.com/docs/articles/tutorial-credits-management Illustrates how to report usage of specific units to a billing system, like Stripe. This function is called after an action that consumes a unit, ensuring accurate billing based on consumption. ```typescript // await CreditsServer.create({ ... reportUsage(tenantId, UNIT_PROJECT_CREDITS.name); ``` -------------------------------- ### JSON Schema Validation Example Source: https://saasrock.com/docs/articles/workflows This JSON schema is used with the Ajv validator for the Manual Trigger in SaaSrock workflows. It defines the expected structure and types for the input data, ensuring that workflows receive correctly formatted data. The schema specifies that the input must be an object with a required 'id' property of type number. ```json { "type": "object", "properties": { "id": { "type": "number" } }, "required": [ "id" ] } ``` -------------------------------- ### Configure B2B2C Portals with TypeScript Source: https://context7.com/context7/saasrock/llms.txt This snippet shows how to configure B2B2C portals using TypeScript, including settings for enabled features, domain providers, and metadata. It also demonstrates Stripe Connect integration for subscription payments and defines portal access patterns via subdomains or custom domains. Environment variables and Git workflow for managing the portal project are also included. ```typescript // Portal configuration in appConfiguration.db.server.ts const conf: AppConfiguration = { portals: { enabled: true, forTenants: true, pricing: true, analytics: false, domains: { enabled: true, provider: "fly", portalAppId: "saasrock-portal", records: { A: "66.241.125.25", AAAA: "2a09:8280:1::31:5dc2:0" } }, metadata: [ { name: "layout", title: "Layout", type: "select", required: true, defaultValue: "hero", options: [ { name: "Classic", value: "classic" }, { name: "Hero", value: "hero" } ] } ] } }; // Environment configuration // .env PORTAL_SERVER_URL=http://localhost:3001 // Architecture: // Server 1 (Base): Marketing, Admin, Tenant dashboard // - /admin, /app/:tenant, /pricing // Server 2 (Portal): Consumer application // - *.portal.yourdomain.com // Portal access patterns: // 1. Subdomain: customer1.portal.yourdomain.com // 2. Custom domain: www.customer-domain.com // Stripe Connect integration // In PortalStripe.server.ts const createCheckoutSession = { mode: "subscription", payment_intent_data: { application_fee_percent: 10 // Your platform fee }, stripe_account: portal.stripeAccountId // Tenant's connected account }; // Portal metadata usage const portal = { subdomain: "acme-directory", title: "Acme Directory", metadata: { layout: "hero", theme: "modern", customColor: "#3B82F6" } }; // Cache management // Base server updates portal -> calls /api/cache on portal server // Portal server tracks analytics -> calls /api/analytics/page-views on base server // Git workflow for portals // In portal project: git remote add base https://github.com/your-saasrock-project git remote add upstream https://github.com/AlexandroMtzG/saasrock-portal // Pull shared components from base git fetch base git merge base/main // Portal-specific routes // /portal/:subdomain - Portal home // /portal/:subdomain/login - Portal authentication // /portal/:subdomain/register - Portal user registration ``` -------------------------------- ### Tenant Subscription Product Model Source: https://saasrock.com/docs/articles/prisma-models Defines the TenantSubscriptionProduct model, which links tenant subscriptions to products and pricing details. It includes relations to Tenant, SubscriptionPrice, and SubscriptionUsageBasedPrice, and a list of usage records. ```Prisma Schema model TenantSubscriptionProduct { tenantSubscriptionProductId String subscriptionPriceId String? subscriptionPrice SubscriptionPrice? @relation(fields: [subscriptionPriceId], references: [id]) subscriptionUsageBasedPriceId String? subscriptionUsageBasedPrice SubscriptionUsageBasedPrice? @relation(fields: [subscriptionUsageBasedPriceId], references: [id]) usageRecords TenantSubscriptionUsageRecord[] tenantSubscriptionProduct Tenant @relation(fields: [tenantSubscriptionProductId], references: [id], onDelete: Cascade) } ``` -------------------------------- ### Set Environment Secrets for Fly.io App Source: https://saasrock.com/docs/articles/deploy-to-fly-io This command sets essential environment secrets for your Fly.io application. It includes variables like database credentials, API keys, and domain names. Remember to replace 'TODO' placeholders with your actual values or remove unused variables. The `--app` flag specifies the target application. ```bash flyctl secrets set APP_NAME=YOUR_APP_NAME \ SERVER_URL=https://YOUR_APP_NAME.fly.dev \ DOMAIN_NAME=YOUR_APP_NAME.fly.dev \ DATABASE_URL=postgres://{USER}:{PASSWORD}@{HOST}:{PORT}/{DATABASE} \ API_ACCESS_TOKEN=1234567890 \ SESSION_SECRET=abc123 \ JWT_SECRET=abc123 \ SUPABASE_API_URL=TODO \ SUPABASE_KEY=TODO \ SUPABASE_ANON_PUBLIC_KEY=TODO \ STRIPE_SK=TODO \ SUPPORT_EMAIL=TODO \ POSTMARK_SERVER_TOKEN=TODO \ POSTMARK_FROM_EMAIL=TODO \ --app YOUR_APP_NAME ``` -------------------------------- ### Build and Embed Widget Script for SaasRock Source: https://saasrock.com/docs/articles/widget-based-saas-apps This command builds the widget project, generating an `embed.js` file in the `dist` directory. The generated script should be copied into the `public` folder of your SaasRock instance. The provided HTML snippet shows how to embed this script into the `
` of your `root.tsx` file. ```bash npm run build ``` ```html ``` -------------------------------- ### Limit Usage Based on Credits (TypeScript) Source: https://saasrock.com/docs/articles/tutorial-credits-management Shows how to check if a user has reached their credit limit using the `getPlanFeatureUsage` helper function. If the feature is not enabled, an error is thrown, preventing further action. ```typescript const creditsFeature = await getPlanFeatureUsage(tenantId, "credits"); if (creditsFeature && !creditsFeature.enabled) { throw Error(t(creditsFeature.message)) } ``` -------------------------------- ### Enable Widgets Configuration in SaasRock Source: https://saasrock.com/docs/articles/widget-based-saas-apps This snippet shows how to enable widgets by modifying the `app/utils/db/appWidgetsConfiguration.db.server.ts` file. It involves setting the `enabled` property to `true` within the `WidgetsConfiguration` object. ```typescript export function getWidgetsConfiguration({ t }: { t: TFunction }): WidgetsConfiguration { const conf: WidgetsConfiguration = { enabled: true, ... ``` -------------------------------- ### Scale VM for Fly.io App Source: https://saasrock.com/docs/articles/deploy-to-fly-io Optional command to scale the virtual machine for your Fly.io application. Adjusting the VM size can help prevent crashes due to insufficient resources. Replace 'YOUR_APP_NAME' with your application's name. ```bash fly scale vm shared-cpu-2x --app YOUR_APP_NAME ``` -------------------------------- ### Define MetricLog Data Model Source: https://saasrock.com/docs/articles/prisma-models Defines the MetricLog model for recording performance metrics. It includes details like environment, type (loader/action), route, URL, function, duration, and associated user and tenant. Dependencies include User and Tenant. ```prisma model MetricLog { id String @id @default(cuid()) createdAt DateTime @default(now()) env String type String // loader, action route String url String function String duration Int userId String? tenantId String? user User? @relation(fields: [userId], references: [id], onDelete: Cascade) tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade) } ```