2N App Template

// production-ready Rails 8 generator with batteries included

curl -fsSL rails.2n.pl/go | ruby

setup_checklist

// complete before first deploy

0/27 completed

credentials

rails credentials:edit

deployment

config files

github_secrets

repository settings

optional

app-specific

default_stack

// what you get with 'Use defaults? Yes'

core

PostgreSQL
Vite + Tailwind 4 + DaisyUI
React 19 + TypeScript
Devise (User model)
Pundit
Shrine + S3

monitoring

Sentry
NewRelic
Rack::Attack
Bullet (N+1)

deployment

Kamal (prod + staging)
GitHub Actions
Solid Queue
Mission Control

extras

ViewComponent
meta-tags + sitemap
pagy (pagination)
invisible_captcha

usage_examples

// quick reference for included technologies

DaisyUI Components

<button class="btn btn-primary">Primary</button>
<button class="btn btn-secondary">Secondary</button>
<button class="btn btn-accent">Accent</button>

<!-- Theme: app/frontend/stylesheets/daisyui.css -->

ViewComponent

# app/components/button_component.rb
class ButtonComponent < ViewComponent::Base
  def initialize(label:, variant: :primary)
    @label = label
    @variant = variant
  end
end

# Usage in view:
<%= render ButtonComponent.new(label: "Click") %>

Pagy Pagination

# Controller
@pagy, @records = pagy(:offset, Model.all)

# View
<%== @pagy.series_nav %>

Pundit Authorization

# app/policies/post_policy.rb
class PostPolicy < ApplicationPolicy
  def update?
    record.user == user
  end
end

# Controller: authorize @post

Shrine File Upload

# Model
class User < ApplicationRecord
  include ImageUploader::Attachment(:avatar)
end

# Form
<%= form.file_field :avatar %>

Meta Tags

# Controller
set_meta_tags(
  title: 'Page Title',
  description: 'Page description',
  og: { title: 'OG Title' }
)

# View: <%= display_meta_tags %>

credentials_to_configure

// rails credentials:edit

gtag:

id: 'G-XXXXXXXXXX'

sentry:

dsn: 'https://xxx@sentry.io/xxx'

new_relic:

license_key: 'xxx'

s3:

access_key_id: 'xxx'
secret_access_key: 'xxx'
bucket: 'my-bucket'
region: 'eu-central-1'

database:

user: 'postgres'
password: 'xxx'
name: 'myapp_production'

mission_control:

user: 'admin'
password: 'xxx'

smtp:

user_name: 'postmaster@mg.domain.com'
password: 'xxx'
address: 'smtp.mailgun.org'
port: 587

files_to_update

// replace placeholders before deploy

config/deploy.yml

YOUR_SERVER_IP → 1.2.3.4
your-domain.com → myapp.com

config/deploy.staging.yml

staging.your-domain.com → staging.myapp.com

config/robots.production.txt

Sitemap: https://your-domain.com/sitemap.xml

.github/workflows/*.yml

Add secrets: SSH_PRIVATE_KEY, RAILS_MASTER_KEY

available_endpoints

// ready to use after generation

>_

dev_user

pan@admin.pl / 123123