# RailsFast Documentation > Complete documentation for RailsFast - The AI coding template ## Documentation - [🚀 Welcome! - RailsFast Docs](/) - [Prerequisites](/getting-started-1-prerequisites/) - [Quickstart (15 Minutes)](/getting-started-2-quickstart/) - [Rebrand & customize](/getting-started-3-customization/) - [Configure credentials](/getting-started-4-configuration/) - [Developing your app](/getting-started-5-develop/) - [Stripe, payments & plans](/features-0-payments/) - [User authentication & login](/features-1-auth/) - [Your new admin tools](/features-2-admin/) - [Sending transactional emails](/features-3-emails/) - [Background jobs & scheduled cron jobs](/features-4-background-jobs/) - [Uptime and monitoring](/features-5-monitoring/) - [SEO & Sitemaps](/features-6-seo/) - [Analytics](/features-7-analytics/) - [Caching](/features-9-caching/) - [Attachments and cloud storage (S3-compatible)](/features-12-attachments/) - [Abuse protection](/features-13-abuse-protection/) - [Usage credits](/features-14-usage-credits/) - [UI Overview](/ui-components-1-ui-overview/) - [Social Proof](/ui-components-2-social-proof/) - [Testimonials](/ui-components-3-testimonials/) - [FAQ System](/ui-components-4-faq-system/) - [Features](/ui-components-5-features/) - [Call to action](/ui-components-6-cta/) - [Pricing page](/ui-components-7-pricing/) - [Other components](/ui-components-8-other/) - [Customizing components](/ui-components-9-customizing/) - [AI image generation](/ai-2-image-generation/) - [LLMs and AI chats](/ai-3-llm-chat/) - [AI, vector databases, and RAG](/ai-4-vectors-and-rag/) - [How to get a 10/10 deliverability score for your emails](/guides-email-deliverability/) - [Kamal - Configure a container registry](/guides-kamal-container-registry/) - [Kamal - Configure a remote builder](/guides-kamal-remote-builder/) - [Migrating Existing Project](/guides-migrating-existing-project/) - [Deploy multiple Rails apps to the same server](/guides-multiple-apps/) - [Updating RailsFast](/guides-updating/) --- ## Full Content ## 🚀 Welcome! - RailsFast Docs Welcome to RailsFast! You're only a few minutes away from putting your first RailsFast app in production! But first of all: thanks for purchasing! You've made a great choice. This single decision could very well be the start of your own software business; or it could be the lever to finally take that idea you've been wanting to build into reality. > [!TIP] > 👉 You can go straight ahead and **[[getting-started/1-prerequisites|start building now]]**, or you can read below why I made this project. --- ---

RailsFast Logo

