Skip to content

Instantly share code, notes, and snippets.

@peterc
Last active February 20, 2025 18:20
Show Gist options
  • Save peterc/91d9bc6397eb93e65897c1826f35e345 to your computer and use it in GitHub Desktop.
Save peterc/91d9bc6397eb93e65897c1826f35e345 to your computer and use it in GitHub Desktop.
How to set up a basic Sinatra + React webapp

How to set up a basic Sinatra + React webapp in 2025

First, create the app folder and set up Sinatra:

mkdir my-sinatra-react-app
cd my-sinatra-react-app

bundle init
echo "gem 'sinatra'" >> Gemfile
echo "gem 'puma'" >> Gemfile
bundle install

Then populate app.rb like so:

require 'sinatra'
require 'json'

before do
  content_type :json
  headers 'Access-Control-Allow-Origin' => '*' if settings.development?
end

set :public_folder, 'public'

# API routes
get '/api/hello' do
  { message: 'Hello from Sinatra!' }.to_json
end

get '/' do
  content_type 'text/html'
  send_file File.join(settings.public_folder, 'index.html')
end

Next we can get the JavaScript part sorted:

npm create vite@latest client -- --template react
cd client

# Install frontend dependencies
npm install
npm install -D tailwindcss postcss autoprefixer

# Initialize Tailwind
npx tailwindcss init -p

Tailwind, Vite, and React need a bit of configuring at this point.

client/tailwind.config.js can become:

/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

client/vite.config.js needs tweaking the proxy through the Sinatra app during dev:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: {
    proxy: {
      '/api': 'http://localhost:4567'  // Assuming Sinatra runs on 4567
    }
  },
  build: {
    outDir: '../public'
  }
})

client/src/App.jsx can then become:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: {
    proxy: {
      '/api': 'http://localhost:4567'  // Assuming Sinatra runs on 4567
    }
  },
  build: {
    outDir: '../public'
  }
})

And we need this in client/src/index.css:

@tailwind base;
@tailwind components;
@tailwind utilities;

Finally in one terminal run this to get the Sinatra backend running:

ruby app.rb

Then in dev, run this to use Vite:

cd client
npm run dev

For deployment or to test using Sinatra alone:

cd client
npm run build
cd ..
ruby app.rb
@elhalvers
Copy link

Cool! My Tailwind isn't working but I'll work on that. Thanks! : )

@peterc
Copy link
Author

peterc commented Jan 17, 2025

I'll take a look later today, though mine worked when I ran through and tested it before. Let me know if you resolve it as I'd like to make this as accurate as possible :)

@elhalvers
Copy link

No Tailwind still. Built the app from scratch again to see if I missed anything. All the functionality is there and if I leave the default css in the index.css file, it renders that css, but appending or replacing:

@tailwind base;
@tailwind components;
@tailwind utilities;

doesn't seem to do anything.

@peterc
Copy link
Author

peterc commented Jan 17, 2025

Are you running under Vite with npm run dev in the client folder when doing this, BTW? That's how you'll get everything working dynamically in dev before you do the final build. (It's a bit back to front compared to building a Sinatra app normally as you access it through Vite in dev and it proxies to Sinatra. In prod, you use the assets built with npm run build.)

I'll walk through the steps again from scratch again tomorrow, but in my previous attempt it does seem to be working okay on my system at least (but that's not the most useful thing to hear, I know!) :)

@elhalvers
Copy link

Cool! Yes, I followed your dev example.

cd client
npm run dev

Thanks! : )

@scalp42
Copy link

scalp42 commented Jan 18, 2025

hey thanks for sharing @peterc and trying to help! That's it. That's the comment.

@peterc
Copy link
Author

peterc commented Jan 18, 2025

Added a note into the article to stress this point :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment