Collaboratively pick and vote on items to furnish your next home. Create a flat, add rooms and items, collect options (scraped from product URLs), and vote with 1–5 stars. Budgets and quick-add UX help you decide faster. Build to learn Hotwire's Turbo Frames and Turbo Streams.
- What it does
- Tech stack
- Domain model
- Authorization
- Setup
- Running the app
- Key workflows
- Scraper details
- PWA
- Deployment
- User auth with Devise; role/record authorization with Pundit.
- Manage
Flats(with budget) →Rooms(typed) →Items(importance) →Options(price, image, URL). - Invite collaborators to a flat (pending/accepted/declined; normal/admin).
- Vote 1–5 stars on options; rank by average stars.
- “Quick add” option from a product URL via lightweight scraper (Open Graph).
- Hotwire/Turbo + Stimulus UI, Tailwind styling.
- Active Storage via Cloudinary for images.
- PWA manifest + service worker for installability.
- Ruby 3.1.2, Rails 7.0.4.x
- Postgres
- Devise, Pundit, Turbo, Stimulus, Tailwind (tailwindcss-rails), Simple Form + simple_form-tailwind
- Active Storage (Cloudinary)
- RSpec, Capybara
- Faraday (+ redirects, cookies, retry) for scraping
- Pundit for authorization
Userhas manyFlats,Invitations,InspirationsFlatbelongs toUser; has manyRooms,Items(through rooms),Options(through items)Roombelongs toFlat; has manyItems,Options(through items); kind enum with auto-namingItembelongs toRoom; importance enum; average price computed across optionsOptionbelongs toItem; has manyVotes; image attached; average starsInvitationbelongs toUserandFlat; statuses: pending/accepted/declined; levels: normal/adminVotebelongs toUserandOption(unique per user/option); 1..5 stars
- Flat owners have full control.
- Invited accepted users can view.
- Invited admin users can create/update/destroy rooms, items, options, and invitations.
- Users can vote on options of flats they own or are invited to; only the voter can update their vote.
- Prereqs: Ruby 3.1.2, Postgres, Bundler, Foreman (auto-installed by
bin/dev). - Env vars (copy to
.envfor development):CLOUDINARY_URL=cloudinary://<key>:<secret>@<cloud_name>(required for image uploads)HTTP_PROXY_URL=(optional; can improve scraping reliability)
- Install and prepare:
bin/setup # (optional demo data) bin/rails db:seed - Verify DB is running (Postgres).
bin/dev
# runs web (3000) + tailwind watcher via Procfile.dev- Create a flat (name, address, optional budget).
- Invite collaborators; they accept/decline (admin or normal).
- Add rooms (typed: kitchen, bedroom, etc.); names auto-suffixed when duplicates.
- Add items to rooms; set importance (low/medium/high/urgent).
- Add options to items:
- Normal form with name/price/image/description/url/size.
- Quick add: paste product URL; we prefill from Open Graph tags; you review before saving.
- Vote 1–5 stars on options; items show options sorted by rating.
- Budget insights: flat total estimate = sum of item average prices; see priciest item.
- Service object:
OptionScrapper→HttpClient. - Parses HTML with Nokogiri; prefers Open Graph tags.
- If blocked (403, etc.), returns
{ status: "403", website: "<domain>" }and the UI explains the limitation. - Optional proxy via
HTTP_PROXY_URL. Retries/redirections/cookies enabled via Faraday middleware.
- Manifest at
/manifest.json, service worker at/service-worker.js. - Minimal SW (no offline caching yet); safe to iterate later.
- Required env:
CLOUDINARY_URL. - Active Storage service:
cloudinaryin development and production.