## Why RailsFast RailsFast is essentially a template, but it's also a bit more than a template – as you'll soon discover. It's a way of building and running software startups in a very solid, secure, and streamlined way. A way that gives you back total freedom, ownership, and control over your software business so you can be fast and independent. I ([Javi](https://x.com/rameerez), the maker of RailsFast, the one writing all these docs) personally think this is the best way one could build and run SaaS and web apps, and that's why I myself use RailsFast for every new app I make. Building a software startup means making millions of tiny decisions, and the promise when buying a template is that most of those decisions are made for you, giving that time back to you and freeing you up to build the actual product instead. That's a great responsibility, and the template is only as powerful as the quality of the decisions it incorporates. If the person building the template makes the wrong decisions, those bad decisions cascade downstream and multiply for every single user of the template. It's unfortunately not uncommon to see fairly inexperienced developers making templates that are later found to contain massive flaws that could have been easy to prevent, causing a lot of headaches for a lot of people. It's also unfortunately not uncommon to see templates made by seasoned engineers that despite their technical ability have never built a run any software business other than the template itself – which also reflects in the quality of the decisions, because all of a sudden the entire thing is a maze of technical complexity that cripples any aspiring entrepreneur just wanting to put something fast out there. As for myself, I've been both developing software and running startups for the past 10+ years. I'm familiar with the technical stuff _and_ the business pains. I put my first website on the internet in 2006, and since then I've created and scaled Rails startups to over 4+ million users a month, I've built Ruby gems downloaded 100k+ times, I've perfected Rails SEO to get Google to send my websites millions of clicks in organic traffic, I've been viral with Rails-based AI projects featured on media like The Washington Post, Fast Company, TNW; and I've made dozens of other projects, not only Rails-based. I've launched apps using everything from TypeScript and JavaScript, to PHP, to React / Next, to Python. Throughout the years I've tried and tested many technologies, libraries and frameworks, and I wouldn't use anything other than Ruby on Rails to build and run a web-based software businesses – that's why Ruby on Rails is the technology of choice for this template. You only have to look at the list of startups that are made with Rails (GitHub, Shopify, Coinbase...) to realize you'll be in great company. As for security, scalability, performance, auth, and those other myriads of little yet critical decisions: RailsFast incorporates everything I've learned in my 10+ years building and running startups. I had to scale startups to millions of users, but I've also been hacked, I've been DDoS'd, I've been penalized by Google, botnets from Kazakhstan have tried to jam my API endpoints... I've seen a fair deal of things. I'm by no means perfect, but every one of those things left scar tissue that I've now coded into RailsFast, to prevent some of those problems (or at least help a little bit) and make your journey easier. I started making RailsFast after selling PromptHero, my biggest Rails-based startup to date. I launched it in 2022 and it grew very very fast, so I had to develop a lot of things _very quickly_. I was surprised I had to develop from scratch things as basic and universal as a user credits system or plan limits enforcement; and since the business was growing so fast I couldn't spend much time engineering, so the resulting quality of those systems was not the best. That's why when after selling the business I started creating new projects, and I came across the exact same problems, I couldn't believe I had to re-implement these things all over again. But since this time over I could spend a bit more time engineering, I set out to do things right. So for an entire year I broke down into Ruby gems all the little parts from PromptHero that I needed to reuse in my new apps. The result were 15+ Ruby gems I could stack up like LEGO pieces to build new apps very fast. It worked, and now thousands of developers around the world use them. But I was still spending a lot of time wiring everything together for every new project. I was missing something that would bring all those gems into a cohesive template that _just worked_, with everything already wired up and preconfigured out of the box, so I could just clone it and make new projects _like churros_. That was the starting point for RailsFast. Then of course the AI-assisted coding revolution was ongoing, and I saw a lot of my peers struggling with _vibe coding_. At first I didn't get it, because it worked so well for me. Then I realized a few main differences between their approach and mine. The first thing was the choice of technology: Rails is simply superior for vibe coding compared to, say, JavaScript. That alone would explain the difference in results, but on top of it they were also asking the AI to create everything from scratch for every new project. Without a template that leverages known truths, learnings, and well-tested libraries, what you get is a blob of hallucinated spaghetti code: the perfect recipe for disaster. And lastly, I realized the way I structured my Rails projects was fairly optimized for AI. If you write good context (rules, prompts, etc.) and organize things logically, the AI agents understand quickly what to do in each part of the codebase, which makes things significantly easier and more accurate. So I decided to make RailsFast not just good for manually cloning and building a startup, but designed explicitly for AI from the beginning. Other than Rails, AI, and code itself, I've also arrived at a pretty stable set of external tools I now use in literally every project. I think those are the best tools one could use, and therefore RailsFast is designed for them. For example, RailsFast uses Stripe for payment processing, Cloudflare for caching and DDoS prevention, Hetzner for servers to deploy your app to, and R2/S3 for storage. I believe this stack is extremely well battle-tested and maximizes your freedom & ownership as a software business owner. It also happens to be dirt cheap (or straight up free), allowing you to launch and run many app ideas for close to nothing. You can change everything in RailsFast, of course. At the end of the day it's just code you can edit. But if you change some of these essential pieces, it will be at the cost of adding a lot of complexity. As a rule of thumb: RailsFast, as you bought it, is guaranteed to work. Mess with the recipe, and it may no longer work. I believe it's opinionated in a good way: it makes a lot of good decisions for you, so you can fully focus on building your product; and it provides strong guardrails for the AI so it gets things done without getting lost. The other thing I believe RailsFast excels at is forcing you to **ship early**, and **ship often**. You're going to be pushing things to production since the very first minute of the onboarding. This is because the single biggest and most common mistake for entrepreneurs like us is launching too late. We tend to spend too much time developing locally without ever showing anyone, and it's often the case that our projects never see the light of day. Who knows why: maybe we think they're never good enough to be made public, or maybe by the time we're happy the project is already too complex to be put in production easily. The result in any case is that we keep postponing the moment of publishing, and by the time we realize, months have already passed. Since this is probably the #1 problem for software entrepreneurs like us, it's exactly what we're going to address first thing in RailsFast. We're going to completely reverse the order things are usually done, and so we're going to launch our app first in the quickstart. We'll begin our journey by publishing our project, giving us a shareable URL straight from the beginning, and forcing us to ship, and to do so iteratively. It'll help us develop a bias towards action. It will only be after your project is live and online for everyone to see that we'll start developing it. I deeply believe having an unfinished website already live will give you motivation to fix it and build, and most importantly: to share your project from the start. With that being said, I really hope you put RailsFast to good use! I myself am going to be building many things based off it, so expect the template to get updated and improved as I launch new stuff. I truly believe you're at an advantage here over any other JavaScript-based templates or people rawdogging vibe coding, and I think you'll realize it too very soon. If you build something cool with RailsFast please [let me know on X](https://x.com/rameerez) so I can see it and add it to the list of projects in the RailsFast website! 👉 Your journey [[getting-started/1-prerequisites|starts here]]! Good luck! --- --- ## Prerequisites Let's set strong foundations first so you can fly through the upcoming 15-minute quickstart. ## Before you start It makes things easier if before starting you have already decided: - [ ] A **name** for your project - [ ] A **domain name** (like `myproject.com`) to deploy your project to > [!TIP] > You can also use a subdomain (like `myapp.example.com`) instead of a domain, but in any case you need to have either purchased and ready to use if you want to deploy your app to production. I recommend buying your domains from [Cloudflare](https://www.cloudflare.com/products/registrar/) (they sell domains at cost) You can always rebrand and change your project name and domain later, but renaming everything everywhere is always a pain, so I strongly recommend setting it right from the start. ## Technical requirements You should have the following things installed and configured in your development computer: - [ ] `git` ([guide](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)) - [ ] Ruby 3.3+ and Rails 8+ ([guide](https://guides.rubyonrails.org/install_ruby_on_rails.html)) - [ ] Docker Desktop ([macOS](https://docs.docker.com/desktop/setup/install/mac-install/), [Windows](https://docs.docker.com/desktop/setup/install/windows-install/)) - [ ] PostgreSQL 15+ ([macOS](https://postgresapp.com/), [Windows](https://www.postgresql.org/download/windows/)) ## External services For your RailsFast app to run in production (live for everyone to see and use), you will need accounts in: - [ ] [GitHub](https://github.com) (for storing your code) - [ ] [Hetzner](https://hetzner.cloud/?ref=dSlYpM3ogSsu) (for servers to deploy to) [Get $20 in credits with [this link](https://hetzner.cloud/?ref=dSlYpM3ogSsu)] - [ ] [Cloudflare](https://www.cloudflare.com) (for caching and DDoS protection) - [ ] [Stripe](https://stripe.com) (for payment processing) - [ ] [AWS](https://signin.aws.amazon.com/signup) (for storage and mailing) These are the RailsFast recommendations. These are not hard requirements, but we'll move forward assuming you have accounts in these services. You may be able to develop your RailsFast app locally without any of these, but they'll be needed for putting your app in production. You may swap some of these external services for others you prefer (for example, using DigitalOcean instead of Hetzner, or using Mailgun instead of AWS SES), but these are not the official RailsFast recommendations and therefore RailsFast may not support them. It's strongly encouraged you stick to these recommendations. > [!TIP] > If you've skipped it, I recommend going back to the [[index|docs home page]] and reading the motivation behind RailsFast. It's not mandatory, but it's a good read and I believe it will help you understand why we'll be doing the things we'll be doing. ## Development tools To develop / vibe code your RailsFast app, I recommend: - [ ] [Cursor](https://cursor.com) (and/or [Claude Code](https://code.claude.com/docs/en/overview)) - [ ] [Context7](https://context7.com) MCP (get your free API key [here](https://context7.com/docs/api-guide)) You can also just use VS Code, `nvim` or any other code editor if you like it more: development tools are very developer-specific, and therefore these are not hard requirements. RailsFast should work fine with any code editor you choose, but you'll only get the best AI-assisted experience if you stick to Cursor/Claude Code. > [!NOTE] > Throughout this first few "Getting Started" pages, I'll try to get you up and running from zero, explaining things in simple terms without making many assumptions about how much you may already know about Rails or web development in general. If you're an experienced developer, you may feel I'm overexplaining at times: please remember it's just to make onboarding easier for people that may not be as experienced. After the Getting Started section, the docs will get more technical. If, on the other hand, you're starting from scratch and this is the first time you work with an entire web project by yourself, you may find those extra explanations helpful. If you still have questions, no matter how basic, paste the docs URL into Grok or ChatGPT and ask away! P.S.: I'm writing **everything** in this "Getting Started" manually, without AI -- I've put a lot of effort and care into it so it's not AI slop! All set? Jump to the 15 min quickstart! --- ## Quickstart (15 Minutes) The main goal of RailsFast is getting you to put _something_ online as fast as humanly possible. I've worked really hard to make something that takes, literally, only 15 minutes to production. While it won't be your finished product just yet, it will be something that at least _is out there_ and people can visit. Something that proves your entire RailsFast workflow from development to production works fine. Something to build upon so you can start charging money as soon as possible. > [!IMPORTANT] > This guide assumes you've already installed everything described in the [[getting-started/1-prerequisites|Prerequisites]] section. Please make sure everything is installed and configured before continuing. [TODO: Video of me doing all this tutorial actually in under 15 minutes] ## Kick off your RailsFast project Start by accessing the main RailsFast repository [`railsfast/railsfast-base`](https://github.com/railsfast/railsfast-base), to which you should have gotten access upon purchasing, and clone it: ```bash git clone --origin railsfast https://github.com/railsfast/railsfast-base.git myapp ``` > [!TIP] > Replace `myapp` in the command above with the name of your app. Open the `myapp` folder that has been created in Cursor. This is your very own RailsFast project now! ## Push your project to GitHub Right now you already have a working codebase, so let's save it to GitHub. Open up your GitHub account and create a **PRIVATE**, empty repository (no template, no README, no .gitignore, no license). > [!WARNING] > Make sure the repository you create is __private__! RailsFast doesn't allow public repositories. Point your local project’s origin to your new repo: ```bash git remote add origin https://github.com/YOUR-USERNAME/myapp.git ``` And push the code: ```bash git branch -M main git push -u origin main ``` ## Run the project setup script Now open up your project in Cursor and run this in the terminal: ```bash bin/railsfast init ``` This will start the interactive RailsFast setup script. First, it will ask you to name your project. Then, it'll generate secure encryption files, a sample encrypted credentials file template, the right deployment config, and essentially get your project ready for deployment. At the end, if everything went right, you should see a success message telling you the project is now ready to deploy. ## Deploy your project We're now ready to deploy the RailsFast project to production! We only need a server to deploy to. > [!INFO] > A server may also be called a VPS (Virtual Private Server). ### Spin up a server (VPS) Go to [Hetzner](https://console.hetzner.com) and log in to your dashboard. Create a project if you don't have one (a "project" in Hetzner is just a named folder under which resources like servers are grouped). Then, inside the Hetzner project, click on the `[ Create Resource ]` button, and then click on the `[ Servers ]` button. #### Select a server type and size For a low-traffic app (an app that's just starting, or a hobby project) pretty much any size will do. You can even fit multiple RailsFast apps in the same server to save costs. For now, let's choose a good cheap-yet-powerful server with 2vCPUs and 2GB RAM: - For **type**, choose: `Regular Performance` under `Shared Resources` (`x86`) - For **size**, choose: `CPX11` or `CPX22` (the actual model number depends on the location) A server like this will be more than enough and only costs around $5/mo. There are other cost-optimized options for about $3/mo you can experiment with, but their location availability may vary. You can also choose a server a bit more expensive like `CPX31` or `CPX32` (4vCPUs and 8GB RAM) for ~$20/mo if you expect your app to have more traffic / load, if you expect to fit multiple apps in the same server, or if you'd just like to have some extra room to grow from the start. #### Select a server location Make sure to choose a location physically close to your customers (if your users are mainly in America, spin up the server in the US; if most of them are in Europe, choose one of the European locations, etc.) Keep the rest of the config as default (Ubuntu OS image, public IPv4 and IPv6 addresses, etc.) Scroll down until the SSH section. #### Create or choose a SSH key to access your server To access your server and deploy code to it you'll need an SSH key. Create one if you don't have one: ```bash ssh-keygen -t ed25519 -f ~/.ssh/my_hetzner_ssh_key ``` > [!TIP] > Replace `my_hetzner_ssh_key` with the name you want to give your SSH key. Add your SSH key to your SSH agent so your terminal can actually connect to the server in the next steps: ```bash ssh-add ~/.ssh/my_hetzner_ssh_key ``` Then display and copy your __public__ key: ```bash cat ~/.ssh/my_hetzner_ssh_key.pub ``` And paste the contents into the "Add an SSH key" box in Hetzner. Give it an identifiable name, like `my_hetzner_ssh_key` or whatever you named it in the previous step. #### Add backups to your server Now, __optionally__, you may want to add backups to your Hetzner server. It's just a checkbox: if you check it, Hetzner will make a daily copy of your server so you can easily recover things in case things go wrong. RailsFast already offers a different database backup mechanism, but it's always a good idea to have contingency plans in case, so if you're a bit paranoid like me just check it and Hetzner will have your back in case things go really wrong. #### Run the initial server setup To finish setting up our server, let's run the RailsFast setup script to harden the security of the server and install dependencies. It's all streamlined, you just need to paste this into the "Cloud Config" text box: ```yaml #cloud-config runcmd: - bash -lc 'set -euo pipefail; wget -qO /root/railsfast-setup.sh https://setup.railsfast.com; chmod +x /root/railsfast-setup.sh; /root/railsfast-setup.sh 2>&1 | tee -a /var/log/railsfast-setup.log && reboot' ``` This will use Cloud-init to run the RailsFast server setup script upon creation, and get the server ready to deploy apps to. > [!NOTE] > This Cloud-init snippet runs the server setup script you can find at [setup.railsfast.com](https://setup.railsfast.com). If you prefer, you can do the initial setup manually to check the contents of the script. First, `ssh` into your server after it's created, then `wget` the setup script at `setup.railsfast.com`, inspect it, `chmod +x` it, and then execute it as root. You can explore the remaining server configuration options or just leave them as-is. Finish the process by giving a name to your server (like "railsfast-production" or something that helps you keep things organized), and then click the [ Create & Buy Now ] button. Your server will now start being created and initialized. #### Wait for the server to initialize We now need to wait for the server to boot up and the setup to complete (usually ~5 minutes) You can check the status of the initialization Cloud-init setup by `ssh`ing as `root` into your server and running: ```bash tail -f /var/log/cloud-init-output.log ``` Wait until you see a success message like `👽 SUCCESS: Setup complete!` and the system restarts. If you go and see the logs again after restarting, you'll now see cloud-init confirmation: `Cloud-init... finished at...` You can keep going with the next quickstart steps while you wait, just make sure your server is all ready before you actually deploy! ### Configure things for deployment Let's get ready to actually deploy your RailsFast project to your server! #### Point your domain's DNS to the server First, go to wherever you manage your domain's DNS, and point your domain to the server's public IP address you can find in Hetzner. For me, since I'm using Cloudflare to register and manage my domains, I navigate to my Domain, click on `DNS > Records`, and click the `[ + Add record ]` button to add a new record. Make the record of type `A` where the name is `@` (root) and the IP address is the server's IPv4 address from Hetzner. Leave the proxy status active (Proxied). #### Select the right SSL encryption mode Then, still in Cloudflare, go to `SSL/TLS > Overview` and click on the `[ Configure ]` button. Select `Full (Strict)` encryption mode and click Save. > [!NOTE] > If you don't do set the right SSL mode in Cloudflare, even if your deployment succeeds, your server will complain about weird redirect errors like this: _"The page isn’t redirecting properly. Firefox has detected that the server is redirecting the request for this address in a way that will never complete. This problem can sometimes be caused by disabling or refusing to accept cookies."_ #### Edit `deploy.yml` to let Rails know where to deploy to After the `A` DNS record is set and the Full SSL encryption mode is set, go back to your RailsFast project in Cursor and edit the `deploy.yml` file you can find at `config/deploy.yml`. The `deploy.yml` is where we'll add all the details about your server and domain name so the app actually knows where to deploy to. Change the following things: - **IP**: Replace the placeholder IP of your server. The placeholder IP is `1.2.3.4`: search and replace, or replace manually in: - `servers` > `web` - `accessories` > `postgres` > `host` - `accessories` > `pg-backup` > `host` - **Domain**: Replace the placeholder domain for your actual domain name in: - `proxy` > `host` - **SSH**: Replace the placeholder SSH key path for the actual path of your Hetzner SSH **private** key in (example: `~/.ssh/my_hetzner_ssh_key`): - `ssh` > `keys` Now, optionally (but recommended): - [[guides/kamal-remote-builder|Configure a remote builder machine]] (if you're using macOS, you _may have to_ do this) - [[guides/kamal-container-registry|Configure a remote container registry]] > [!NOTE] > RailsFast uses Kamal for deployments. If you want to understand more about the `deploy.yml` file and what you can do re: deployments, check out the [Kamal docs](https://kamal-deploy.org/docs/configuration/overview/) ### Hit the deploy button We're ready to deploy! Let's boot up the database and its scheduled backups: ```bash kamal accessory boot all ``` If you're not using a [[guides/kamal-container-registry|container registry]], launch the Docker Desktop app (to run Docker engine). Then, run this to set up and boot the local registry (and confirm your container registry credentials are okay if you're not using a local registry): ```bash kamal registry setup ``` And then, finally, deploy your project with: ```bash kamal deploy ``` ✅ Success! This gets your RailsFast app live. Visit your domain name on a web browser and you'll see the live demo page. > [!TIP] > This is a good time to share your project online! If you use X (formerly Twitter), please [post about it](https://x.com/intent/post?text=I%27ve%20just%20built%20my%20first%20project%20using%20@RailsFast%20by%20@rameerez!%20Check%20it%20out!&url=https://yourproject.com) and tag me so I can see it! 🚀 That's it! Your project is now running and living on the internet for about $5/mo, ready for full production usage, fully secured, on your own VPS that you fully control, where you own all your code and users' data, with no surprise $10k Vercel monthly bills! Welcome to freedom! ## What you just got I think it's worth repeating and making explicit everything you already have up and running now, because it's remarkable. Other templates require you several external dependencies, subscriptions to different services, and configuration headaches for something we've achieved here in under 15 minutes. You now own: - ✅ A full-stack web application (not just a frontend decoy: both front and back-end) fully ready for production traffic - ✅ Running on your own domain - ✅ Secured with a **SSL certificate** (automatically issued on deployment and auto-renewed before expiration) which makes all client-server communications secure and strictly encrypted - ✅ A fully secure, production-ready **database, DB schema, and migrations**; all this with no external dependencies: you own all your user's data, nothing leaves your server, nobody can nuke your business by banning your Supabase account (because you don't need one!) - ✅ **User authentication / login** working by default, without any external dependencies either - ✅ **Billing + payments**: everything ready to start charging real money as soon as you configure your Stripe credentials in the next sections - ✅ You're running your entire business on your own server for a **flat fee of less than $10/mo**, without having to worry about getting traffic spikes (unlike Vercel!) - ✅ You can even fit **multiple RailsFast projects** in the same server, without having to pay more! - ✅ Your project is now ready to support thousands of users, right out of the box - ✅ Easily scalable to millions of users as your app grows (and even then, you won't be paying a fortune because [servers are cheap](https://rameerez.com/how-i-exited-the-cloud/)!) - ✅ Plus all the features you can find in the features section of the docs, ready to go! --- This quickstart may feel like a lot of steps, but it's only a one-time setup! Moving on, every time you want to deploy your app, you just need to run `kamal deploy` You're now ready to start developing (or vibe coding) your app! Your next step is customizing the base project to start making your app actually look like your own app. --- ## Rebrand & customize If you're here, you should have been able to complete the quickstart and you should have your RailsFast base project already deployed and live. That's huge! You have a live, secure, monetizable demo page that screams "build on me!", so let's get to it! It's time to own your app. Let's start by customizing the base project to make it truly yours. ## Rebrand the project Customizing your brand name, logo, company name etc. in RailsFast is extremely straightforward: you just need to edit the `railsfast.yml` under `config/railsfast/railsfast.yml`. Since you already have a name and domain name, go ahead and edit the file. While you're at it, you can also add your project logo, your default page title and description for SEO, and your legal address for invoicing. > [!TIP] > While you're setting branding materials, don't forget to add a default OG image on `railsfast.yml`. An OG image is the image showed on apps like X, Telegram, Discord, Facebook, etc when you share a link. They're usually 1200x630px. OG images [are notoriously important](https://x.com/levelsio/status/1967622683480441106) for CTR and looking professional when people share your project. When you're done, you can update the live website by first git commiting your changes, and then deploying the project with: ```bash kamal deploy ``` And if you just want to see the changes in your computer without updating the live website, just fire up the local development server: ```bash bin/dev ``` And your project will be available in your computer only at [`http://localhost:3000`](http://localhost:3000) ## Add a favicon While we're at it, there's one last thing we can do to make your RailsFast project professional-looking and properly branded: add a favicon. The favicon is the little icon that shows up in the browser navbar next to your website title, and in mobile browsers when you save the page as a bookmark, browse tabs, etc. If you already have a logo for your project, this should be quite straightforward. I recommend you use a favicon generator [like this one](https://www.favicon-generator.org), because it already gives you not only the favicon, but the mobile iOS / Android app icons, and icons in different sizes, all RailsFast-compatible. Just generate your favicon pack and replace the contents of `public/favicon` in your RailsFast project with your own generated assets. --- ## Configure credentials The next thing that's stopping us from charging money and delivering our software service right away is configuring the app to use our credentials. We need, for example, to configure our Stripe API keys in the project so we can start processing payments; or our S3 access keys so we can upload and save attachments like user avatars. ## Credentials are secure and encrypted Credentials in RailsFast are encrypted. They can only be decrypted with the random encryption key (`config/master.key`) that was generated uniquely for you upon project setup (when we ran `bin/railsfast init` in the quickstart). This is a secure way to store private & sensitive credentials like access and API keys, without risking leaking them in plaintext in the codebase. No one can read your credentials even if they get access to the encrypted file (`credentials.yml.enc`), because they don't have the decryption key. > [!WARNING] > Never commit or make public your `master.key` file. It is already in the `.gitignore` to avoid it getting accidentally commited, so don't change that. Use the same caution for any other `.key` file in the project. ## How to edit the encrypted credentials file The RailsFast setup also generated a sample credentials file for you, to help you understand how the credentials file should be used in your project. You'll see it's very straightforward. To view and edit your project credentials, run: ```bash EDITOR="cursor --wait" bin/rails credentials:edit ``` And you'll view the decrypted credentials, ready to edit. To save changes after editing, just save the file and close it, and the credentials will automatically get encrypted back, ready to be used by your app. ## How the credentials file is organized If you look at the credentials file, you'll see it's organized by environments: `shared`, `production`, and `development`. You may (and probably should) have different credentials for your development and production environments. For example, for Stripe, you should use your sandbox / test keys in development; and you should only use the live keys in production, exclusively. > [!INFO] > "Production" just means "your server": the environment where your project is live and ready to be used by other people. As opposed to "development": where the project is only running in your local development computer, and only accessible by you. For some other services, this `production` vs `development` distinction may not make much sense, so to avoid duplication you can just put those credentials under the `shared` block, and both `production` and `development` will get them automatically. I've included a sample `demoservice` to showcase how shared credentials work. You can also override any part of a shared credentials block like `demoservice` per environment, while the rest will be kept the same. In any case, `demoservice` is just there for demoing purposes: you can remove it. ## Add all the necessary credentials If you followed the [[getting-started/1-prerequisites|Prerequisites]] section, you should already have accounts in all the key services we're going to use, so now it's just a matter of going service by service generating the right keys and plugging them in the right place. For your RailsFast app to fully work, we'll need at least: - **AWS**: we'll just use AWS SES for sending emails. I'm not a fan of AWS, but SES is probably the cheapest & most reliable emailing service out there. - Inside your AWS Dashboard, navigate to `AWS SES` (Simple Email Service) - Add your domain in SES > Configuration > Identities and create all required DNS records - For more detailed instructions, follow our [[guides/email-deliverability|perfect emailing guide]] and you'll also achieve a 10/10 deliverability score in your emails - Now move away from SES and navigate to AWS IAM to generate an Access Key and Secret Access Key for SES - Create a new IAM user - Name it something descriptive like `yourprojectname`-production - Give it enough SES permissions to send emails - To do that, create a new policy, click on the [ Create policy ] button - In the "Specify permissions window, switch from "Visual" to "JSON" and paste the following contents: ```json { "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "ses:SetIdentityMailFromDomain", "ses:SendEmail", "ses:SendTemplatedEmail", "ses:SendCustomVerificationEmail", "ses:SendRawEmail", "ses:SendBulkTemplatedEmail", "ses:SetIdentityDkimEnabled", "ses:SetActiveReceiptRuleSet" ], "Resource": "*" } ] } ``` - Give it a descriptive name like `ses-send-email-policy` and create the policy - Back on the create user screen, attach the new created policy to the user, and create it - Once the user is created, click it to access the user details screen, navigate to the "Security credentials" tab, and create a new Access Key. When asked, select "Other" as your reason (your reason is direct AWS API calls, but that's not listed) - Create the Access Key and copy the access key and private key to your RailsFast project's credentials file - **Cloudflare**: DNS + DDoS protection, Turnstile for anti-bot signups, R2 for S3-compatible storage (for storing avatars, user uploads, etc.) - R2: [create an R2 bucket](https://developers.cloudflare.com/r2/api/tokens/) for your project. Then, on the R2 Overview screen, under the Account Details box, you'll see the "API Tokens" row and next to it, a `{Manage}` button, click it. Now in the Manage R2 API tokens screen, create a User API Token for your bucket (give it `Object Read & Write` permissions, click "Apply to specific buckets only" and specify just your bucket). Create the API Token and copy and paste the `account_id`, `access_key_id`, `secret_access_key` and bucket name, and paste them in the right place in your credentials file. Go back to the R2 Overview screen, copy your Cloudflare account ID and paste it in the corresponding spot in the credentials file too. You only need to do this for `production`, not for `development`. - Turnstile: [create a Turnstile widget](https://developers.cloudflare.com/turnstile/get-started/widget-management/dashboard/) to get your Turnstile site key and secret key. This will be used to protect your auth / signup forms from bots. As with R2, Turnstile credentials are only needed in `production`, not in `development`. You just need the site and secret keys, you don't need to do anything else with the widget, all is already configured and wired in RailsFast for you. - **Stripe**: payment processing - [Generate a publishable and a private key](https://docs.stripe.com/keys) (both in live and sandbox mode, for `production` and `development`, respectively) - [Create a webhook](https://docs.stripe.com/webhooks) in live mode (webhook URL: [`https://YOUR-DOMAIN-HERE/pay/webhooks/stripe`](https://github.com/pay-rails/pay/blob/main/docs/7_webhooks.md)), and add the webhook signing secret in `production` - Install the [Stripe CLI](https://docs.stripe.com/stripe-cli/install) and add the development webhook signing secret to `development` ## Configure database backups RailsFast ships by default with automatic database backups. All your user's data gets backed up regularly outside of your server, so in case of disaster you can recover all your data and put your app back up. However, for this to work you need to let your app know **where** those backups should be uploaded to. Luckily for us, we can use any S3-compatible storage solution for this. So, since we already have an AWS and a Cloudflare account, we could just use AWS S3 or Cloudflare R2 for our backups and be done with it. There's nothing wrong with that. However, if you're like me and you want to add an extra bit of resilience to your setup (in the improbable case your AWS or Cloudflare accounts get compromised because you're already using them for other things), you can keep your backups in a completely different service that we're only going to use for backups. I use [Backblaze B2](https://www.backblaze.com/cloud-storage) for that. Backblaze B2 is S3-compatible just like AWS S3 or Cloudflare R2, and they also have a free tier that makes your backups free or close to free as long as they're not too big. Whatever the service you end up using for storing backups (again, AWS S3 and Cloudflare R2 are both good options if you don't want to complicate things early), you just need to add the S3-compatible credentials in the designated files under `config/backups`: - `s3_access_key.key` - `s3_bucket.key` - `s3_region.key` - `s3_secret_access_key.key` These credentials are the same for any S3-compatible storage service. Just replace the placeholder text in each file with your credentials, re-deploy the backups service with `kamal accessory reboot pg-backup`, and you'll be automatically backing up your entire production database every night. If you want to adjust when to do backups, how often to do them, and how many backups to keep, you just need to adjust the `pg-backup` config in `config/deploy.yml`. Make sure to reboot the backups service after you make changes: ```bash kamal accessory reboot pg-backup ``` > [!INFO] > We're using the [kartoza/pg-backup](https://github.com/kartoza/docker-pg-backup) Docker image for database backups. It's already wired up and configured to work with your credentials. It's also configured as a Kamal accessory so you can easily manage it as shown above. Read their docs to know more about available backup options. --- ## Developing your app Look at you, you already have a beautiful working project! Everything is wired and configured. And it's even live on the internet for other people to see and interact with! You've deployed your app and have something live before even starting development, isn't that beautiful? Now it's just a matter of building __your own__ business on top of the template. To begin development, just run: ```shell bin/dev ``` And the local development server will start up, serving everything needed for you to see your project in localhost (at port 3000 by default) -- just visit [http://localhost:3000](http://localhost:3000) > [!IMPORTANT] > Make sure you're running your local PostgreSQL server (on macOS: by launching the [Postgres app](https://postgresapp.com/) and starting a v15+ server; if you're on Windows follow the [Windows instructions](https://www.postgresql.org/download/windows/)). Without a PostgreSQL database, your local Rails app will error upon launch.

