├── README.md ├── application_helper.rb ├── basic.rb ├── postcss.config.js ├── template.rb └── templates ├── _flashes.html.erb ├── _navbar.html.erb └── _navbar_basic.html.erb /README.md: -------------------------------------------------------------------------------- 1 | Inspired by the [Le Wagon Rails templates](https://github.com/lewagon/rails-templates) 2 | 3 | ## Create a new repo 4 | 5 | 2 templates available, with or without devise.
6 | Run one of the commands below and change _PROJECT-NAME_ to the name of your new project. 7 | 8 | 9 | ### Rails 6 | Tailwind 2.0 🏳️‍🌈 | Devise 🔐 10 | - styled navbar 11 | - styled devise/views from [thomasvanholder/devise](https://github.com/thomasvanholder/devise) 12 | - javascript/components from [thomasvanholder/tailwind-components](https://github.com/thomasvanholder/tailwind-components) 13 | - assets and icons from [thomasvanholder/assets](https://github.com/thomasvanholder/assets) 14 | - first and last name added to user model 15 | 16 | ```bash 17 | rails new \ 18 | --database postgresql \ 19 | --webpack \ 20 | -m https://raw.githubusercontent.com/thomasvanholder/jumpstart/main/template.rb \ 21 | PROJECT-NAME 22 | ``` 23 | 24 | ### Rails 6 | Tailwind 2.0 🏳️‍🌈 25 | - styled navbar 26 | - javascript/components from [thomasvanholder/tailwind-components](https://github.com/thomasvanholder/tailwind-components) 27 | - assets and icons from [thomasvanholder/assets](https://github.com/thomasvanholder/assets) 28 | 29 | ```bash 30 | rails new \ 31 | --database postgresql \ 32 | --webpack \ 33 | -m https://raw.githubusercontent.com/thomasvanholder/jumpstart/main/basic.rb \ 34 | PROJECT-NAME 35 | ``` 36 | 37 | __To Do__ 38 | - [ ] application controller, sanitize extra paramaters 39 | - [ ] add more button colors as tailwind components 40 | - [ ] remove login / signup button from navbar when no devise 41 | - [ ] add stimulus2.0 42 | - [ ] change flash messages to be compatible with stimulusjs 43 | - [ ] navbar dropdown to be compatible with stimulusjs 44 |   45 | -------------------------------------------------------------------------------- /application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | def render_svg(name, styles: "fill-current text-gray-400", title: nil) # class is reserverd word in method, so styles 3 | filename = "#{name}.svg" 4 | title ||= name.underscore.humanize 5 | inline_svg_tag(filename, aria: true, nocomment: true, title: title, class: styles) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /basic.rb: -------------------------------------------------------------------------------- 1 | run "if uname | grep -q 'Darwin'; then pgrep spring | xargs kill -9; fi" 2 | 3 | 4 | say "starting template creation: Rails 6, Tailwind 2", :green 5 | 6 | inject_into_file 'Gemfile', before: 'group :development, :test do' do 7 | <<~RUBY 8 | gem 'autoprefixer-rails' 9 | gem 'font-awesome-sass' 10 | gem 'inline_svg' 11 | RUBY 12 | end 13 | 14 | inject_into_file 'Gemfile', after: 'group :development, :test do' do 15 | <<-RUBY 16 | gem 'pry-byebug' 17 | gem 'pry-rails' 18 | gem 'dotenv-rails' 19 | RUBY 20 | end 21 | 22 | gsub_file('Gemfile', /# gem 'redis'/, "gem 'redis'") 23 | 24 | def add_tailwind 25 | run "yarn remove @rails/webpacker" 26 | run "yarn add @rails/webpacker" 27 | 28 | gsub_file('Gemfile', /gem 'webpacker', '~> 4.0'/, "gem 'webpacker', github: 'rails/webpacker'") 29 | 30 | run "yarn add tailwindcss@latest postcss@latest autoprefixer@latest" 31 | run 'yarn add @tailwindcss/forms @tailwindcss/typography @tailwindcss/aspect-ratio' 32 | 33 | run "mkdir -p app/javascript/stylesheets" 34 | run "touch app/javascript/stylesheets/application.scss" 35 | inject_into_file "app/javascript/stylesheets/application.scss" do <<~EOF 36 | @import 'tailwindcss/base'; 37 | @import 'tailwindcss/components'; 38 | @import 'tailwindcss/utilities'; 39 | 40 | @import "components/base"; 41 | @import "components/buttons"; 42 | @import "components/cards"; 43 | @import "components/forms"; 44 | @import "components/icons"; 45 | @import "components/navigation"; 46 | EOF 47 | end 48 | 49 | run 'curl -L https://github.com/thomasvanholder/tailwind-components/archive/master.zip > components.zip' 50 | run 'unzip components.zip -d app && rm components.zip && mv app/tailwind-components-master app/javascript/components' 51 | 52 | run "npx tailwindcss init --full" 53 | gsub_file "tailwind.config.js", /plugins:\s\[],/, "plugins: [require('@tailwindcss/forms'), require('@tailwindcss/typography'), require('@tailwindcss/aspect-ratio'),]," 54 | 55 | 56 | run "mv tailwind.config.js app/javascript/stylesheets/tailwind.config.js" 57 | 58 | append_to_file("app/javascript/packs/application.js", 'import "stylesheets/application"') 59 | inject_into_file("./postcss.config.js", 60 | "let tailwindcss = require('tailwindcss');\n", before: "module.exports") 61 | inject_into_file("./postcss.config.js", "\n tailwindcss('./app/javascript/stylesheets/tailwind.config.js'),", after: "plugins: [") 62 | end 63 | 64 | def add_assets 65 | run 'rm -rf vendor' 66 | run 'rm -rf app/assets' 67 | run 'curl -L https://github.com/thomasvanholder/assets/archive/master.zip > assets.zip' 68 | run 'unzip assets.zip -d app && rm assets.zip && mv app/assets-master app/assets' 69 | 70 | gsub_file('config/environments/development.rb', /config\.assets\.debug.*/, 'config.assets.debug = false') 71 | end 72 | 73 | # Layout 74 | gsub_file('app/views/layouts/application.html.erb', "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>", "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>") 75 | style = <<~HTML 76 | 77 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> 78 | <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %> 79 | HTML 80 | gsub_file('app/views/layouts/application.html.erb', "<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>", style) 81 | 82 | 83 | def add_navbar 84 | run "mkdir -p app/views/shared" 85 | run 'curl -L https://raw.githubusercontent.com/thomasvanholder/jumpstart/main/templates/_navbar_basic.html.erb > app/views/shared/_navbar.html.erb' 86 | end 87 | 88 | def add_flashes 89 | run 'curl -L https://raw.githubusercontent.com/thomasvanholder/jumpstart/main/templates/_flashes.html.erb > app/views/shared/_flashes.html.erb' 90 | end 91 | 92 | inject_into_file 'app/views/layouts/application.html.erb', after: '' do 93 | <<-HTML 94 | \n 95 | <%= render 'shared/navbar' %> 96 | <%= render 'shared/flashes' %> 97 | HTML 98 | end 99 | 100 | # README 101 | ######################################## 102 | markdown_file_content = <<-MARKDOWN 103 | Rails app generated by [thomasvanholder/jumpstart](https://github.com/thomasvanholder/jumpstart), inspired by the [Le Wagon](https://www.lewagon.com). 104 | MARKDOWN 105 | file 'README.md', markdown_file_content, force: true 106 | 107 | # Generators 108 | ######################################## 109 | generators = <<~RUBY 110 | config.generators do |generate| 111 | generate.assets false 112 | generate.helper false 113 | generate.test_framework :test_unit, fixture: false 114 | end 115 | RUBY 116 | 117 | def set_routes 118 | route "root to: 'pages#home'" 119 | end 120 | 121 | def add_git_ignore 122 | append_file '.gitignore', <<~TXT 123 | # Ignore .env file containing credentials. 124 | .env* 125 | # Ignore Mac and Linux file system files 126 | *.swp 127 | .DS_Store 128 | TXT 129 | end 130 | 131 | def add_svg_helper 132 | run 'rm -rf app/helpers/application_helper.rb' 133 | 134 | run 'curl -L https://raw.githubusercontent.com/thomasvanholder/jumpstart/main/application_helper.rb > app/helpers/application_helper.rb' 135 | end 136 | 137 | environment generators 138 | 139 | ######################################## 140 | # AFTER BUNDLE 141 | ######################################## 142 | after_bundle do 143 | rails_command 'db:drop db:create db:migrate' 144 | generate(:controller, 'pages', 'home', '--skip-routes', '--no-test-framework') 145 | 146 | set_routes 147 | add_assets 148 | add_git_ignore 149 | 150 | # Environments 151 | ######################################## 152 | environment 'config.action_mailer.default_url_options = { host: "http://localhost:3000" }', env: 'development' 153 | environment 'config.action_mailer.default_url_options = { host: "http://TODO_PUT_YOUR_DOMAIN_HERE" }', env: 'production' 154 | 155 | # Webpacker / Yarn 156 | ######################################## 157 | append_file 'app/javascript/packs/application.js', <<~JS 158 | 159 | // ---------------------------------------------------- 160 | // ABOVE IS RAILS DEFAULT CONFIGURATION 161 | // WRITE YOUR OWN JS STARTING FROM HERE 👇 162 | // ---------------------------------------------------- 163 | 164 | // External imports 165 | import "../stylesheets/application.scss"; 166 | 167 | // Internal imports, e.g: 168 | // import { initSelect2 } from '../components/init_select2'; 169 | 170 | document.addEventListener('turbolinks:load', () => { 171 | // Call your functions here, e.g: 172 | // initSelect2(); 173 | }); 174 | JS 175 | 176 | inject_into_file 'config/webpack/environment.js', before: 'module.exports' do 177 | <<~JS 178 | const webpack = require('webpack'); 179 | // Preventing Babel from transpiling NodeModules packages 180 | environment.loaders.delete('nodeModules'); 181 | 182 | environment.plugins.prepend('Provide', 183 | new webpack.ProvidePlugin({ 184 | }) 185 | ); 186 | JS 187 | end 188 | 189 | run 'touch .env' 190 | run 'curl -L https://raw.githubusercontent.com/lewagon/rails-templates/master/.rubocop.yml > .rubocop.yml' 191 | 192 | # Git 193 | ######################################## 194 | git add: '.' 195 | git commit: "-m 'Initial commit with template from https://github.com/thomasvanholder/jumpstart'" 196 | 197 | # Fix puma config 198 | gsub_file('config/puma.rb', 'pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }', '# pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }') 199 | 200 | add_tailwind 201 | add_navbar 202 | add_flashes 203 | add_svg_helper 204 | 205 | run "bundle install" 206 | say "--------------------------------" 207 | say 208 | say "Kickoff app successfully created! 👍", :green 209 | say 210 | say "Switch to your app by running:", :green 211 | say " cd #{app_name}" 212 | say 213 | end 214 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require("tailwindcss")("./app/javascript/stylesheets/tailwind.config.js"), 4 | require("postcss-import"), 5 | require("postcss-flexbugs-fixes"), 6 | require("postcss-preset-env")({ 7 | autoprefixer: { 8 | flexbox: "no-2009", 9 | }, 10 | stage: 3, 11 | }), 12 | ], 13 | }; 14 | -------------------------------------------------------------------------------- /template.rb: -------------------------------------------------------------------------------- 1 | run "if uname | grep -q 'Darwin'; then pgrep spring | xargs kill -9; fi" 2 | 3 | 4 | say "starting template creation: Rails 6, Tailwind 2, Devise", :green 5 | 6 | inject_into_file 'Gemfile', before: 'group :development, :test do' do 7 | <<~RUBY 8 | gem 'devise' 9 | gem 'autoprefixer-rails' 10 | gem 'font-awesome-sass' 11 | RUBY 12 | end 13 | 14 | inject_into_file 'Gemfile', after: 'group :development, :test do' do 15 | <<-RUBY 16 | gem 'pry-byebug' 17 | gem 'pry-rails' 18 | gem 'dotenv-rails' 19 | RUBY 20 | end 21 | 22 | gsub_file('Gemfile', /# gem 'redis'/, "gem 'redis'") 23 | 24 | def add_tailwind 25 | run "yarn remove @rails/webpacker" 26 | run "yarn add @rails/webpacker" 27 | 28 | gsub_file('Gemfile', /gem 'webpacker', '~> 4.0'/, "gem 'webpacker', github: 'rails/webpacker'") 29 | 30 | run "yarn add tailwindcss@latest postcss@latest autoprefixer@latest" 31 | run 'yarn add @tailwindcss/forms @tailwindcss/typography @tailwindcss/aspect-ratio' 32 | 33 | run "mkdir -p app/javascript/stylesheets" 34 | run "touch app/javascript/stylesheets/application.scss" 35 | inject_into_file "app/javascript/stylesheets/application.scss" do <<~EOF 36 | @import 'tailwindcss/base'; 37 | @import 'tailwindcss/components'; 38 | @import 'tailwindcss/utilities'; 39 | 40 | @import "components/base"; 41 | @import "components/buttons"; 42 | @import "components/cards"; 43 | @import "components/forms"; 44 | @import "components/icons"; 45 | @import "components/navigation"; 46 | EOF 47 | end 48 | 49 | run 'curl -L https://github.com/thomasvanholder/tailwind-components/archive/master.zip > components.zip' 50 | run 'unzip components.zip -d app && rm components.zip && mv app/tailwind-components-master app/javascript/components' 51 | 52 | run "npx tailwindcss init --full" 53 | gsub_file "tailwind.config.js", /plugins:\s\[],/, "plugins: [require('@tailwindcss/forms'), require('@tailwindcss/typography'), require('@tailwindcss/aspect-ratio'),]," 54 | 55 | 56 | run "mv tailwind.config.js app/javascript/stylesheets/tailwind.config.js" 57 | 58 | append_to_file("app/javascript/packs/application.js", 'import "stylesheets/application"') 59 | inject_into_file("./postcss.config.js", 60 | "let tailwindcss = require('tailwindcss');\n", before: "module.exports") 61 | inject_into_file("./postcss.config.js", "\n tailwindcss('./app/javascript/stylesheets/tailwind.config.js'),", after: "plugins: [") 62 | end 63 | 64 | def add_assets 65 | run 'rm -rf vendor' 66 | run 'rm -rf app/assets' 67 | run 'curl -L https://github.com/thomasvanholder/assets/archive/master.zip > assets.zip' 68 | run 'unzip assets.zip -d app && rm assets.zip && mv app/assets-master app/assets' 69 | 70 | gsub_file('config/environments/development.rb', /config\.assets\.debug.*/, 'config.assets.debug = false') 71 | end 72 | 73 | # Layout 74 | gsub_file('app/views/layouts/application.html.erb', "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>", "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>") 75 | style = <<~HTML 76 | 77 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> 78 | <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %> 79 | HTML 80 | gsub_file('app/views/layouts/application.html.erb', "<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>", style) 81 | 82 | 83 | 84 | def add_navbar 85 | run "mkdir -p app/views/shared" 86 | run 'curl -L https://raw.githubusercontent.com/thomasvanholder/jumpstart/main/templates/_navbar.html.erb > app/views/shared/_navbar.html.erb' 87 | end 88 | 89 | def add_flashes 90 | run 'curl -L https://raw.githubusercontent.com/thomasvanholder/jumpstart/main/templates/_flashes.html.erb > app/views/shared/_flashes.html.erb' 91 | end 92 | 93 | inject_into_file 'app/views/layouts/application.html.erb', after: '' do 94 | <<-HTML 95 | \n 96 | <%= render 'shared/navbar' %> 97 | <%= render 'shared/flashes' %> 98 | HTML 99 | end 100 | 101 | # README 102 | ######################################## 103 | markdown_file_content = <<-MARKDOWN 104 | Rails app generated by [thomasvanholder/jumpstart](https://github.com/thomasvanholder/jumpstart), inspired by the [Le Wagon](https://www.lewagon.com). 105 | MARKDOWN 106 | file 'README.md', markdown_file_content, force: true 107 | 108 | # Generators 109 | ######################################## 110 | generators = <<~RUBY 111 | config.generators do |generate| 112 | generate.assets false 113 | generate.helper false 114 | generate.test_framework :test_unit, fixture: false 115 | end 116 | RUBY 117 | 118 | def set_routes 119 | route "root to: 'pages#home'" 120 | end 121 | 122 | def add_devise 123 | generate('devise:install') 124 | generate('devise', 'User') 125 | run "rails g migration AddFirstNameLastNameToUsers first_name last_name" 126 | 127 | run 'rm app/controllers/application_controller.rb' 128 | file 'app/controllers/application_controller.rb', <<~RUBY 129 | class ApplicationController < ActionController::Base 130 | #{ "protect_from_forgery with: :exception\n" if Rails.version < "5.2"} before_action :authenticate_user! 131 | end 132 | RUBY 133 | 134 | rails_command 'db:migrate' 135 | run 'curl -L https://github.com/thomasvanholder/devise/archive/master.zip > devise.zip' 136 | run 'unzip devise.zip -d app && rm devise.zip && mv app/devise-master app/views/devise' 137 | 138 | run 'rm app/controllers/pages_controller.rb' 139 | file 'app/controllers/pages_controller.rb', <<~RUBY 140 | class PagesController < ApplicationController 141 | skip_before_action :authenticate_user!, only: [ :home ] 142 | 143 | def home 144 | end 145 | end 146 | RUBY 147 | end 148 | 149 | def add_git_ignore 150 | append_file '.gitignore', <<~TXT 151 | # Ignore .env file containing credentials. 152 | .env* 153 | # Ignore Mac and Linux file system files 154 | *.swp 155 | .DS_Store 156 | TXT 157 | end 158 | 159 | def add_svg_helper 160 | inject_into_file 'Gemfile', after: "gem 'font-awesome-sass'" do 161 | <<~RUBY 162 | \ngem 'inline_svg' 163 | RUBY 164 | end 165 | 166 | run 'rm -rf app/helpers/application_helper.rb' 167 | 168 | run 'curl -L https://raw.githubusercontent.com/thomasvanholder/jumpstart/main/application_helper.rb > app/helpers/application_helper.rb' 169 | end 170 | 171 | environment generators 172 | 173 | ######################################## 174 | # AFTER BUNDLE 175 | ######################################## 176 | after_bundle do 177 | rails_command 'db:drop db:create db:migrate' 178 | generate(:controller, 'pages', 'home', '--skip-routes', '--no-test-framework') 179 | 180 | set_routes 181 | add_assets 182 | add_devise 183 | add_git_ignore 184 | 185 | # Environments 186 | ######################################## 187 | environment 'config.action_mailer.default_url_options = { host: "http://localhost:3000" }', env: 'development' 188 | environment 'config.action_mailer.default_url_options = { host: "http://TODO_PUT_YOUR_DOMAIN_HERE" }', env: 'production' 189 | 190 | # Webpacker / Yarn 191 | ######################################## 192 | append_file 'app/javascript/packs/application.js', <<~JS 193 | 194 | // ---------------------------------------------------- 195 | // ABOVE IS RAILS DEFAULT CONFIGURATION 196 | // WRITE YOUR OWN JS STARTING FROM HERE 👇 197 | // ---------------------------------------------------- 198 | 199 | // External imports 200 | import "../stylesheets/application.scss"; 201 | 202 | 203 | // Internal imports, e.g: 204 | // import { initSelect2 } from '../components/init_select2'; 205 | 206 | document.addEventListener('turbolinks:load', () => { 207 | // Call your functions here, e.g: 208 | // initSelect2(); 209 | }); 210 | JS 211 | 212 | inject_into_file 'config/webpack/environment.js', before: 'module.exports' do 213 | <<~JS 214 | const webpack = require('webpack'); 215 | // Preventing Babel from transpiling NodeModules packages 216 | environment.loaders.delete('nodeModules'); 217 | 218 | environment.plugins.prepend('Provide', 219 | new webpack.ProvidePlugin({ 220 | }) 221 | ); 222 | JS 223 | end 224 | 225 | # Dotenv 226 | ######################################## 227 | run 'touch .env' 228 | 229 | # Rubocop 230 | ######################################## 231 | run 'curl -L https://raw.githubusercontent.com/lewagon/rails-templates/master/.rubocop.yml > .rubocop.yml' 232 | 233 | # Git 234 | ######################################## 235 | git add: '.' 236 | git commit: "-m 'Initial commit with template from https://github.com/thomasvanholder/jumpstart'" 237 | 238 | # Fix puma config 239 | gsub_file('config/puma.rb', 'pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }', '# pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }') 240 | 241 | add_tailwind 242 | add_navbar 243 | add_flashes 244 | add_svg_helper 245 | 246 | run "bundle install" 247 | say "--------------------------------" 248 | say 249 | say "Kickoff app successfully created! 👍", :green 250 | say 251 | say "Switch to your app by running:", :green 252 | say " cd #{app_name}" 253 | say 254 | end 255 | -------------------------------------------------------------------------------- /templates/_flashes.html.erb: -------------------------------------------------------------------------------- 1 | <% if notice %> 2 | 3 |
4 |
5 |
6 |
7 |
8 |

9 | <%= notice[:title] %> 10 |

11 | <% if notice[:content] %> 12 |

13 | <%= notice[:content] %> 14 |

15 | <% end %> 16 |
17 |
18 | 23 |
24 |
25 |
26 |
27 |
28 | 29 | <% end %> 30 | -------------------------------------------------------------------------------- /templates/_navbar.html.erb: -------------------------------------------------------------------------------- 1 | 67 | -------------------------------------------------------------------------------- /templates/_navbar_basic.html.erb: -------------------------------------------------------------------------------- 1 | 25 | --------------------------------------------------------------------------------