Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Delegating 404s to builder.io in Rails

Delegating 404s to builder.io in Rails

Give builder.io a chance to respond to paths that you don't have a route for before serving up a 404 page:

  1. In Gemfile, add gem 'rack-cors' and bundle.

  2. In config/application.rb, add:

     config.middleware.insert_before 0, Rack::Cors do
       allow do
         origins '*'
         resource '*', headers: :any, methods: [:get, :post, :options]
       end
     end
  3. In config/application.rb, add:

    config.exceptions_app = self.routes
  4. rails generate controller not_found builder

  5. In config/routes.rb, replace the generated route with:

    match "/404", to: "not_found#builder", via: :all
  6. In app/controllers/not_found_controller.rb, enhance the action:

    class NotFoundController < ApplicationController
      def builder
        builder_url = "https://builder.io/api/v1/html/page?url=#{request.original_url}&apiKey=#{ENV.fetch("BUILDER_API_KEY")}"
    
        builder_response = HTTParty.get(builder_url, follow_redirects: true)
    
        if builder_response.code != 404
          data = JSON.parse(builder_response.body).fetch("data")
    
          @content = data.fetch("html").html_safe
        else
          render :not_found, status: 404
        end
      end
    end
  7. Create a folder app/views/not_found and add a file within builder.html.erb:

    <%= @content %>
  8. Create a file app/views/not_found/not_found.html.erb with your usual 404 content. If you're copying in an entire document from a static public/404.html, then you may want to:

    render :not_found, status: 404, layout: false
  9. If you've got one, rm public/404.html.

  10. Test locally: in config/environments/development.rb,

    config.consider_all_requests_local = false
  11. Use a layout specifically for builder.io pages if you want to:

    render layout: "builder"

    And then create builder.html.erb in app/views/layouts.

    Alternatively, use layout: false and put your entire document, including <html>, <head>, etc, in found.html.erb.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.