RailsFast Email Deliverability Guide

## Start coding or vibe coding RailsFast comes ready for you to vibe code on top of it. It ships with smart context rules so that Cursor, Claude Code, Codex etc. can easily understand the structure and contents of the project, and can use the right tools in the appropriate subparts of the project. It understands the technologies used, where they're used, and how to fetch detailed docs, so vibe coding on top of it should be a breeze. Just ask Claude Code or Cursor whatever you want to do. For example, let's ask AI to create a new "Help" page for us, wire it with the appropriate routes and controllers, add it to the navigation bar and footer, and fill it with useful help content from the FAQ. ### Your first vibe coded feature To get started, we could just ask AI something like: ```plaintext create a new demo "Help" page, add it to the navbar and footer, use the FAQ component as main content, add a title and description and SEO meta tags too ``` > [!TIP] > If you're using Cursor, make sure it's on "Agent" mode (not "Plan" or "Ask") so it can actually browse and edit your project files for you. Let the AI agent browse through your project and create + edit the necessary files. When it's done, it should have done something similar to this: - Added a new route to the `config/routes.rb` file - Created a new view under `app/views/demo/help.html.erb` (or similar) and filled it with content - Added the controller action to `app/controllers/demo_controller.rb` - Edited the navbar and footer partials at `app/views/layouts/partials/_navbar.html.erb` (and footer) Now if you visit and reload your project at [http://localhost:3000](http://localhost:3000), you'll see the new Help page in the navbar and footer, and you should be able to navigate to it if you click on it. ### Your second vibe coded thing Another idea would be to ask AI to edit the default landing page and make it yours. AI can replace the placeholder text and generate landing copy text specific to your project, so you can just move really quick to put something out there. I would ask the AI agent something like: ```plaintext my startup idea is: [describe it]. With this info, please edit @app/views/demo/landing_page.html.erb to replace the placeholder text and tailor the landing page to my startup idea. Use any components under @app/views/components/railsfast. There's no need to use all components, nor any need to keep any of the existing components. No need to keep any of the placeholder content: edit, delete, and mix the available UI components as needed. Just tailor the landing page to the idea in the best way possible ``` Of course, the resulting AI-generated text will be pretty bland, and will look placeholder too. I strongly recommend against this approach for your actual project landing page: for the long-term you'll need an actually well-researched, well-thought-out, well-written landing page for your startup, with your actual product images. But for demo purposes I think this is a really quick way to get started: all of a sudden you can have a fully branded landing page, tailored to your specific product offering, ready in theory to start charging money. You get the hang of it -- so go ahead and start building! ### Add the Context7 MCP One of the most important, if not **the** most imporant thing you can do when vibe coding is give the AI good context. Context about your app, context about your architecture, context about the APIs and dependencies you're using. RailsFast ships with already good context by default, but to make it work you need to connect to the Context7 MCP: a service that will help your AI get updated docs about any of the APIs and dependencies your project is using. To do that, first grab your [free Context7 API key](https://context7.com/docs/api-guide), and then configure your AI to use it: For example, if you're using Claude Code just run: ```bash claude mcp add --transport http context7 https://mcp.context7.com/mcp --header "YOUR_API_KEY" ``` If you're using Cursor or other IDEs, you can learn how to install it on the [Context7 GitHub page](https://github.com/upstash/context7). ### Do small, incremental steps Don't try to vibe code your whole project at once! Break big milestones into extremely simple tasks that the AI can achieve without problem. Maybe have the AI edit 1-2 files at the time, at most! Commit often to GitHub. Don't wait until you have 20 or 30 edited files to commit! Do very small, incremental steps, test them, and commit the changes to GitHub before moving on to the next thing. ### Deploy often! Your main goal while developing should be to press _the deploy button_ as much and as often as possible: ``` kamal deploy ``` Here's the workflow: ask AI one tiny thing, review the code and verify everything works, commit and hit `kamal deploy`. Rinse and repeat. ### How your RailsFast project is structured For development (no matter if you're coding manually, reviewing AI-generated code or managing AI agents), you'll need to have a rough notion of where things are. If you're already familiar with Rails, you already know this. If you're new to Rails, this is what your RailsFast project (and every other Rails project) is structured like: - **Front-end** - [Views](https://guides.rubyonrails.org/action_view_overview.html): - All visible pages ("HTML") are called `views` - Views live under `app/views` - Rails uses `erb` for views. `erb` is just HTML with Ruby code. It's somewhat similar to what PHP code looks like. - If a view file name starts with underscore (`_`), it's called a partial. Example: `_navbar.html.erb`. Partials are like components, you can include and reuse them in other views. - [Controllers](https://guides.rubyonrails.org/layouts_and_rendering.html#overview-how-the-pieces-fit-together): - Every view (except partials) needs a corresponding `controller` - A `controller` is just what sits between your backend/database and your views - The controller fetches data and gets your views ready for display - Controllers live under `app/controllers` - The name of the controller needs to match the name of the folder the view is in - Example: `demo` -- If your view is `app/views/demo/help.html.erb`, the corresponding controller needs to be `app/controllers/demo_controller.rb` (note how the `demo` part is identical in both file names) - The controller needs to define a **controller action** (a method inside the controller file) whose name needs to match the name of the **view** file - If your view is `help.html.erb`, inside your controller you need to define the `help` method - You can define special "`@` variables" in your controller action. If a variable name inside your controller action starts with `@`, you can use it right away in the corresponding view without doing anything else. Use this to, for example, load data and display it in the view. - Interactive pages and JavaScript - Rails comes with a suite of tools called [Hotwire](https://hotwired.dev) to make your pages interactive (not just static) - For interactive pages, Rails uses [Hotwire Turbo](https://turbo.hotwired.dev): a way of modifying / deleting / adding HTML to your pages in a few lines of Ruby code, without needing any JavaScript. - If you do need JavaScript, Rails uses [Hotwire Stimulus](https://stimulus.hotwired.dev) by default. Stimulus controllers let you add JS functionality to your views with the minimal amount of JavaScript needed. - You can also add React, Vue, Svelte, or any other JS framework / library to your Rails project. I do not recommend this, though, I believe you'll find both Turbo and Stimulus work way better when used within a Rails project than any JS framework - To add any JS library to your Rails project, use `importmaps` - For example, if you want to use Three.js in your project, just run `bin/importmap pin three` and Three.js will be available to use in your Stimulus controllers - **Back-end** - [Models](https://guides.rubyonrails.org/active_record_basics.html) - In Rails, you don't interact with your SQL database directly - Database tables are abstracted into **models** (using something called `ActiveRecord`) - A `model` is just a database table abstraction + related logic - Models live under `app/models` - Example: if you have a `user` table in your database, the corresponding model is `User` and lives under `app/models/user.rb` - Most of the logic in your entire project should live in the models ("heavy models, thin controllers") - Models can be interacted within Rails like `User.last`, or `User.last.created_at` - Models can (and should) validate data and enforce lengths, limits, etc. - Models can define relationships between other models (like `has_many`, `belongs_to`... which map to DB relationships) - You can still write SQL queries in Rails, but it's usually easier to just use model methods provided like `ActiveRecord` - For example: `User.last.posts.count` joins the `post` table with the `user` table and gets you the post count for the last user - Database - PostgreSQL - PostgreSQL (sometimes called `psql` or `postgres`) is the database of choice in RailsFast - PostgreSQL is robust, it's the industry standard, and it scales beautifully - It has very powerful plugins to do things like vector embeddings for AI, or geolocation things, etc. - PostgreSQL has pretty much everything you startup will ever need, even if you reach millions of users - Since you don't really interact with the database directly in Rails, you can in theory swap PostgreSQL for any other database like MySQL, SQLite, MariaDB, etc. This is NOT recommended in practice, but just know that it's in theory possible - Migrations - You never touch the database directly - You alter the state of the database through database migrations - Migrations live under `db/migrate` - Migrations define changes in the database, like new tables or fields, new relationships, new indices, or deletions - You generate a new migration with `rails g migration` - You run pending migrations with `rails db:migrate` - The current state of your database after all migrations is always available in `db/schema.rb` - You never touch the database directly (again, worth repeating, because if you do you'll be bypassing all model validations and callbacks and your database may get to inconsistent states. You do everything through migrations and through `ActiveRecord` model logic) - Services / POROs - Some logic may not belong to any specific model, and it may not belong to any view/controller either - For that kind of logic, using services is usually a good idea - A `service` is just a PORO (Plain Old Ruby Object): that is, a default Ruby file without any required Rails logic - Services live under `app/services` - Example of services: a thin wrapper over an API you're using (like `openai_service.rb`), codebase-wide utilities, etc. - Background / async jobs - Background jobs go in `app/jobs` - You can set scheduled, recurring jobs (cron-like) by editing `config/recurring.yml` - Background jobs work thanks to a component of Rails called `solid_queue` - **Config** - [Routes](https://guides.rubyonrails.org/routing.html) - Your routes are defined in `config/routes.rb` - The routes file just link specific routes like `/help` to the corresponding controller action - You can do all sorts of things with routes: conditionals for auth / logged in users, dynamic routes by matching params, etc. - [Deployments](https://kamal-deploy.org/docs/configuration/overview/) - We use Kamal for deployments - Everything related to your deployments (servers, domain name, etc.) is configured in the `config/deploy.yml` file - Environments - Advanced configuration for your app can be found at `config/application.rb` - Environment-specific overrides can be made at `config/environments/development.rb`, `config/environments/production.rb`, etc. - None of this is needed to get you started, everything has been already configured in RailsFast, just know that these files exist - Gem-specific configs - Under the `config` folder you'll usually find configuration files for gems (gems are software packages in Ruby, like libraries) This is just a quick overview of what a Rails project looks like so you can get up to speed fast. It is by no means a comprehensive list of everything Rails has, I just wanted to give you the right mental models to get you to 80% understanding in a few minutes. If you want to go in depth, I recommend reading the [official Rails guides](https://guides.rubyonrails.org/getting_started.html) for getting started with Rails, or better yet: asking ChatGPT/Grok any questions you may have. ## Convention over configuration A tip before I send you off: when I started programming on Ruby on Rails, I remember feeling many things worked "like magic". There's many things in Rails that are wired implicitly behind the scenes, things you're not explicitly aware of, and the first feeling people usually get is that those things just work by means of magic. It can get frustrating at first because in other programming languages and frameworks you're used to wiring everything explicitly, and you may not know how things are even working in Rails, or where they're actually connected. The answer is **convention over configuration**. This is one of the main principles of Rails, and in practice it just means that all Rails projects look pretty much the same. Views go under `app/views`. Controllers go into `app/controllers`. Views names and controller actions need to be named the same. If you get comfortable with these conventions, you will understand any Rails database out there in minutes. You can onboard and get up to speed with any new project in literally minutes. It's one of the many advantages of Rails. Here's an anecdote: in the past I've hired Rails developers. Once, this one new Rails dev pushed code to production within 30 minutes of first onboarding the project (not an exageration) -- just because all Rails projects look alike. He was literally outputting production-ready code and being profitable for the company within 30 minutes of him first sitting as his desk. He hadn't seen the codebase before and was not familiar with the project. He simply just understood intuitively where everything was thanks to Rails and its principles. I still have to see something remotely similar in any other programming language / framework. If you ever wonder how things are wired up in Rails or how Rails knows this thing is related to that other thing, the trick is usually **naming**. When two things are named the same (or similar, like singular/plural etc.) those things are usually related (and wired behind the scenes) like views and controllers. ## It's now your turn! You now have all the tools you need with succeed with RailsFast! There's not much more I can say to help you onboard: you should now have a live project, fully configured, and ready to go! It's now your turn to start exploring and building. Don't be afraid to break things (commit to GitHub often!), and don't be afraid to ask silly questions to the AI, just go for it! >[!TIP] The RailsFast docs come in LLM-friendly format! Just feed our [LLMs.txt](/llms.txt) file to any AI and ask it questions! The rest of the docs cover specific features within RailsFast. There's a lot of functionality that comes preconfigured in RailsFast that _just works_ so you don't need to worry much about it: auth, user uploads, backups, sending emails, payment processing integration, etc. But there's also many optional things you can easily "turn on" and leverage to build your project as if you were stacking LEGO pieces. The rest of the sections cover this. The next section, in particular, goes over the different features that come with RailsFast. Feel free to keep reading the docs in order, or just jump straight to the section that draws your attention the most! Good luck! -[Javi](https://x.com/rameerez) --- ## Stripe, payments & plans Once your Stripe credentials are configured (like we did in the [[getting-started/4-configuration|quickstart]]), setting up payments and pricing plans in your app is quite straightforward. ## Install the Stripe CLI The first thing you're gonna want to do is install the [Stripe CLI](https://docs.stripe.com/stripe-cli) and configure it with your Stripe Sandbox, so you can receive Stripe webhooks in development. Once installed, log in to your Stripe account from the CLI: ```bash stripe login ``` And then forward all development webhooks to your local dev server: ```bash stripe listen --forward-to localhost:3000/pay/webhooks/stripe ``` You'll get a development Stripe webhook signing secret, which you need to add to your development [[getting-started/4-configuration|credentials]] so that Stripe webhooks get processed. With that, your development RailsFast app is now fully wired to Stripe, and reacting + processing all webhooks! > [!NOTE] > For Stripe webhooks to get processed, solid_queue needs to be running. This is handled automatically by RailsFast when you run `bin/dev` to start your development server, but if you're doing something else like starting your server with `rails s`, you need to launch solid_queue like this: `bundle exec rake solid_queue:start` ## Add and define your pricing plans The next thing you're going to do is add your subscription options (your pricing plans) to your `railsfast.yml` file. There's a placeholder there, you need to fill it up with your actual Stripe price IDs you've created in your Stripe dashboard: ```yaml development: <<: *default # Stripe pricing configuration # Define your Stripe Price IDs for each environment # These will be used by both pricing_plans and usage_credits gems # Use Sandbox / testing mode in Stripe to get test IDs in development stripe: plans: basic_plan: monthly: "price_REPLACE_ME" yearly: "price_REPLACE_ME" pro_plan: monthly: "price_REPLACE_ME" yearly: "price_REPLACE_ME" advanced_plan: monthly: "price_REPLACE_ME" yearly: "price_REPLACE_ME" ``` > [!IMPORTANT] > Make sure you use Stripe Sandbox price IDs for your `development` environment, and live price IDs for your `production` environment. This is the single source of Stripe price IDs for your entire app: everything draws from here. To have these subscription plans show up in your pricing page, edit the `pricing_plans.rb` file. It will look something like this: ```ruby stripe_config = Rails.configuration.x.railsfast.dig(:stripe, :plans) || {} plan :basic_plan do stripe_price month: stripe_config.dig(:basic_plan, :monthly), year: stripe_config.dig(:basic_plan, :yearly) allows :api_access limits :projects, to: 5 description "Your basic plan description" bullets "API Access", "Up to 5 projects" end ``` RailsFast uses the [`pricing_plans`](https://github.com/rameerez/pricing_plans) gem to define pricing plans. The first thing you get automatically is your users can purchase whatever plans you define (with monthly and yearly pricing) from your `/pricing` page – try it out after defining your plans! On top of having checkout and billing already configured, whatever you define in each of your pricing plans is automatically enforceable anywhere else in your app. In the example above, we give users on the `basic_plan` API access and up to 5 projects. You can enforce these limits easily throughout your app with methods and helpers like these: ```ruby @user.plan_allows_api_access? # => true / false @user.projects_remaining # => 2 ``` Read the [`pricing_plans`](https://github.com/rameerez/pricing_plans) gem docs to learn everything you can do with it (which is a lot!)

