Skip to content

Instantly share code, notes, and snippets.

@anon987654321
Created March 2, 2025 05:10
Show Gist options
  • Save anon987654321/a49a6cf1ca5b470d9000713fe79c16d1 to your computer and use it in GitHub Desktop.
Save anon987654321/a49a6cf1ca5b470d9000713fe79c16d1 to your computer and use it in GitHub Desktop.
#!/usr/bin/env zsh
set -e
# amber.sh - Sets up "Amber", an AI-enhanced social network for fashion.
# Version: 2.0.0 (2025-03-02)
#
# Features:
# • Wardrobe management with AI-powered recommendations
# • Style assistance for outfit combinations
# • Medium-style rich text editor for fashion posts
# • Social interactions with infinite scroll and live search
# • Stripe integration for marketplace functionality
# • Mapbox integration for location-based fashion discovery
APP_NAME="amber"
BASE_DIR="$HOME/dev/rails_apps"
source "$BASE_DIR/__shared.sh"
log "Starting Amber setup (AI-based fashion network)"
# -- INITIALIZE APPLICATION --
initialize_setup "$APP_NAME"
setup_yarn
create_rails_app "$APP_NAME"
# -- INSTALL DEPENDENCIES --
install_common_gems
setup_devise
setup_merit
setup_frontend
setup_active_storage
setup_stripe
setup_mediumstyle_editor
setup_mapbox
setup_common_scss
setup_redis
setup_pwa
# -- GENERATE MODELS --
log "Generating base social models"
generate_social_models
log "Generating WardrobeItem model for clothing management"
bin/rails generate model WardrobeItem name:string color:string size:string description:text category:string \
brand:string season:string status:string user:references || error_exit "WardrobeItem model creation failed"
# Enhance WardrobeItem model
cat <<EOF > app/models/wardrobe_item.rb
class WardrobeItem < ApplicationRecord
# Associations
belongs_to :user
has_many :outfit_items, dependent: :destroy
has_many :outfits, through: :outfit_items
has_one_attached :photo
# Validations
validates :name, presence: true
validates :category, presence: true
# Statuses
enum status: {
active: 'active',
archived: 'archived',
donated: 'donated',
sold: 'sold'
}
# Categories
CATEGORIES = [
'tops', 'bottoms', 'dresses', 'outerwear',
'shoes', 'accessories', 'bags', 'jewelry'
]
# Seasons
SEASONS = ['spring', 'summer', 'fall', 'winter', 'all']
# Scopes
scope :by_category, ->(category) { where(category: category) }
scope :by_season, ->(season) { where(season: season) }
scope :active, -> { where(status: 'active') }
# Search
include PgSearch::Model
pg_search_scope :search_by_attributes,
against: [:name, :description, :brand, :color],
using: { tsearch: { prefix: true } }
# Methods
def similar_items
WardrobeItem
.where(category: category)
.where.not(id: id)
.limit(5)
end
end
EOF
log "Generating Outfit model for style combinations"
bin/rails generate model Outfit name:string description:text occasion:string season:string user:references || error_exit "Outfit model creation failed"
cat <<EOF > app/models/outfit.rb
class Outfit < ApplicationRecord
# Associations
belongs_to :user
has_many :outfit_items, dependent: :destroy
has_many :wardrobe_items, through: :outfit_items
has_many :reactions, as: :reactable, dependent: :destroy
# Validations
validates :name, presence: true
# Occasions
OCCASIONS = [
'casual', 'work', 'formal', 'date_night',
'workout', 'travel', 'special_event'
]
# Seasons
SEASONS = ['spring', 'summer', 'fall', 'winter', 'all']
# Scopes
scope :by_occasion, ->(occasion) { where(occasion: occasion) }
scope :by_season, ->(season) { where(season: season) }
scope :recent, -> { order(created_at: :desc) }
scope :popular, -> { joins(:reactions).group(:id).order('COUNT(reactions.id) DESC') }
# Search
include PgSearch::Model
pg_search_scope :search_by_attributes,
against: [:name, :description, :occasion],
using: { tsearch: { prefix: true } }
end
EOF
log "Generating OutfitItem join model"
bin/rails generate model OutfitItem outfit:references wardrobe_item:references || error_exit "OutfitItem model creation failed"
# -- GENERATE CONTROLLERS --
log "Generating WardrobeItems controller"
bin/rails generate controller WardrobeItems index show new create edit update destroy || error_exit "WardrobeItems controller generation failed"
log "Generating Outfits controller"
bin/rails generate controller Outfits index show new create edit update destroy || error_exit "Outfits controller generation failed"
log "Generating StyleRecommendations controller for AI suggestions"
bin/rails generate controller StyleRecommendations index show || error_exit "StyleRecommendations controller generation failed"
# -- SETUP REFLEXES --
setup_infinite_scroll
setup_live_search
log "Generating WardrobeReflex for real-time wardrobe management"
bin/rails generate reflex WardrobeReflex || error_exit "WardrobeReflex generation failed"
cat <<'EOF' > app/reflexes/wardrobe_reflex.rb
class WardrobeReflex < ApplicationReflex
def filter
category = element.dataset["category"]
season = element.dataset["season"]
@wardrobe_items = current_user.wardrobe_items.active
@wardrobe_items = @wardrobe_items.by_category(category) if category.present?
@wardrobe_items = @wardrobe_items.by_season(season) if season.present?
morph "#wardrobe_items", ApplicationController.render(
partial: "wardrobe_items/items_list",
locals: { wardrobe_items: @wardrobe_items }
)
end
def search
query = element.value.to_s.strip
if query.present? && query.length >= 2
@wardrobe_items = current_user.wardrobe_items.search_by_attributes(query)
morph "#wardrobe_items", ApplicationController.render(
partial: "wardrobe_items/items_list",
locals: { wardrobe_items: @wardrobe_items }
)
end
end
end
EOF
# -- SETUP ROUTES --
log "Configuring routes"
cat <<'EOF' > config/routes.rb
Rails.application.routes.draw do
# Root path
root 'home#index'
# Authentication
devise_for :users
# Wardrobe management
resources :wardrobe_items
# Outfit management
resources :outfits
# Style recommendations
resources :style_recommendations, only: [:index, :show]
# Social features
resources :posts do
resources :reactions, only: [:create, :destroy]
end
# User profiles
resources :users, only: [:show] do
member do
get :wardrobe
get :outfits
get :posts
end
end
# Marketplace (enabled by Stripe)
namespace :marketplace do
resources :listings
resources :purchases, only: [:index, :show, :create]
end
# PWA offline route
get "/offline", to: "pages#offline"
# Stripe webhook
mount StripeEvent::Engine, at: '/stripe/webhooks'
end
EOF
# -- CREATE HOME CONTROLLER AND VIEWS --
log "Generating Home controller"
bin/rails generate controller Home index || error_exit "Home controller generation failed"
cat <<'EOF' > app/views/home/index.html.erb
<div class="home-container">
<header class="hero">
<h1>Welcome to Amber</h1>
<p>Your AI-powered fashion assistant</p>
</header>
<section class="features">
<div class="feature">
<h3>Manage Your Wardrobe</h3>
<p>Catalog your clothing items and access them anytime, anywhere.</p>
<%= link_to 'My Wardrobe', wardrobe_items_path, class: 'btn btn-primary' if user_signed_in? %>
</div>
<div class="feature">
<h3>Get Outfit Recommendations</h3>
<p>AI-powered suggestions based on your style, occasion, and weather.</p>
<%= link_to 'Style Suggestions', style_recommendations_path, class: 'btn btn-primary' if user_signed_in? %>
</div>
<div class="feature">
<h3>Share Your Style</h3>
<p>Create posts about your outfits and fashion discoveries.</p>
<%= link_to 'Fashion Feed', posts_path, class: 'btn btn-primary' %>
</div>
</section>
<% if !user_signed_in? %>
<section class="cta">
<h2>Start Your Fashion Journey</h2>
<div class="cta-buttons">
<%= link_to 'Sign Up', new_user_registration_path, class: 'btn btn-primary' %>
<%= link_to 'Log In', new_user_session_path, class: 'btn btn-secondary' %>
</div>
</section>
<% end %>
</div>
EOF
# -- CREATE STYLE RECOMMENDATION SERVICE --
log "Creating AI style recommendation service"
mkdir -p app/services
cat <<'EOF' > app/services/style_recommendation_service.rb
class StyleRecommendationService
attr_reader :user, :occasion, :season
def initialize(user, occasion: nil, season: nil)
@user = user
@occasion = occasion || 'casual'
@season = season || current_season
end
def recommend_outfit
wardrobe_items = user.wardrobe_items.active
# Create a balanced outfit based on categories
outfit_items = {}
# Start with tops
outfit_items[:top] = wardrobe_items.by_category('tops')
.by_season([season, 'all'])
.order('RANDOM()')
.first
# Add bottoms
outfit_items[:bottom] = wardrobe_items.by_category('bottoms')
.by_season([season, 'all'])
.order('RANDOM()')
.first
# Add shoes
outfit_items[:shoes] = wardrobe_items.by_category('shoes')
.by_season([season, 'all'])
.order('RANDOM()')
.first
# Add accessories (optional)
outfit_items[:accessory] = wardrobe_items.by_category('accessories')
.by_season([season, 'all'])
.order('RANDOM()')
.first
# Filter out nil items
outfit_items.compact
end
def recommend_items_to_buy
# Identify gaps in the wardrobe
categories = WardrobeItem::CATEGORIES
missing_categories = []
categories.each do |category|
if user.wardrobe_items.by_category(category).count < 2
missing_categories << category
end
end
# Return recommendations for missing items
missing_categories.map do |category|
{
category: category,
recommendation: "Consider adding more #{category} to your wardrobe"
}
end
end
private
def current_season
month = Time.zone.now.month
case month
when 3..5
'spring'
when 6..8
'summer'
when 9..11
'fall'
else
'winter'
end
end
end
EOF
# -- MIGRATE AND SEED --
log "Running database migrations"
bin/rails db:create db:migrate || error_exit "Database migration failed"
log "Setting up seed data"
cat <<'EOF' > db/seeds/wardrobe_items.rb
# Sample wardrobe items for users
users = User.all
users.each do |user|
# Create tops
['T-shirt', 'Button-up Shirt', 'Blouse', 'Sweater'].each do |item|
WardrobeItem.create!(
name: item,
category: 'tops',
color: ['white', 'black', 'blue', 'green', 'red'].sample,
size: ['XS', 'S', 'M', 'L', 'XL'].sample,
description: "A nice #{item.downcase}",
brand: ['Zara', 'H&M', 'Nike', 'Adidas', 'Uniqlo'].sample,
season: ['spring', 'summer', 'fall', 'winter', 'all'].sample,
status: 'active',
user: user
)
end
# Create bottoms
['Jeans', 'Pants', 'Shorts', 'Skirt'].each do |item|
WardrobeItem.create!(
name: item,
category: 'bottoms',
color: ['blue', 'black', 'beige', 'grey'].sample,
size: ['XS', 'S', 'M', 'L', 'XL'].sample,
description: "A nice pair of #{item.downcase}",
brand: ['Levi\'s', 'Gap', 'J.Crew', 'Uniqlo'].sample,
season: ['spring', 'summer', 'fall', 'winter', 'all'].sample,
status: 'active',
user: user
)
end
# Create shoes
['Sneakers', 'Boots', 'Dress Shoes', 'Sandals'].each do |item|
WardrobeItem.create!(
name: item,
category: 'shoes',
color: ['black', 'white', 'brown', 'blue'].sample,
size: ((5..12).to_a.sample).to_s,
description: "A nice pair of #{item.downcase}",
brand: ['Nike', 'Adidas', 'Converse', 'Vans', 'Dr. Martens'].sample,
season: ['spring', 'summer', 'fall', 'winter', 'all'].sample,
status: 'active',
user: user
)
end
# Create accessories
['Hat', 'Scarf', 'Necklace', 'Watch'].each do |item|
WardrobeItem.create!(
name: item,
category: 'accessories',
color: ['black', 'gold', 'silver', 'red', 'blue'].sample,
size: 'One Size',
description: "A nice #{item.downcase}",
brand: ['Fossil', 'Gucci', 'Zara', 'H&M'].sample,
season: ['spring', 'summer', 'fall', 'winter', 'all'].sample,
status: 'active',
user: user
)
end
end
EOF
cat <<'EOF' > db/seeds/outfits.rb
# Create sample outfits for users
users = User.all
occasions = Outfit::OCCASIONS
seasons = Outfit::SEASONS
users.each do |user|
3.times do |i|
# Create an outfit
outfit = Outfit.create!(
name: "#{occasions.sample.titleize} Outfit #{i+1}",
description: "A great outfit for #{occasions.sample} occasions",
occasion: occasions.sample,
season: seasons.sample,
user: user
)
# Add wardrobe items to the outfit
tops = user.wardrobe_items.by_category('tops').limit(1)
bottoms = user.wardrobe_items.by_category('bottoms').limit(1)
shoes = user.wardrobe_items.by_category('shoes').limit(1)
accessories = user.wardrobe_items.by_category('accessories').limit(1)
[tops, bottoms, shoes, accessories].flatten.each do |item|
OutfitItem.create!(
outfit: outfit,
wardrobe_item: item
) if item
end
end
end
EOF
cat <<'EOF' >> db/seeds.rb
# Amber seed data
puts "Creating wardrobe items..."
require Rails.root.join('db', 'seeds', 'wardrobe_items')
puts "Creating outfits..."
require Rails.root.join('db', 'seeds', 'outfits')
EOF
# Run seeds
log "Populating database with seed data"
setup_social_seed_data
bin/rails db:seed || error_exit "Database seeding failed"
# -- FINAL STEPS --
log "Setting up application layout"
cat <<'EOF' > app/views/layouts/application.html.erb
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= content_for?(:title) ? yield(:title) : "Amber - AI Fashion Assistant" %></title>
<meta name="description" content="<%= content_for?(:description) ? yield(:description) : "Amber helps you manage your wardrobe, get style recommendations, and share your fashion journey." %>">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
<!-- PWA support -->
<%= render 'layouts/pwa' %>
<!-- SEO metadata -->
<meta property="og:title" content="<%= content_for?(:title) ? yield(:title) : "Amber - AI Fashion Assistant" %>">
<meta property="og:description" content="<%= content_for?(:description) ? yield(:description) : "Amber helps you manage your wardrobe, get style recommendations, and share your fashion journey." %>">
<meta property="og:type" content="website">
<meta property="og:url" content="<%= request.original_url %>">
</head>
<body>
<%= render 'shared/navigation' %>
<div class="container">
<%= render 'shared/flash_messages' %>
<main>
<%= yield %>
</main>
</div>
<%= render 'shared/footer' %>
</body>
</html>
EOF
log "Creating navigation partial"
mkdir -p app/views/shared
cat <<'EOF' > app/views/shared/_navigation.html.erb
<nav class="main-nav">
<div class="container">
<div class="nav-brand">
<%= link_to "Amber", root_path %>
</div>
<div class="nav-links">
<% if user_signed_in? %>
<%= link_to "My Wardrobe", wardrobe_items_path %>
<%= link_to "My Outfits", outfits_path %>
<%= link_to "Style Recommendations", style_recommendations_path %>
<%= link_to "Fashion Feed", posts_path %>
<div class="dropdown">
<button class="dropdown-toggle"><%= current_user.name %></button>
<div class="dropdown-menu">
<%= link_to "Profile", user_path(current_user) %>
<%= link_to "Settings", edit_user_registration_path %>
<%= link_to "Sign Out", destroy_user_session_path, method: :delete %>
</div>
</div>
<% else %>
<%= link_to "Fashion Feed", posts_path %>
<%= link_to "Sign In", new_user_session_path, class: "btn btn-secondary" %>
<%= link_to "Sign Up", new_user_registration_path, class: "btn btn-primary" %>
<% end %>
</div>
<button class="mobile-menu-toggle" data-controller="mobile-menu">
<span></span>
<span></span>
<span></span>
</button>
</div>
</nav>
EOF
log "Creating flash messages partial"
cat <<'EOF' > app/views/shared/_flash_messages.html.erb
<% flash.each do |key, message| %>
<div class="flash flash-<%= key %>">
<%= message %>
<button class="close">&times;</button>
</div>
<% end %>
EOF
log "Creating footer partial"
cat <<'EOF' > app/views/shared/_footer.html.erb
<footer class="main-footer">
<div class="container">
<div class="footer-content">
<div class="footer-brand">
<h3>Amber</h3>
<p>Your AI-powered fashion assistant</p>
</div>
<div class="footer-links">
<div class="footer-section">
<h4>Features</h4>
<ul>
<li><%= link_to "Wardrobe Management", wardrobe_items_path %></li>
<li><%= link_to "Style Recommendations", style_recommendations_path %></li>
<li><%= link_to "Fashion Feed", posts_path %></li>
</ul>
</div>
<div class="footer-section">
<h4>Help</h4>
<ul>
<li><a href="#">FAQ</a></li>
<li><a href="#">Contact Us</a></li>
<li><a href="#">Privacy Policy</a></li>
</ul>
</div>
</div>
</div>
<div class="footer-bottom">
<p>&copy; <%= Time.current.year %> Amber. All rights reserved.</p>
</div>
</div>
</footer>
EOF
# Commit changes to Git
commit_to_git "Amber is fully set up (AI-enhanced fashion network)"
log "Amber setup complete. Run 'bin/rails server' to start local development."
echo "Visit http://localhost:3000 to see your application."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment