├── 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 |
--------------------------------------------------------------------------------