RailsFast pricing cards with automatic pricing plan limits and entitlements enforcement

And with that, you're pretty much ready to start charging and providing a fully functional service! Both in development and production! Try it out! If you want to tweak how the pricing page is rendered (toggle, accent color, scalable plans, etc.), see [[ui-components/7-pricing|Pricing page]]. ## Handle plan upgrades and downgrades RailsFast uses the Stripe Customer Portal integration to offload everything billing-related to Stripe. This includes handling plan upgrades and downgrades, which Stripe does beautifully. To get started, go to your Stripe dashboard and configure your plan upgrade and downgrade options in: https://dashboard.stripe.com/settings/billing/portal With that, your users will be able to upgrade or downgrade their subscription at any time through the Stripe Customer Portal link we provide with RailsFast. Everything else is automatically handled: whenever a user upgrades or downgrades, your app gets the webhook and your user gets moved to the corresponding plan, with its corresponding limits and enabled features. ## One-time payments TODO: PayChargeExtension ## Invoices TODO: receipts gem ## Adding a production Stripe webhook Don't forget to add a production Stripe webhook for your payments to work in production too! 1. Go to your [Stripe Dashboard - Webhooks](https://dashboard.stripe.com/webhooks) (make sure it's in live mode, and not in Sandbox!) 2. Click "Add endpoint" 3. Enter your webhook URL: `https://YOURDOMAIN.COM/pay/webhooks/stripe` 4. Select events to listen to (at minimum: `customer`, `charge`, `invoice`, and `payment_intent`, or select "receive all events") 5. Copy the signing secret and add it to your production credentials RailsFast uses the [`pay`](https://github.com/pay-rails/pay) gem to handle everything Stripe-related, check out the Pay Docs for guidance on how to use it if what you want to do is not covered in the RailsFast docs! --- ## User authentication & login RailsFast comes with an entire user authentication and login system. We leverage the [`devise`](https://github.com/heartcombo/devise) gem for that. Of course, the main thing it handles is user signup and login:

RailsFast user authentication

But on top of that, it also handles things like "Forgot your password?" and "Resend email confirmation" flows:

RailsFast user password reset flow

All this with beautiful transactional emails that will work out of the box if you followed the [[getting-started/4-configuration|quickstart]]:

RailsFast user confirmation email

## Abuse protection If you've configured your Cloudflare Turnstile credentials, you'll see the Turnstile captcha protecting all your user forms against bots and abuse:

RailsFast protects all user forms with Cloudflare Turnstile

There's no need for you to configure anything other than your Turnstile credentials as outlined in the [[getting-started/4-configuration|quickstart]], it all works automatically (you'll see a placeholder in development, and the real Cloudflare Turnstile widget once your app is deployed to production) ## Block disposable emails RailsFast automatically blocks users using disposable emails from signing up to your app. This comes working out of the box, there's nothing you need to do to make it work. If a user tries to create an account with a disposable email address like `xfgh0z@disposablemails.com`, they'll get blocked and see an alert like this:

