Spectacular is a responsive SPA built with a Ruby on Rails backend and React/Redux frontend. Inspired by Warby Parker, it serves as a platform to buy glasses. This MVP was styled and developed in 10 days so there's still more to come, desired features are listed at the bottom.
Spectacular was made to be a near perfect clone of Warby Parker. As such, Spectacle images were web scrapped using a simple Python script that downloaded all images from the web page. To seed Spectacle Names, random names for spectacles were generated using names for Coffee Blends, US States, Athenian Gods, Book Publishers, Book Genres, and common first names. Seed data was implemented using a Gem called Faker.
possible_title= [Faker::Book.genre,
Faker::Book.publisher,
Faker::Ancient.god,
Faker::Address.state,
Faker::Coffee.blend_name].sample
After images and randomly generated names, the display was modeled to be as close as possible to the site. To compare the result, I have posted both images below.
My website clone
Compared to the final Site.
Users are automatically signed in as "guest users". This means that in the backend, Users are automatically signed in a Hex key upon visiting the site. Upon logging in or
Ruby on Rails was used to serve the backend. PostgreSQL database to store data.
ActiveRecords
used for Object-relational Mapping.
has_many :cartitems,
foreign_key: :user_id,
class_name: "Cartitem"
has_many :cart,
through: :cartitems,
source: :spectacle
has_many :cartitems,
foreign_key: :spectacle_id,
class_name: "Cartitem"
has_many :users,
through: :cartitems,
source: :user
- Hosted on Heroku
- AWS S3 Buckets and Paperclip to host and upload content
- RESTful API endpoints
- Views created with Jbuilder
- Figaro for API key protection
- BCrypt for password hashing and privacy
Facebook's React frontend framework was used for speedy rendering. Redux architecture was used for unidirectional data flow.
- Webpack for bundling
- Guard for live reloading
- ES6 Javascript
componentWillMount() {
const { requestCommentsForPost, post } = this.props;
requestCommentsForPost(post)
.then( () => this.setState({
loading: false
})
);
}
componentWillReceiveProps(nextProps) {
if (this.props.commentsByPost !== nextProps.commentsByPost) {
this.setState({ commentsByPost: nextProps.commentsByPost });
}
if (this.props.likesCount !== nextProps.likesCount) {
this.setState({ liked: nextProps.liked });
}
}
}
- SCSS and CSS styling based on SMACSS style guide
$bgcolor: #fafafa;
$var: 15px;
body {
background: $bgcolor;
font-family: 'Open Sans', sans-serif;
}
.container {
padding: $var;
}
- Search for Title of Spectacles
- Imporve Functionality of Cart-Items