RailsFast blocks disposable emails

The list of disposable email providers gets automatically updated in production every night (check your `recurring.yml` file!) We leverage the [`nondisposable`](https://github.com/rameerez/nondisposable) gem for this, which gets its updated list of known disposable email providers from the [`disposable-email-domains`](https://github.com/disposable-email-domains/disposable-email-domains) list. --- > [!INFO] > The [`devise`](https://github.com/heartcombo/devise) gem (what we use for auth) is very flexible and powerful! You can easily add Oauth and other login methods to your app, make sure to read the Devise docs for more info! --- ## Your new admin tools RailsFast ships with a few admin tools to help you manage your entire app and see key metrics. Of course, those are only accessible to admins, so the first thing we need to do is create you an admin user. ## Create an admin user First, just sign up to your own app as any other user would: - If you're in **development**, visit [`localhost:3000/users/sign_up`](http://localhost:3000/users/sign_up) - If you're in **production**, visit `yourdomain.com/users/sign_up` Signing up will send you an email to verify your account before you're able to do anything else: - If you're in **development**, emails don't actually get sent anywhere, so you need to use [`mailcatcher`](https://mailcatcher.me) to see emails in development mode (run `gem install mailcatcher`, then run `mailcatcher` to launch the daemon, and then visit [`127.0.0.1:1080`](http://127.0.0.1:1080) to see your "development inbox") - If you're in **production** and have correctly configured Amazon SES in the [[getting-started/4-configuration|Configuration]] section, you should actually get the confirmation email in the address you signed up with After confirming your email, launch a Rails console: ```ruby rails c ``` And in the Rails console, update your user grant it admin rights: ```ruby User.find_by_email("your_email@example.com").update!(admin: true) ``` That's it! You now have a user with admin rights. You may have to do this both in development and production, so you have an admin user in each environment. ## Your admin superpowers There are many things you can do as an admin. Let's give you a tour of your new superpowers. ### Get an overview of your business Visit `/admin` to see the general admin overview of your entire project:

MRR dashboard in RailsFast

### See and moderate your users From the admin sidebar, you can access different screens to see and moderate different models in your application. Visit `/admin/dashboard/users` to see a list of all your users. You can ban users, and admin / moderate any individual record. We leverage the [`madmin`](https://github.com/excid3/madmin) gem for this.

RailsFast admin panel with all tools needed to see a list of all your users and moderate them

### See your MRR dashboard and business valuation Visit `/admin/profitable` to view your current estimated business valuation, current MRR, and a few other SaaS metrics that will come in handy. We use the [`profitable`](https://github.com/rameerez/profitable) gem for this, which draws from your `pay` data (in your own database, without having to make calls to Stripe)

MRR dashboard in RailsFast

### Monitor background jobs and scheduled tasks (Cron) Visit `/admin/jobs` to see the status of all async background jobs and scheduled jobs (cron-like) You can see the status and logs of all executed jobs, whether succeeded or failed, you can pause, discard, or retry individual jobs and entire queues, and see when the next scheduled jobs will get triggered, and what happened when they last got triggered. We leverage the [`mission_control-jobs`](https://github.com/rails/mission_control-jobs) gem.

Background jobs and cron jobs monitoring in RailsFast

--- ## Sending transactional emails When you followed the [[getting-started/4-configuration|quickstart]], you configured your Amazon SES credentials to send transactional emails. On top of that, your RailsFast app is configured to send beautiful transactional emails using the [`goodmail`](https://github.com/rameerez/goodmail/) gem by default. So instead of sending boring, ugly, plaintext emails -- you send well-designed emails that look good on all email clients:

RailsFast beautiful transactional emails

All your user auth emails and your payment-related emails come already configured and working out of the box. You can view and edit all those emails: - `app/mailers/devise_goodmailer.rb` for `devise`-related emails (user authentication) - `app/mailers/pay_goodmailer.rb` for `pay`-related emails (payments & subscriptions) Other than the pre-configured emails, you can also send a transactional email at any point in your app like this: ```ruby mail = Goodmail.compose( to: recipient.email, from: "'#{Goodmail.config.company_name} Support' ", subject: "Welcome!", ) do h1 "Welcome aboard, #{recipient.name}!" text "We're thrilled to have you join the community." button "Go to Dashboard", user_dashboard_url(recipient) sign end mail.deliver_now ``` You can customize all transactional emails however you want! Add animated GIFs, change the text, make new emails... make sure to read the [`goodmail`](https://github.com/rameerez/goodmail/) gem docs to know everything that's possible. If you don't like `goodmail`, or if you'd like to use your own email templates, you can still use Rails' [`ActionMailer`](https://guides.rubyonrails.org/action_mailer_basics.html) -- `goodmail` is just an add-on, doesn't replace Action Mailer, you can keep writing emails with Action Mailer if that's what you like! --- ## Background jobs & scheduled cron jobs RailsFast comes with a robust background job processing system using [Solid Queue](github.com/rails/solid_queue/), Rails 8's built-in job backend. This is a fully-functional, production-ready background job system that allows you to: - Offload long-running operations (like processing files, or running cleanup tasks) as background jobs to be performed asynchronously in the background whenever the system can - Enqueue jobs to be performed later, in 5 minutes or any arbitrary amount of time - Send emails / do things whithout blocking the current request and making the user feel wait time - Handle file uploads and processing - Schedule jobs to run at night or whenever you'd like (`cron`-like), very useful for admin and reporting tasks - Handle retries automatically, retry jobs multiple times if they fail > [!INFO] > Something people don't usually expect is that this entire system doesn't have any dependency on Redis! You don't need any Redis process, instance or any in-memory store system to run this, it's all database-backed! (and very efficient in production!) ## Creating a background job It's better you read the [`ActiveJob`](https://guides.rubyonrails.org/active_job_basics.html) docs, but in a nutshell, you generate a new job with: ```bash rails generate job SendWelcomeEmail ``` Which creates the job file: ```ruby # app/jobs/send_welcome_email_job.rb class SendWelcomeEmailJob < ApplicationJob queue_as :default def perform(user) UserMailer.welcome_email(user).deliver_now end end ``` And then you can either perform the job right now: ```ruby SendWelcomeEmailJob.perform_later(current_user) ``` Or perform it later: ```ruby # Perform in 5 minutes SendWelcomeEmailJob.set(wait: 5.minutes).perform_later(current_user) # Perform at specific time SendWelcomeEmailJob.set(wait_until: Date.tomorrow.noon).perform_later(current_user) ``` ## Schedule recurring jobs (`cron`-like) You can schedule recurring jobs, which behave pretty much like `cron` behaves. To see all your recurring jobs and edit when they get triggered, open your `config/recurring.yml` file: ```yaml production: refresh_sitemap: class: SitemapRefreshJob queue: default schedule: every day at 4am Europe/Lisbon ``` Refer to the [`ActiveJob`](https://guides.rubyonrails.org/active_job_basics.html) docs to learn how to handle job errors and retries. ## Web UI As mentioned in the [[features/2-admn|Admin]] section, RailsFast comes with a dashboard to see all your background tasks, all your scheduled task and when they last ran, the output and result of each job run, etc. You can also discard and retry jobs manually. Access it as an admin user via `/admin/jobs` --- ## Uptime and monitoring RailsFast comes preconfigured with the [`allgood`](https://github.com/rameerez/allgood) gem for health checks / smoke tests. You can see all your current health checks by navigating to `/healthcheck`:

RailsFast app health checks with the allgood gem

By default, we check things like whether the database is up and running, the server has enough disk and memory, etc. You can customize your health checks by editing your `config/allgood.rb` file. Check the [`allgood`](https://github.com/rameerez/allgood) docs to know everything you can add to check the health of your app! The recommended use of this `/healthcheck` endpoint is to use it together with an uptime monitoring service like UptimeRobot. In UptimeRobot, you'd just add `https://YOURAPP.COM/healthcheck` as an URL to monitor every 5 minutes, and whenever any of the checks fail, you'd get a notification, a call, or a text, depending on what you have configured. It's very useful to quickly know if there's anything wrong with your app and fix it before any of your users notice! --- ## SEO & Sitemaps RailsFast has been designed for SEO and discoverability from the ground up. Your project, immediately upon deployment, should score 100/100 on SEO and close to 100/100 on overall performance on [Google PageSpeed Insights](https://pagespeed.web.dev/):

RailsFast apps have perfect SEO scores on Google PageSpeed Insights by default

Other than technical improvements and good technical architecture, your main two ways of affecting on-page SEO on your RailsFast app are: metadata and the sitemap. ## Metadata We use the [`meta-tags`](github.com/kpumuk/meta-tags) gem to handle on-page metadata. Everything is already configured and you'll see examples throughout the codebase, but to make it explicit, you can set your page metadata inside views like this: ```erb <% title "My page" %> <% description "This is the SEO description for my page" %> ``` Or in the corresponding controller action: ```ruby @page_title = "My page" @page_description = "My SEO description" ``` You can also set your page OG card image like this: ```ruby set_meta_tags og: { image: "https://example.com/image.jpg" } ``` ## Sitemaps Your app sitemap is available at `/sitemaps/sitemap.xml.gz` You can configure what URLs go in the sitemap by editing your `config/sitemap.rb` file. You can dynamically add thousands of URLs by iterating over all your database records. We leverage the [`sitemaps-generator`](github.com/kjvarga/sitemap_generator) gem for this, read their docs to know what's possible! You can also enable automatic sitemap discovery in your `robots.txt` file by uncommenting the sitemap line at the end of the file. TODO: make sure Cloudflare is not blocking sitemaps / are readable by GSC ## Slugs If you want to create SEO-friendly URLs, I recommend using the [`slugifiable`](https://github.com/rameerez/slugifiable) gem. This will allow you to have semantic URLs like ```ruby https://myapp.com/products/big-red-backpack ``` instead of ```ruby https://myapp.com/products/14 ``` The `slugifiable` gem does not come pre-configured by default in RailsFast because it's very app-dependent, but it should take you just ~5 minutes to set up! --- ## Analytics If you're using an analytics service like Google Analytics, Umami, SimpleAnalytics, etc. you can add its tag to `app/views/layouts/html_head/_analytics.html.erb`, and this will achieve three things: - It will add your analytics tag to all pages - Without cluttering the main layout (`app/views/layouts/application.html.erb`) - It's instantly reusable by other layouts in your app (like `app/views/layouts/devise.html.erb`) maintaining a single source of truth for all your analytics tags --- ## Caching RailsFast comes with everything ready and configured so you can just cache database-intensive parts of your with just the keyword `cache`: ```ruby <% @products.each do |product| %> <% cache product do %> <%= render product %> <% end %> <% end %> ``` Or, if you want to cache conditionally, you can do so with `cache_if`: ```ruby <% cache_if admin?, product do %> <%= render product %> <% end %> ``` Learn everything you can do with caching in the official [Rails caching](https://guides.rubyonrails.org/caching_with_rails.html) docs --- ## Attachments and cloud storage (S3-compatible) Uploading images and files is one of that features that looks trivial until you realize it's not. And mostly every app requires it: setting up user avatars is maybe one of the most common features. Thankfully, RailsFast comes with everything working out of the box, and you don't need to do mostly anything as long as you've configured your R2 credentials correctly in the [[getting-started/4-configuration|Configuration]] section. In the demo app that ships with RailsFast, all users can upload and update their avatar. This is done by just one line of code in the `User` model: ```ruby has_one_attached :avatar do |attachable| attachable.variant :thumb, resize_to_limit: [100, 100], format: :webp end ``` As you can see, you can indicate optional sizes and compression for better asset serving & on-page optimization. RailsFast comes with another two image sizes (variants) configured: `:small` and `:medium`, so you get an idea how to use it, but it's quite straightforward. If you want to add image (or file) attatchments to any other model in your app, just copy what's already working for user avatars, and read the official [Active Storage](https://guides.rubyonrails.org/active_storage_overview.html) docs. --- ## Abuse protection RailsFast ships with several measures you can use to protect against abuse and bots / DDoS / scrapers / bad actors. ## Cloudflare Turnstile (Captcha-like) Cloudflare Turnstile is a widget, like the famous CAPTCHA, that validates whether the user is human or not. This is useful to prevent bots from automatically / massively submitting information to your app, for example. As we saw in the auth section, all signup/login forms come already protected against abuse by Cloudflare Turnstile. If you want to add Turnstile (Captcha-like) protection to any other form on any other page, you just need to add the `cloudflare_turnstile` element to your view: ```erb <%= cloudflare_turnstile(theme: 'dark') %> ``` And then, in the corresponding controller action: ```ruby before_action :validate_cloudflare_turnstile, only: [:your_action] ``` Everything is configured in RailsFast so that these two lines are enough to add a fully functional Turnstile validation to any form in your app. We leverage the [`cloudflare-turnstile-rails`](https://github.com/vkononov/cloudflare-turnstile-rails) gem for this, in case you need more documentation in how to use it. ## Rate limiting I recommend setting up any rate-limiting countermeasures in Cloudflare (it's more advanced and kills any request before it actually hits your Rails app), but in case you don't want to / can't do it, you still have a very solid and production-ready mechanisim to easily rate limit requests in your RailsFast apps. Just add `rate_limit` to any controller: ```ruby class DemoController < ApplicationController rate_limit to: 3, within: 1.minute, by: -> { current_user.id }, only: :my_action end ``` For example, the rule above will block users from submitting more than 3 requests per minute to the `my_action` endpoint. Read more about `rate_limit` in the official [`RateLimiting`](https://api.rubyonrails.org/classes/ActionController/RateLimiting/ClassMethods.html) docs. --- ## Usage credits RailsFast ships with a fully working usage credits system, so you can keep track of how many credits each of your users has, and allow them to spend credits on your app. If you don't need this in your app, you can just ignore it! There's nothing else to do. If you do want usage credits in your app, everything is ready to go! You just need to define how your users get credits and how much each credit-consuming operation costs in `usage_credits.rb`. For example, you define how your users get credits like this: ```ruby stripe_config = Rails.configuration.x.railsfast.dig(:stripe, :plans) || {} subscription_plan :basic_plan do stripe_price month: stripe_config.dig(:basic_plan, :monthly), year: stripe_config.dig(:basic_plan, :yearly) gives 10_000.credits.every(:month) end ``` And you define the cost of operations like this: ```ruby operation :process_image do costs 10.credits + 1.credit_per(:mb) end ``` And then you can do this anywhere in your app: ```ruby @user.spend_credits_on(:process_image) do # Perform the actual operation here. # No credits will be spent if this block fails. end ``` Finally, to make everything work in both development and production, uncomment the credit fulfillment jobs from `config/recurring.yml`: ```yaml # Uncomment this so usage_credits refills credits in production: refill_credits: class: UsageCredits::FulfillmentJob queue: default schedule: every 5 minutes ``` RailsFast uses the [`usage_credits`](https://github.com/rameerez/usage_credits/) gem for this, please refer to the gem README to learn everything you can do and how to fully define credit-consuming operations and credit-giving plans. --- ## UI Overview RailsFast uses Tailwind 4.3+ for all its UI. The components are all Tailwind too, so if you're already familiar with it you'll feel right at home. You can do in RailsFast whatever you would usually do with any Tailwind project! You can either write your own UI components from scratch using Tailwind, or use any UI components library like Tailwind Pro or Shadcn, or any other you are familiar with. Just bring your components and you're ready to go! However, since RailsFast aims at providing you with a really fast speed to market, I thought it would be a good idea to include some very common and useful components you could just mix-and-match like LEGO blocks to quickly build marketing landing pages and UIs. I think that (as long as you already have the copy text ready) you could put together entire SEO-optimized, conversion-oriented marketing pages in 10 or 20 minutes, which I think it's extremely powerful.

RailsFast user authentication

You're not forced to use any RailsFast components, though: you can just ignore them if you'd rather use your own stuff. But I really think you'd love them, not only because they harness the full power of RailsFast, but because some of them (like the testimonials component) are so complete they could very well replace entire separate SaaS subscriptions that you'd need to achieve the same results. You can edit any component to tailor it to your needs and styles, too! --- ## Social Proof

RailsFast UI - Social proof component

The `social_proof` component lets you show social support to your app or product through a series of circle avatars. Use it like: ```ruby <%= render 'components/railsfast/marketing/social_proof', avatars: [ { image_url: "https://example.com/image.jpg", alt_text: "John Smith" }, ], rating: 4.9, max_avatars: 5, size: "size-10", overlap: "-ml-3", theme: "dark", avatar_border: "border-white/90", star_color: "text-white", overflow_count: "2.5k", trust_message: "2,500+ users love RailsFast" %> ``` `theme` can be: - `light` (default) - `dark` Parameters: - `avatars`: array of `{ image_url:, alt_text: }` (defaults to demo avatars) - `max_avatars`: max number of avatars to show (default: `5`) - `rating`: rating number (default: `5.0`) - `overflow_count`: shows a `+X` overflow pill (only shown when explicitly provided) - `trust_count`: trust count text (default: `"1,000+"`) - `trust_label`: label after the trust count (default: `"users"`) - `trust_message`: overrides the default “Trusted by …” line (supports HTML) - `size`: avatar size class (default: `"size-10"`) - `overlap`: avatar overlap class (default: `"-ml-3"`) - `text_color`: custom primary text color (Tailwind class or CSS color like `#fff`) - `secondary_text_color`: custom secondary text color (Tailwind class or CSS color like `#fff`) - `avatar_border`: custom avatar border class (overrides theme default) - `star_color`: custom star color (Tailwind class or CSS color like `#facc15`) --- ## Testimonials

RailsFast UI - Testimonials component

The `testimonials` component showcases user testimonials (in text, video, or photo format) in a fully responsive and beautiful **masonry grid**. The `testimonials` component can also be used as a **carousel** instead of a masonry grid, to highlight specific testimonials:

RailsFast UI - Testimonials component in carousel mode

The component draws all testimonials from the config file `config/testimonials.yml` Config structure: - `default` - `accent_color`: highlight/accent color shown in all testimonial cards (example: `"#df430d"`) - `accent_text_color`: text color on highlighted/accented text (example: `"#fff"`) - `star_max`: maximum number of stars on testimonial cards (default: `5`) - `default_avatar_url`: fallback avatar when `avatar_url` is missing - `development` / `test` / `production`: you can have different sets of configurations and testimonials per environment - `testimonials`: array of testimonial entries >[!TIP] To highlight any text in the testimonial, wrap any words in double brackets to highlight them with your accent color, like this: `Launched [[in a week]]` Example config: ```yaml default: &defaults accent_color: "#df430d" accent_text_color: "#fff" star_max: 5 default_avatar_url: "https://example.com/avatar.jpg" development: <<: *defaults testimonials: - kind: text text: "Launched [[in a week]] and seeing great user engagement." name: "Charlie Quinn" rating: 5 - kind: video quote: "Everything you need to build your app fast" name: "Morgan Casey" rating: 5 video: mp4_url: "https://example.com/video.mp4" poster_url: "https://example.com/image.jpg" ``` Testimonial entry (common fields): - `kind`: one of `text`, `image`, `text_image`, `video`, `tweet` - `name`: person name - `position`: job title (optional) - `company`: company name (optional) - `handle`: social handle (optional) - `avatar_url`: image URL (optional; falls back to `default_avatar_url`) - `rating`: number of stars to show (optional) - `date`: date string (optional) - `tags`: array of labels (optional; useful to curate subsets like `featured` or `demo`) For testimonials of different `kind`s, you can add specific fields: - `text` - `text`: testimonial body - `image` - `image_url`: image URL to display - `text_image` - `text`: testimonial body - `image_url`: image URL to display - `video` - `quote`: short highlighted quote - `video.mp4_url`: MP4 URL - `video.poster_url`: poster image URL (optional but recommended) - `tweet` - `text`: tweet body - `source.label`: source name (example: `"X"`) (optional) - `source.url`: source URL (optional) --- ## FAQ System

RailsFast UI - FAQ Frequently Asked Questions component

The Frequently Asked Questions section is arguably one of the highest-converting sections of any website, and even more important than the question and the answers themselves is whether the questions can be linked to uniquely and individually as "sub-pages". The FAQ component in RailsFast does this: not only it allows any arbitrary content in your answers, but it also provide you with unique links to each question, to help LLMs and search engines understand your website and product better, and to help users share specific questions with one unique link. It's almost as if with RailsFast you have FAQ questions automatically mounted as independent blog posts searchable by Google. The FAQ component renders a beautiful accordion, and auto-generates **unique, shareable links per question** (great for SEO, LLMs, and support). Use it like: ```ruby <%= render "components/railsfast/marketing/faq", title: "Frequently Asked Questions", subtitle: "Everything you need to know before getting started.", theme: "light" %> ``` The component draws all questions from `config/faqs.yml` (via `Rails.configuration.x.faq[:faqs]`). Linking / stable URLs: - Each question gets an `id="faq-..."` so it can be linked as `#faq-your-question-slug`. - If you rely on stable links, **set an explicit `id` per FAQ item** so you can safely edit the question text later. Example config: ```yaml development: faqs: - id: pricing question: "Do you have a free trial?" answer: |

Yes — you can try it for 14 days.

``` >[!IMPORTANT] If you don’t set `id`, the anchor is derived from the question text. Since each question gets its unique link based on the question text, **do not** change the question text or it'll break the link. Parameters: - `items`: array of FAQ items (optional; overrides config) - `ids`: only include specific FAQ IDs (optional) - `limit`: max number of items to show (optional) - `title`: section heading (optional) - `subtitle`: section subheading (optional) - `section_id`: HTML id for the whole section (default: `"faq"`) - `multiple_open`: allow multiple items to be open at once (default: `true`) - `padding`: section padding classes (default: `"py-12 sm:py-16"`) - `theme`: `light` (default) or `dark` Style overrides (override theme defaults): - `item_bg`, `item_border`, `item_shadow`, `item_rounded`, `item_hover` - `question_text`, `answer_text`, `icon_color` - `item_gap` --- ## Features Use the `features` component to showcase features of your product. You can use it in a handful of `mode`s; in all of them you pass an `items` array and it renders a beautiful features section. Use it like: ```ruby <%= render "components/railsfast/marketing/features", mode: :grid, title: "Everything you need", subtitle: "A fast overview of what you get out of the box.", title_alignment: "center", padding: "py-16 sm:py-24", items: [ { title: "Fast setup", description: "Ship in days, not weeks.", icon: "bolt" }, { title: "Secure by default", description: "Sane defaults everywhere.", icon: "shield-check" } ] %> ``` Common parameters (wrapper): - `mode`: one of the modes below (default: `:grid`) - `items`: array of feature items (required) - `title`: section title (optional) - `subtitle`: section subtitle (optional) - `title_alignment`: `"center"` (default), `"left"`, `"right"` - `title_max_width`: `"2xl"` (default), `"3xl"`, `"4xl"`, `"full"` - `padding`: section padding classes (default: `"py-16 sm:py-24"`) Icons: - For the modes that support it, `icon` uses [Heroicons](https://heroicons.com) names (example: `"bolt"`, `"shield-check"`). ## Feature modes ### Grid mode `:grid`: card grid with optional badges, bullet points, and CTA. Good to showcase multiple features at once

RailsFast UI - Grid features component

Item fields: `{ title:, description:, icon:, badge:, points:, cta: }` ### Alternating mode `:alternating`: the bread and butter of features in landing pages. Rows that alternate their alignment left and right, with big images on the other side. Good for telling a story

RailsFast UI - Alternating features component

Item fields: `{ title:, description:, image:, image_class:, points: }` Specific paramenters: - `image_aspect`: `"video"` (default), `"square"`, `"photo"` - `layout`: `"balanced"` (default), `"image_large"`, `"content_large"` - `compact`: `true`/`false` ### Bento mode `:bento`: “bento box” mosaic for mixed-size, more visual feature blocks

RailsFast UI - Bento features component

Item fields: `{ title:, description:, bento_size:, image:, image_position:, icon:, badge:, points:, cta:, extra_content: }` ### Icons mode `:icons`: best for a section of 3 highlighted features

RailsFast UI - Icons features component

Item fields: `{ icon:, title:, description:, cta:, accent_color: }` Specific parameters: - `columns`: `2`, `3` (default), `4`, `6` - `icon_style`: `"rounded"` (default), `"circle"`, `"square"`, `"none"` - `icon_size`: `"small"`, `"medium"` (default), `"large"` - `icon_variant`: `:solid` (default) or `:outline` - `accent_color`: hex/CSS color (example: `"#84cc16"`) — can also be set per item via `accent_color` - `alignment`: `"center"` (default) or `"left"` - `compact`: `true`/`false` ### List mode `:list`: simple checkmark list in different columns that looks clean and organized

RailsFast UI - List features component

Item fields: either a string (`"Simple feature"`) or `{ title:, description: }` --- ## Call to action ## Call To Action (CTA) The `cta` component is a prominent “call to action” section (usually near the bottom of a landing page) to convert readers into signups, demo views, or purchases.

RailsFast UI - CTA

>[!TIP] This component intentionally has **no background** and doesn’t hardcode text colors — style the parent container and it will inherit. Use it like: ```ruby
<%= render "components/railsfast/marketing/cta", title: "Ready to get started?", subtitle: "This is the perfect spot for your first major call-to-action (CTA). Users have just finished reading about your product's main benefits and are primed to take the next step. Use this CTA to convert interest into action: invite them to get started or explore a live demo.", primary_button: { text: "Get started now", url: new_user_registration_path, style: "solid", size: "medium" }, secondary_button: { text: "View Demo", url: "#", style: "outline", show_arrow: true }, layout: "centered", icon: "rocket-launch", stats: [ { value: "10K+", label: "Customers" }, { value: "+40%", label: "Revenue" }, { value: "99.9%", label: "Uptime" } ] %>
``` Parameters: - `title`: main heading text (default: `"Ready to get started?"`) - `subtitle`: supporting text (optional) - `layout`: `"centered"` (default), `"split"`, `"offset"` - `container`: `"normal"` (default), `"wide"`, `"full"` - `icon`: optional Heroicon name (example: `"rocket-launch"`) - `stats`: optional array of `{ value:, label: }` - `primary_button`: hash with: - `text`, `url` - `style`: `"solid"` (default), `"outline"`, `"ghost"` - `size`: `"small"`, `"medium"`, `"large"` (default), `"xlarge"` - `icon`: optional Heroicon name - `color`, `text_color`: optional hex/CSS colors (example: `"#df430d"`) - `data`: optional Rails `data:` hash - `secondary_button` (optional): hash with: - `text`, `url` - `style`: `"outline"` (default), `"solid"`, `"ghost"` - `icon`: optional Heroicon name - `show_arrow`: `true`/`false` - `data`: optional Rails `data:` hash ## Call To Action Card (CTA Card) The `cta_card` component is an attention grabber: a single CTA inside a card, with optional gradients, patterns, and a featured image.

RailsFast UI - CTA Card

Use it like: ```ruby
<%= render "components/railsfast/marketing/cta_card", title: "Another catchy CTA in a card", subtitle: "Use eye-catching gradients to grab users' attention and drive them to your CTA.", button: { text: "Start now", url: new_user_registration_path, style: "solid", icon: "arrow-right", color: "white", data: { turbo: false } }, image: { url: "https://placehold.co/600x400/e4e4e4/c4c4c4?text=Your+featured+image+here", alt: "RailsFast dashboard screenshot", position: "right" }, background: "gradient", gradient_colors: ["#00b09b", "#96c93d"], image_effects: "tilted" %>
``` Parameters: - `title`: main heading text - `subtitle`: supporting text - `button`: hash with `text`, `url`, `style` (`"solid"`, `"outline"`, `"ghost"`), optional `icon`, optional `color`/`text_color`, optional `data` - `image` (optional): hash with `url`, `alt`, `position` (`"right"`, `"left"`, `"background"`) - `background`: `"gradient"` (default), `"solid"`, `"pattern"` - `gradient_colors`: array of 2–3 colors (Tailwind names or hex/CSS colors) - `background_color`: base color for `"solid"` / `"pattern"` - `decorative_blobs`: `true`/`false` (default: `true`) - `card_style`: `"elevated"` (default), `"bordered"`, `"minimal"` - `image_effects`: `"tilted"` (default), `"shadow"`, `"glow"`, `"none"` --- ## Pricing page

RailsFast UI - Pricing page and pricing cards

RailsFast also provides a fully working pricing page with pricing cards, a toggle to choose between monthly / yearly billing, and more. As described in the [[features/0-payments|Payments]] section, this pricing page is already fully integrated with the [`pricing_plans`](https://github.com/rameerez/pricing_plans) gem, and it's not just front-end / aesthetics: all plans can be purchased and whatever is defined in the plan itself is immediately enforceable app-wide. The pricing page uses the plans defined in `pricing_plans` if you’ve configured the gem, otherwise it falls back to the placeholder `@static_plans` in the `DemoController`, so the page still looks good. What you’ll likely customize: - **Your actual plans**: define them in `config/initializers/pricing_plans.rb` and plug in your Stripe Price IDs in `config/railsfast/railsfast.yml` as described in [[features/0-payments|Payments]]. - **Which plan is “Most Popular”**: mark a plan as highlighted in `pricing_plans.rb` (RailsFast auto-detects it), or pass a `popular_plan_id:` manually. - **Monthly/Yearly toggle**: `show_toggle: true/false` - **Scalable / enterprise slider card**: `show_scalable: true/false` + `scalable_plans: [...]` - **Brand theming**: pass `accent:` (hex/CSS color string) --- ## Other components ## Navbar

RailsFast UI - Navbar

It's a fully responsive navbar that works on desktop as well as in mobile, with a collapsible menu. Use it like: ```ruby <%= render 'layouts/partials/navbar', variant: 'floating' %> ``` `variant` can be: - `sticky` - `regular` - `floating` ## Footer

RailsFast UI - Footer

## Other components RailsFast uses the `tailwindcss-stimulus-components` library, so all these other components are also available and ready to use: - `Alert` - `Autosave` - `Color Preview` - `Dropdown` - `Modal` - `Popover` - `Slideover` - `Tabs` - `Toggle` To learn how to use these components, read the official [`tailwindcss-stimulus-components`](https://github.com/excid3/tailwindcss-stimulus-components). --- ## Customizing components RailsFast components are meant to be edited. The defaults are great, but your product should look like **your** product. If you want to customize a component provided by RailsFast, here’s the simplest workflow: - **Copy the component out of the RailsFast folder before editing**: take the partial from `app/views/components/railsfast/...` and copy it into `app/views/components/...` - **Edit your component**: restyle, change layout, edit copy, whatever - **Keep upstream updates clean**: since your customized component lives outside `components/railsfast`, you can keep pulling template updates without getting messy conflicts in your edited files. >[!TIP] One useful idea is to ask an AI to refactor the Tailwind classes of a component you'd like restyled. It works best if you also paste a “reference” of what you like (a picture, or HTML code), so the AI can get the vibe better If you'd rather override the RailsFast components themselves in place, you'd need to add it to the `.gitattributes` file with `merge=ours`, like this: ```gitattributes app/views/components/marketing/_hero.html.erb merge=ours ``` So that when I update the RailsFast template and you do fetch the changes, you don't get your custom component overriden by the upstream template changes. --- ## AI image generation --- title: AI image generation sort: 2 --- --- ## LLMs and AI chats --- title: LLMs and AI chats sort: 3 --- --- ## AI, vector databases, and RAG RailsFast includes built-in support for AI-powered features, vector search, and Retrieval-Augmented Generation (RAG) to help you build intelligent applications. ## Overview Modern Rails applications can leverage AI for: - Semantic search and similarity matching - Content recommendations - Document question-answering - Intelligent data retrieval - Contextual assistance ## Vector Databases Vector databases store embeddings (numerical representations of text) that enable semantic search. ### Supported Solutions RailsFast works with: - **pgvector** - PostgreSQL extension (recommended for most projects) - **Pinecone** - Managed vector database - **Weaviate** - Open-source vector search engine - **Milvus** - Scalable vector database ### Using pgvector pgvector is included in your PostgreSQL setup. #### Enable the Extension ```ruby # db/migrate/xxx_enable_pgvector.rb class EnablePgvector < ActiveRecord::Migration[8.0] def change enable_extension 'vector' end end ``` #### Create a Model with Embeddings ```ruby # db/migrate/xxx_add_embeddings_to_documents.rb class AddEmbeddingsToDocuments < ActiveRecord::Migration[8.0] def change add_column :documents, :embedding, :vector, limit: 1536 add_index :documents, :embedding, using: :ivfflat, opclass: :vector_cosine_ops end end ``` ```ruby # app/models/document.rb class Document < ApplicationRecord has_neighbors :embedding end ``` ## Generating Embeddings ### Using OpenAI Install the OpenAI gem: ```ruby # Gemfile gem 'ruby-openai' ``` Generate embeddings: ```ruby # app/services/embedding_service.rb class EmbeddingService def self.generate(text) client = OpenAI::Client.new( access_token: Rails.application.credentials.dig(:openai, :api_key) ) response = client.embeddings( parameters: { model: "text-embedding-3-small", input: text } ) response.dig("data", 0, "embedding") end end ``` Use it in your model: ```ruby class Document < ApplicationRecord has_neighbors :embedding after_save :generate_embedding, if: -> { content_changed? } private def generate_embedding update_column :embedding, EmbeddingService.generate(content) end end ``` ## Semantic Search ### Finding Similar Documents ```ruby # Find documents similar to a query query = "How do I set up payments?" query_embedding = EmbeddingService.generate(query) similar_docs = Document.nearest_neighbors( :embedding, query_embedding, distance: "cosine" ).limit(5) ``` ### Building a Search Controller ```ruby # app/controllers/search_controller.rb class SearchController < ApplicationController def show @query = params[:q] return if @query.blank? query_embedding = EmbeddingService.generate(@query) @results = Document.nearest_neighbors( :embedding, query_embedding, distance: "cosine" ).limit(10) end end ``` ## RAG (Retrieval-Augmented Generation) RAG combines vector search with LLMs to provide contextual answers. ### Basic RAG Implementation ```ruby # app/services/rag_service.rb class RagService def self.answer_question(question) # 1. Find relevant documents query_embedding = EmbeddingService.generate(question) relevant_docs = Document.nearest_neighbors( :embedding, query_embedding, distance: "cosine" ).limit(3) # 2. Build context from documents context = relevant_docs.map(&:content).join("\n\n") # 3. Generate answer with LLM client = OpenAI::Client.new( access_token: Rails.application.credentials.dig(:openai, :api_key) ) response = client.chat( parameters: { model: "gpt-4-turbo-preview", messages: [ { role: "system", content: "Answer questions based on the provided context." }, { role: "user", content: "Context:\n#{context}\n\nQuestion: #{question}" } ] } ) response.dig("choices", 0, "message", "content") end end ``` ### RAG Controller ```ruby # app/controllers/ai_assistant_controller.rb class AiAssistantController < ApplicationController def ask @question = params[:question] @answer = RagService.answer_question(@question) respond_to do |format| format.json { render json: { answer: @answer } } format.html end end end ``` ## Advanced Patterns ### Hybrid Search Combine traditional search with vector search: ```ruby class Document < ApplicationRecord has_neighbors :embedding def self.hybrid_search(query, limit: 10) # Vector search query_embedding = EmbeddingService.generate(query) vector_results = nearest_neighbors( :embedding, query_embedding, distance: "cosine" ).limit(limit * 2) # Keyword search keyword_results = where("content ILIKE ?", "%#{query}%") .limit(limit * 2) # Combine and deduplicate (vector_results + keyword_results).uniq.take(limit) end end ``` ### Caching Embeddings Cache embeddings to reduce API costs: ```ruby class EmbeddingService def self.generate(text) cache_key = "embedding:#{Digest::SHA256.hexdigest(text)}" Rails.cache.fetch(cache_key, expires_in: 30.days) do # API call to generate embedding client = OpenAI::Client.new(...) # ... generate and return embedding end end end ``` ### Batch Processing Generate embeddings in background jobs: ```ruby class GenerateEmbeddingsJob < ApplicationJob queue_as :default def perform(document_ids) documents = Document.where(id: document_ids, embedding: nil) documents.each do |doc| doc.update(embedding: EmbeddingService.generate(doc.content)) end end end # Usage GenerateEmbeddingsJob.perform_later(Document.pluck(:id)) ``` ## Configuration Add your AI service credentials: ```bash EDITOR="cursor --wait" bin/rails credentials:edit ``` ```yaml openai: api_key: sk-... # Or for other services anthropic: api_key: sk-ant-... pinecone: api_key: ... environment: us-east-1-aws ``` ## Performance Tips 1. **Index your embeddings**: Use appropriate index types (IVFFlat, HNSW) 2. **Batch embed operations**: Generate embeddings in batches for better throughput 3. **Cache frequently used embeddings**: Reduce API costs 4. **Use smaller models when possible**: `text-embedding-3-small` is faster and cheaper 5. **Implement retry logic**: Handle API failures gracefully ## Cost Optimization - Cache embeddings aggressively - Use background jobs for non-urgent embedding generation - Choose appropriate embedding models (smaller = cheaper) - Implement rate limiting on user queries - Monitor usage and set budgets ## Example Use Cases ### Documentation Search ```ruby # Find relevant docs for a user question question = "How do I configure email?" answer = RagService.answer_question(question) ``` ### Content Recommendations ```ruby # Find similar articles article = Article.find(params[:id]) similar = Article.nearest_neighbors(:embedding, article.embedding).limit(5) ``` ### Intelligent Support Bot ```ruby # Answer customer questions customer_query = "Do you offer refunds?" support_answer = RagService.answer_question(customer_query) ``` ## Resources - [pgvector GitHub](https://github.com/pgvector/pgvector) - [Neighbor gem (Rails integration)](https://github.com/ankane/neighbor) - [OpenAI Embeddings Guide](https://platform.openai.com/docs/guides/embeddings) - [RAG Explained](https://www.anthropic.com/research/rag) ## See Also - [[background-jobs|Background Jobs]] - For async embedding generation - [[configuration|Configuration]] - Setting up AI credentials - [[development|Development]] - Testing AI features locally --- ## How to get a 10/10 deliverability score for your emails RailsFast can achieve a 10/10 email deliverability out of the box, as tested by mail-tester.com

RailsFast Email Deliverability Guide

To achieve that, when configuring AWS SES for sending email, make sure to strictly follow these steps: - Navigate to your Amazon SES dashboard - Add your project domain name as a SES identity - To do that, on the sidebar, navigate to Configuration > Identities and click [ Create Identity ] - In the new page, select "Domain" as the new identity type - Enter your domain - Activate the "Use a custom MAIL FROM domain" checkbox - In the MAIL FROM field, input something like `mail.` - Scroll down and select "Easy DKIM" - Select RSA_2048_BIT - Leave "DKIM Signatures" active - Click on the [ Crete identity ] button - On the new identiy page, you'll see three main sections: DKIM, MAIL FROM, and DMARC. For each section, there's a "Publish DNS records" unfoldable item. If you click it, you'll see the DNS records you need to add to your domain's DNS to clear each section. It's a somewhat tedious job, but make sure you add all records right. - Once you're done adding all records, scroll up in the indentity page in SES and click the refresh button. If everything went right, you should see your "Identity status: Verified", and the DKIM and MAIL FROM sections marked as successful. If that did not happen, give your DNS time to propagate (anywhere from some minutes to a few hours) and try again. - RailsFast is configured with best email practices so that when you send a transactional email from Rails you should get a perfect 10/10 score (or pretty close to it) in deliverability: you can test it at mail-tester.com --- ## Kamal - Configure a container registry Kamal uses your local development machine as a Docker container registry by default. This means that, after the Docker image containing your app is built, it's stored in your local computer and needs to be uploaded from your computer to the production server for deployment. If your internet connection is not the best, this may slow down your total deployment time from the time you hit `kamal deploy` until the time everything is live in production. Also, you may be filling up your local machine with big stale Docker images. > [!TIP] > Using a remote container registry usually speeds up deployment times. There are many remote container registry options: Docker Hub, ghcr.io, GitLab container registry, etc. Some are paid, some are free (but always public, which is not supported on RailsFast). What I found to be easiest to configure and integrate with Kamal (RailsFast) is AWS ECR. ## How to use AWS ECR with Kamal as container registry AWS ECR costs close to nothing (I paid $0.32 –yes, 32 cents– last month), and it's very straightforward to integrate with Kamal using the AWS CLI. And since we're already using AWS for storage (S3) and emailing (SES) in RailsFast, it makes sense to also leverage their container registry. ### Install and configure the AWS CLI First, [install and configure the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html). Then, at the end of the Kamal secrets file under `.kamal/secrets`, uncomment this line: ``` AWS_ECR_PASSWORD=$(aws ecr get-login-password --region us-east-1 --profile default) ``` Make sure to change the `us-east-1` for the region you're using in ECR, or leave it like that if you're fine with us-east-1. > [!INFO] > This is a secure way of sharing your AWS ECR credentials with Kamal for deployment. No password, API token or anything sensible ever gets commited or made public. Upon every deployment, Kamal will call the AWS CLI on your local computer to get a temporary login password for ECR, and will load that token as the `AWS_ECR_PASSWORD` ENV var in the containers that need it. ### Create a private registry on AWS ECR Go to your AWS console and navigate to [ECR (Elastic Container Registry)](https://us-east-1.console.aws.amazon.com/ecr/private-registry/repositories?region=us-east-1). Click on the ` [ Create repository ] ` button. Give your registry a name with a username in front. Example: use `myusername/myproject`, not just `myproject`. This is because Docker container registries require username namespacing (a container must belong to a username). Tip: just use the same username you use on GitHub and the same project name you use on GitHub. Keep the rest of the settings default and click on `[ Create ]` Since we're at it, let's do a couple more clicks to limit how many versions of our Docker images the registry is going to store (saving us storage money!) Select your recently created repository from the list of private repositories. On top, click `[Actions ▼]` and then `Lifecycle policies`. Click on `[Create rule]` to create a new rule, and in the new screen leave everything by default but where it says: `Image tag status` (select: `Any`). Then, under `Match criteria`, I suggest you select `Days since image created` or `Image count`. In the box below, you can specify for how many days you want to store each version, or how many version (images) in total you want to storage. I personally just select `Image count`, and set it to only save the last `30` images. Click `[Save]` and `[Confirm]` and you won't be storing old, stale versions forever. ### Edit `deploy.yml` Now that we have everything configured in ECR, in your `config/deploy.yml` let Kamal know which container registry you're using: - Change your `image` name to match the name you gave it in AWS ECR. Example, if before you had something like: ```yaml image: myproject ``` Edit it to make it match what you had on ECR: ```yaml image: myusername/myproject ``` - Remove the `localhost:5555` `server` under the `registry` section and uncomment the placeholder remote container registry options (`server`, `username`, `password`), to end up with something like this: ```yaml registry: server: 1234.dkr.ecr.us-east-1.amazonaws.com username: AWS password: - AWS_ECR_PASSWORD ``` Replace the placeholder `1234.dkr.ecr.us-east-1.amazonaws.com` with the actual repository URI you can see on ECR in your private repositories list. > [!IMPORTANT] > If you're using a remote builder, make sure to pass the `AWS_ECR_PASSWORD` ENV var to the builder too, under the `secrets` section of the `builder` key: > > ``` > builder: > secrets: > - RAILS_MASTER_KEY > - AWS_ECR_PASSWORD >``` And you're done! You can check the remote Docker container registry in AWS ECR is set up correctly in Kamal by running: ```bash kamal registry setup ``` And seeing that it logs in correctly. The next time you deploy using `kamal deploy`, Kamal will push and pull the Docker images from ECR instead of from your local computer registry. --- You can learn more about Kamal and container registries in the [official Kamal docs](https://kamal-deploy.org/docs/configuration/docker-registry/) --- ## Kamal - Configure a remote builder > [!IMPORTANT] > If you're on macOS, especially M1, M2, M3... (Apple Silicon), you may **have to** use a remote builder or your build process may fail. A remote builder is just a server that builds your app for you, instead of doing the build work in your local machine. You send your code to the remote builder, and it produces the deployeable Docker image. This is useful, for example, in case your local development machine is too slow building, and you want to speed things up. It may also me something you **need to** to if you're on macOS. The newest macOS machines (the Apple Silicon family: M1, M2, M3, etc.) may find issues with Docker (the underlying technology Kamal uses for building and deploying your app); **this is fully solvable** if you use a remote builder instead of your local Mac for building. ## How to set up a remote builder server in Kamal Setting up a remote builder couldn't be easier: just spin up a new server on Hetzner exactly as you did on the [[getting-started/2-quickstart|Quickstart]]. In a nutshell: select a server and a location, add your SSH key, __no need__ for backups this time, and in the **Cloud Config** box, paste this: ```yaml #cloud-config runcmd: - bash -lc 'set -euo pipefail; wget -qO /root/railsfast-setup.sh https://setup.railsfast.com; chmod +x /root/railsfast-setup.sh; /root/railsfast-setup.sh 2>&1 | tee -a /var/log/railsfast-setup.log && reboot' ``` Create the server and wait for the setup script to finish as described in the [[getting-started/2-quickstart|Quickstart]]. Then, in your `deploy.yml` file, uncomment the remote builder machine section under the `builder` key: ```yaml builder: arch: amd64 # Uncomment this: local: false remote: ssh://docker@5.6.7.8 args: RUBY_VERSION: 3.4.7 secrets: - RAILS_MASTER_KEY ``` And change the placeholder `5.6.7.8` IP for the actual IP of the server you've just created. That's it! Try deploying with `kamal deploy` now and your setup will use the remote builder for building, instead of your local machine. --- ## Migrating Existing Project Here's the simplest, most reliable way to "adopt" RailsFast into an existing Rails project and start getting updates. ### Goal - Link your project’s history to the RailsFast template so future updates are just normal git merges. - Keep your current code as-is during adoption. - Preserve secrets/config with merge guards. ### One-time adoption (manual) 1) Prep - Commit or stash everything: `git status` should be clean. - Create a safety branch: `git checkout -b adopt-railsfast-backup` 2) Add RailsFast as a remote ```bash git remote add railsfast git@github.com:railsfast/railsfast-base.git git fetch railsfast --prune ``` 3) Establish a baseline relationship (don’t change your files) - This records the template as a merge parent without altering your tree. ```bash git merge --allow-unrelated-histories -s ours --no-ff -m "Adopt RailsFast upstream at baseline" railsfast/main ``` - Result: histories are now related. Future `git merge railsfast/main` will bring only changes made in the template since this baseline. 4) Add merge guards so protected files always keep your local version - If you already have `.gitattributes`, add lines like: ```bash echo '# RailsFast: Preserve local configuration during template merges' >> .gitattributes echo 'Dockerfile merge=ours' >> .gitattributes echo '.kamal/secrets merge=ours' >> .gitattributes echo 'app/views/pwa/manifest.json.erb merge=ours' >> .gitattributes echo 'config/application.rb merge=ours' >> .gitattributes echo 'config/database.yml merge=ours' >> .gitattributes echo 'config/deploy.yml merge=ours' >> .gitattributes echo 'config/railsfast.yml merge=ours' >> .gitattributes echo 'config/credentials.yml.enc merge=ours' >> .gitattributes echo 'config/master.key merge=ours' >> .gitattributes echo 'config/db.key merge=ours' >> .gitattributes ``` - Configure the merge driver + rerere: ```bash git config merge.ours.driver true git config rerere.enabled true git add .gitattributes git commit -m "Configure RailsFast merge guards" ``` 5) (Optional) Record metadata for RailsFast CLI status - If your repo already includes `bin/railsfast`, you can record the baseline and remote without changing your app: ```bash bin/railsfast init --yes --skip-rename --skip-setup ``` - This writes `.railsfast/config.json` and remembers the remote/branch/baseline. If you don’t have the scripts yet, you can skip this step. ### Verifications - Check relation and baseline: ```bash git log --oneline --graph --decorate --all | head -n 50 ``` - See behind count: ```bash git rev-list --count HEAD..railsfast/main ``` --- ## Deploy multiple Rails apps to the same server Running multiple apps in the same VPS server is trivial with RailsFast. Just configure `deploy.yml` to deploy to the same server IP, that's it! Nothing else to do on your side. All apps in the same server will have separate databases and run in separate containers so there's no risk of cross-pollination whatsoever. Your RailsFast apps are like silos, they just happen to be in the same VPS! --- ## Updating RailsFast Updating any template is always going to be a bit difficult, because as you start building your app on top of it many files will diverge from the original template, and conflicts will naturally arise. The worst-case scenario is you need to go file-by-file reviewing the template updates and deciding what to incorporate into your app. HOWEVER, RailsFast is designed so the amount of effort you need to do is minimized, and ideally you can keep pulling RailsFast improvements into your app without much work. ## Make your life easier for updating As we covered in the [[ui-components/9-customizing|Customizing Components]] section, the best practice if you plan to customize RailsFast components, is that you **don’t edit the RailsFast components in-place**, instead, copy the component you want to change into your own folder and edit your copy. ## Protect your customizations (merge guards) At some point, you will inevitably edit RailsFast core files. If you *did* edit files that ship with RailsFast and that you can't copy easily into your own folder (for example, layouts or auth views), you can tell Git to always keep *your* version on merges by adding merge guards in `.gitattributes`. Example: ```gitattributes # Keep my customized files when merging template updates app/views/devise/** merge=ours ``` This way, if for example you update all your authentication screens to match your branding and design, when updating RailsFast your files will get priority, overriding the update, and you won't lose your work (you won't get updates on those files, though) >[!WARNING] My recommendation is you use this only for individual files or small folders. If you guard huge paths like `app/views/**`, you will also silently skip upstream improvements (including fixes) for those files. ## How to update RailsFast Since we configured the remote in the quickstart, we can just `pull` the latest RailsFast changes: ```bash git fetch railsfast --prune ``` And then merge them with your project: ```bash git merge railsfast/main ``` If you get conflicts, resolve them (Git will respect your `.gitattributes` merge guards), and then commit the merge. ## After updating Run any new migrations: ```bash bin/rails db:migrate ``` Restart your dev server (`bin/dev`) and make sure nothing got broken in the update and everything works. ---