Quantcast
Channel: The Houzz Blog
Viewing all 284 articles
Browse latest View live

Inside Houzz Tour: Tel Aviv!

$
0
0
image


The Houzz team in Tel Aviv shared a glimpse of their warm and welcoming new office. Full of light, color, and plenty of areas to collaborate, the space provides a fun and comfortable environment for Houzzers to work and even play!

Here are a few photos of the gorgeous space:

image

The bright and inviting lounge is often the location of the team’s weekly standup meetings

image

An airy, open floor plan creates a collaborative environment for the team

image

Large windows throughout the office offer plenty of natural light and spectacular views of the city

image

The instruments in the Music Room aren’t just decorative – with a few musicians on the team, they are also used for spontaneous jam sessions

image

The Bathroom and Kids Room are popular meeting spaces

image

Houzzers enjoy meals and Friday happy hours in the dining area

image

The Houzz Tel Aviv team

Photography: Uzi Porat


Houzz Acquires GardenWeb from NBCUniversal, Welcomes the GardenWeb Community to Houzz Family

$
0
0

We’re excited to share that Houzz has completed the acquisition of GardenWeb, the longstanding home and gardening community, from NBCUniversal. The GardenWeb and Houzz communities have a lot in common with regard to our shared passion for our homes and gardens.

Since it was founded in 1995, the GardenWeb community has been a bastion of home and gardening advice on the Internet. Bringing GardenWeb’s vibrant and engaged users, forums and resources together with the Houzz platform will provide a richer content experience for the unified community. 

The addition of GardenWeb gives Houzzers access to over 2.8 million discussion threads, over 14 million discussion posts, and nearly 400 discussion topics for both home and gardening enthusiasts. Millions of people participate in discussions on Houzz every month to provide and find advice for their home renovation and design projects. 

Our team has been hard at work to complete the first phase of GardenWeb’s integration onto Houzz. Welcome to the Houzz family, GardenWeb!

New Bedroom, New Style

$
0
0

image

Contemporary Bedroom

It’s out with the old and in with the new style when it comes to master bedroom upgrades, according to the 2015 U.S. Houzz Bedroom Trends Study. Before our master bedroom renovating and decorating projects, most had a traditional style or no particular style at all (64%). Post-updates, most of us opt for transitional, contemporary or modern styles (45%).

image

Bigger is better when it comes to our updated master bedrooms and their closets. Of those of us  renovating our master bedrooms, one in five is expanding its size (21%), and more than half of our closet upgrades involve an increase in square footage (59%). One-third of updated master bedroom closets are growing by 50% or more!

image

When it comes to decorating, the majority of us are using small décor accessories to update our rooms (76%), yet half of us are also replacing furniture (49%), and a third of us are updating our beds (37%). One in five new beds is a platform (23%), with standard and sleigh beds following as the next most popular styles (15% and 13% respectively). Examples of platform beds available for purchase on Houzz can be found here.

image

To further customize our beds, many of us are accessorizing them with accent pillows – many, many accent pillows. Forty percent of our beds will have five or more decorative pillows once our master bedroom updates are complete!

Check out the full 2015 U.S. Houzz Bedroom Trends Study for more details from the report. And if you have products you’d like to see featured on Houzz, contact shopfeatures@houzz.com.

Houzz API Tests at a Glance

$
0
0

As a fast-growing company, we have an increasing number of APIs consumed by our mobile apps, internal batch processes, and business partners. Manually testing these APIs each time has become almost impossible given our weekly release cycle. My first project after joining Houzz was to build our API test automation framework. With hundreds of test cases included, this API automation is now a critical part of our release validation. Not only does it save a lot of manual testing effort, it has also caught many critical bugs and has prevented production issues. This system has played an essential role in scaling product development with our growing team.

Where to start?
With a large number of API endpoints, it could be difficult to figure out where to start at the beginning. After some discussion, we decided that it could be cost-effective to build a smoke test for the most frequently called API endpoints. I compiled a list from our production server logs, and built a smoke test to just make these API calls in batch and do some basic validations, such as HTTP status code and schema validation. Although it only took minimal effort to build, it turned out to be effective in catching a meaningful number of critical bugs before they reached production.

Next step is to build a more comprehensive regression test suite. Quite similar to end-to-end UI tests, API tests should also be based on user scenarios. The only difference is that API tests are simulating user scenarios at a lower level without UI interaction. To find out what APIs our mobile apps are calling, we have an internal tool to capture HTTP requests between our mobile app and API server, including HTTP method, url, query parameters, headers, request body, etc. As I go over each user scenario, the API call flows are being recorded. What’s left is to convert these recordings to API tests by extracting test data, calling APIs and adding validations. Please see the chart below.

image

Use test tool or write code?
There are two popular approaches to automate API tests: one is through UI based API testing tools, such as SoapUI; the other is to write our own automation code with some open source libraries. I decided to go with the latter approach because of the following benefits:

  • more reliable
  • independent of OS
  • better code reusability
  • easier to debug
  • easier to customize
  • easier to integrate with internal tools and other projects

I chose Java to build the API automation framework, and use TestNG for test execution and reporting.

How to automate API calls?
To quickly generate some automated API test flows out of the recorded request data, I wrote an utility to extract request data into JSON format. For example, an API call to get photo by id (GET http://www.example.com/photo?id=1001) could be parsed as the following JSON data:


{
    "method": "GET",
    "baseUrl": "www.example.com",
    "path": "photo",
    "queryParams": {
        "id": "1001",
    }
}

JSON data is later deserialized to RequestData Java objects, which could be used to build API requests. Definition of the RequestData Java class looks like this:

public class RequestData {
    private HttpMethod _method;
    private String _baseUrl;
    private String _path;
    private Map _queryParams;
    private Map _postData;
    private Map _headers;
    …
}

Often times, the same API endpoint will be called multiple times with different variations. JSON data generated from the first request of the same endpoint will be used as a baseline. We don’t need to record the full JSON for subsequent requests of the same endpoint. Instead it will be parsed as a JSON diff. Using the same example of “get photo” API again, let’s say we need to make the same API call with a different photo id “1002”, it will be parsed as:

[{"op":"replace","path":"/queryParams/id","value":"1002"}]

The json-patch library (https://github.com/fge/json-patch) is very useful in this case to generate JSON diff and to reconstruct original JSON data.

Compared to a UI test that requires a browser, for API tests we need a HTTP client to handle request and response.  I’m using Apache HTTP component for that purpose. In order to parse and validate API responses, I use JsonPath and XmlPath from REST-assured, which provides an easy way to access field values in API responses to verify its existence, data type, and expected value.

What to validate?
Now that we have automated making API calls and parsing the response, we also need to perform some validations. Often times different API endpoints or test scenarios require different types of validations, but there are some common ones that almost always apply:

  • Status code, schema validation
  • Verify API response is what the client is expecting. Still using the example of “get photo” API, a client calling this API may be expecting a string field called “url” in the API response that points to the photo’s URL. Assuming a valid photo id is provided, the API test should check that “url” field exists, its data type should be a string, and its value is a valid URL (if you know what is the expected URL for a given photo id, you could also do an exact match on its value).
  • Verify expected effect after making an API call. This is similar to UI functionality test. One example would be after calling an API to add a new photo; if the response is successful, you want to verify the photo is actually added on server side. Usually you can call an API to get the newly created photo to verify this.
  • Cover negative cases in testing. Since we cannot control how clients make API calls once we expose them, we want to make sure API behaves correctly with invalid input such as missing required fields or incorrect data types, and API response should include an error message informative enough to tell client what is wrong with the API call.

Performance
In addition to functionality, we also want to test API performance. One important aspect of performance testing is to monitor latency and resource usage of a single API call. API tests record latency of each call and flag calls with latency higher than a threshold. To monitor resource usages, our backend engineering team implemented a performance logging mechanism to log performance counters for each incoming request (examples include memory usage, and number of sql or solr queries). I integrated API tests with these performance counters to find out if there is any significant increase caused by code change. Basically an API test would make the same API call to two different builds - one is the current development build, the other is from the latest release - and will then retrieve the performance counters for each build and make a comparison. This has helped us detect several performance regressions such as increased memory usage or redundant sql/solr queries.

Backward compatibility
We certainly don’t want to break a previously released mobile app when we roll out changes on the server side. Our users should be able to use the Houzz app regardless of whether they upgrade to the most recent app version or not. Therefore, we need to maintain API tests for some previously released versions. Since both API request and response could be different from version to version, there will be some additional maintenance effort.

To run API tests in different versions, test data is separated into resource files categorized by version if necessary. Based on system property, our test framework will simulate requests with different versions, and pick up different test data resource file accordingly. To determine which versions to maintain, I often need to check production logs to find out which versions are mostly being used by our users. We run API tests more frequently on current version and most used versions, and only check older versions on release day.

Internationalization
With users from all over the world,  we need to test our API endpoints in different countries. In addition to localized language in API response, functionality could also be slightly different in each country. For example, searching “red sofa” related photos could result in different content for different countries. Similar to how we handle versions, we also extract locale specific test data to files grouped by country code. Our test framework is able to pick up correct data file based on locale.

Integration with UI automation
One additional benefit we realized after building the API automation is that, we can leverage them in end-to-end UI automation to speed up test data setup. For example, a significant percentage of our UI tests require a newly created user. Instead of signing up on browser, we now switched to creating users via API. This has several benefits:

  • significantly reduced UI test execution time as API calls are usually a lot faster than UI flow.
  • improved overall stability of the UI automation. One of the reasons is that the UI changes are usually more frequent. For example, if we are iterating different UI designs for sign up flows, all the UI tests that require user sign-up through UI could fail. This is no longer a concern after we switch to creating user via API. One caveat is that you should keep at least one test to cover the UI flow replaced by API elsewhere.

Summary
It has been a very exciting experience to own a project from the beginning and build it from scratch. Of course I also received a lot of help from my amazing coworkers along the way, and it’s always fun to collaborate across the team. As Houzz grows, we will face new technical challenges that provide more exciting opportunities in the test automation area. If you’re interested in joining our growing team, please check out our jobs page at https://www.houzz.com/jobs

Houzzer Profile: Philip Law, Front-End Engineer

$
0
0

As a front-end engineer, Philip is an avid problem solver who enjoys the challenges of building a great user experience for a large-scale web application. When he’s not at work you can find him playing basketball at the gym or hanging out with friends.

When did you first discover computer science?
I discovered engineering later than most. When I started college, I didn’t know that I was going to be a computer science major and didn’t have much experience with computers. I’m a logical thinker and like to analyze problems, but I wasn’t a huge fan of reading books and writing papers, so this led me to computer science.

When I started, the classes were tough because I had never written a program. In my first class, the assignment was to write code and then compile the code into a program. I had no idea what the instructor was talking about, but I stuck with it and things really started clicking during the first semester. If I didn’t choose this career, I might have studied architecture or something where you can build things. For me, computer science is even better because I can build something and see it right away.

What do you enjoy most about being a front-end engineer?
Instant gratification. I get to build things that people see and use everyday. It’s rewarding to hear constant feedback from users and enhance the product for them.

What’s your favorite thing you’ve worked on at Houzz?
I enjoy working on projects that can help make other engineers’ lives easier, such as building components, libraries, and platforms. I’ve also enjoyed working on Houzz’s global expansion, because I get to apply knowledge from my past experiences, refine it and see it work on a large scale. At Houzz, expanding internationally is more than just having the site translated, it’s about serving relevant content in the different markets. We had a very unique set of challenges when we started to localize Houzz for new markets. It feels really good to hear positive feedback from our community around the world.

Currently I am working on a new front-end platform that will utilize some of the newer technology concepts such as isomorphic javascript, Flux, and Asynchronous Module Definition. It will be very interesting to see how these concepts work in a large system and how it will make our growing engineering team work more efficiently.  

What is the best part about working at Houzz?
At Houzz, every engineer has input into the product. Instead of having someone tell you exactly what to do, people tell you what the problem is and you figure out how to solve it. I get to work with many different groups, from homeowners to our professional community to people on other teams at Houzz, and create the best possible product for their needs. At Houzz, engineers get to wear many hats and make important product decisions.

What’s something that has surprised you about working at Houzz?
The vast array of people who use Houzz. I have to think about building an experience that anyone can easily navigate since not everyone that uses Houzz is tech savvy. Things that might make sense to me, because I use many tech products, might not make sense to everyone. So, I really have to think about continuing to improve the functionality of the product, but not over complicating things. Sometimes we take away certain features to improve the product, making it simpler, while at the same time enhancing the experience.

When do you do your best work?
I used to do my best work at night, but lately I try to come in earlier so that I can have more free time in the evenings.

What do you do when you’re not working?
On weekdays, I go to the gym and play basketball. On weekends, I like to go out, eat, try new restaurants, hang out with friends - mostly around eating.

What’s your favorite cuisine?
Japanese.

Do you have a favorite restaurant?
I like restaurants that serve small dishes so that you can try lots of different things while hanging out with friends. Locally, I like the Japanese skewers at Sumika in Los Altos, and the Spanish tapas and sangria at Iberia in Menlo Park.

Houzz Launches in Sweden and Denmark

$
0
0

We’re thrilled to announce Houzz Denmark and Houzz Sweden, dedicated websites and apps for Danish and Swedish homeowners, home professionals and design lovers.

From the addition of new professional categories like “Product Designer” to new photo categories like “Deck & Balcony,” Houzz.dk and Houzz.se have been tailored to the needs of local users. The launches brought something new for the global Houzz community, too, with the introduction of  “Scandinavian” as a new style on Houzz. Scandinavian is one of the most searched-for styles on Houzz globally, and we’re excited to bring even more of the incredible design inspiration, talent and expertise from the Nordics to our community around the world.

A big welcome (and congrats) to our new Houzz teams and to the vibrant and growing Houzz communities in Denmark and Sweden!

image

Our Houzz Sweden team at the launch party

image

Professional community members check out the new Swedish site

image

A packed house of community members celebrates the launch of Houzz Denmark

image

Sweet Houzz treats in Denmark

Remodeling Goes to the Dogs (and Cats!)

$
0
0

image

We knew pets are popular among Houzzers but were blown away by the response to our first-ever survey of how our community caters to their pet at home: over 10,000 responses in Houzz markets around the world!

The survey revealed that dog and cat owners in Australia and Italy are most likely to have made pet-related upgrades to their home in the last two years (43% each). More than one-third of those in the U.S. updated their home to accommodate their pet in the same timeframe (35%) from flooring (38%) to landscaping (21%) to room layout (19%).

image

Pet parents in the U.S. are most likely to allow their cat or dog to sleep in their bed at night (53% and 41% respectively). Meanwhile, only 14% of dogs in Spain are given a spot in their master’s bed and less than a third of cats have nightly snuggle privileges in France and Germany (30% each). Perhaps this is why pets in France are most likely to have their own bed, bench or seating area in the home (66%), followed by those in Germany (60%) and Spain (59%).

image

Globally, 37-68% of pet owners have special areas in their home for their dog and cat. German pet owners are most likely to designate a dining area (75%) versus just 37% in the U.S. and 28% in Russia. Built-in nooks for pets are most common in Italy (57%) and least likely in the U.S. (20%) and Canada (19%). With this low percentage of designated pet spaces in the U.S., it stands that pets in the States are most likely to have free reign of the furniture (78% of cats and 48% of dogs).

image

While cats are more likely to have full furniture privileges, dogs command more dollars. In the U.S., one in five dog owners spent more than $1,000 on pet items for their home in the last two years (22%) versus 14% of cat owners. For the same category, cat owners were nearly 50% more likely to spend less than $100 than dog owners (27% versus 15% respectively).

image

Homes in the U.S. are the cat’s meow, however, with 13% of cat owners reporting that their cat rules the house versus just 8% of dog owners. Overall, pets are most likely to be in charge of homes in Italy (12%), and least likely to rule in Russia and Denmark (4% each).

Additional global findings can be found here:

image

Houzzer Profile: Aran Yeo, UX and Visual Designer

$
0
0

Aran is a UX and Visual Designer at Houzz, where her responsibilities span everything from creating digital products to crafting a visual language for the site. Outside of work, her favorite things to do include brunching with friends, caring for her houseplants, and taking in a bit of culture at the symphony or opera.

How did you get into design?
I originally studied fashion design in South Korea, where I’m from. There was one class where students had to develop their own fashion brand, including the name of the brand, the logo design, and the clothes. As I worked on the assignment, I realized that I enjoyed the graphic design aspects of developing the brand’s identity more than I enjoyed designing the clothes. I decided to move to New York to study graphic design, and I’ve been in love with the field ever since.

Where you do find inspiration?
People and culture inspire me. I like to travel to different countries and meet new people as often as I can. For example, I was recently in Shanghai – I really enjoyed just walking around the neighborhoods, and getting a feel for the areas of the country that tourists don’t typically visit. I get inspired by so many little things – restaurant signs, the menus on the tables, everything. I also like to see what the latest graphic design and home decor trends are in different countries. 

What’s your favorite part of working at Houzz?
It’s similar to what inspires me – I really like that there are people of so many different cultures and backgrounds at Houzz. The members of our design team are all from different countries. I’ve learned how to say “Cheers” in Russian, Hebrew, Chinese, so many languages. We also come from different work backgrounds – some have very product-centric backgrounds, while others came from traditional advertising agencies. We learn a lot from each other because of our different experiences. I just love the diversity here.

What’s your approach to home decor?
I like to take items that are inexpensive and make them look high-end. While I admit that I tend to have expensive taste, I also know that this doesn’t mean that I have to buy pricey furniture and decor to have a beautiful home. It’s similar to fashion – it’s all about mixing high-end pieces with less expensive items to create a unique look. I love when people come to my home, and point at something they like, and I can say that I bought it for a surprisingly low price.

How do you use Houzz?
Houzz helped me remodel my parents’ new apartment in South Korea before I even joined the team here. My parents wanted to remodel their home, but didn’t know how to go about it. I stayed with them for three weeks, and helped my mom remodel the entire place. The contractors didn’t speak English, but with the Houzz app, they didn’t need to – I just showed them pictures of what we were thinking of on Houzz, and they got it. The pros we worked with all downloaded the app after that!

What’s your favorite thing you’ve worked on at Houzz?
It’s tough to choose! But if I had to pick something outside of our core products, it would be one of the early projects I worked on, redesigning the “About Houzz” section of our website, including the “Careers” and “Press Info” pages and the Houzz blog. I was new to Houzz at the time, and the project gave me a chance to learn a lot more about the company. For instance, in order to figure out how to design the press pages, I had to read all of the articles and press releases first. Because Houzz has so many international teams, I also needed to determine how best to organize the “Careers” page. Did it make sense to arrange openings by location, or by team? I loved figuring out answers to those questions.

Whenever we interview new people, it makes me feel good to know that they all probably looked at these pages, and applied for the position through a space that I created. I’m so glad to be a part of that process!


Introducing Houzz for Apple TV

$
0
0

image

Our mission since day one has been to provide the best experience for home renovation and design through technology. We’re excited to share that the Houzz experience is now available on Apple TV®, bringing home design to your living room.

Houzz for Apple TV has been imagined and built from the ground up to optimize the new device’s features. Apple TV provides a rich and immersive format for exploring beautiful home photos, discovering millions of new products and watching original video content from Houzz. With the Apple TV app, decorating or renovating your home is a fun and communal experience together with friends and family.

image

Here are a few of our favorite things to do with the Houzz app, tailor-made for Apple TV:

  • View over eight million retina-quality home photos as a slideshow by pressing Play on the touch remote. You can filter photos by room, style, size, budget, layout and more and save your favorites to ideabooks
  • Play with swinging products tags with the new Apple TV remote. Thanks to the remote’s accelerometer, the tags swing in time to the movement of your hand. Click a tag to learn more about a particular product 
  • Watch Houzz TV … on TV. From a single dad who remodels an airstream trailer and creates a home for his daughter, to a mother of six who creates a spectacular laundry room on a $400 budget, to a surprise home renovation Ashton Kutcher undertakes for his mom, you can now enjoy original Houzz TV programming on the big screen

image

Check our blog over the coming days to learn more about our development process for Apple TV.

A Spooktacular Houzz-o-ween!

$
0
0

image


From festive decor to pumpkin carving to costumes galore, Houzzers around the world got into the spirit of Halloween this year. Check out a few photos from our haunted Houzz festivities:

image

Members of our U.S. editorial team decked out as Houzz of Cardz.

image

A very merry unbirthday to the Alice in Wonderland crew, Mad Hatter and all!

image

A life-sized toilet bot strutted his stuff during the costume contest fashion show. Read more about the toilet bot here.

image

Getting crafty with egg painting and pumpkin carving in the Berlin office.

image

The making of a masterpiece.

image

Our Australian team had an ostrich-riding-tourist stop by the office.

image

Even Crumpet, the Australian team’s office dog, dressed up. Have you ever seen a cuter Frenchie Fry?

image

Our Orange County team got creative with pumpkin painting. Special delivery from Houzz!

image

Welcome to the Animal Houzz.

Renovation Industry Surpasses Pre-Recession Peak

$
0
0

Last week, I attended the Remodeling Futures Conference at Harvard Joint Center for Housing Studies (JCHS). There, JCHS announced that the home renovation market size will have reached $326 billion by the end of 2015, based on data from U.S. Census Bureau, a whooping 1.5 billion above the 2007 pre-recession peak levels, as shown in the chart below.

image

These market estimates support Q2 Houzz Renovation Barometer findings on the state of the industry as of July 2015. The Barometer revealed that over two-thirds of residential architecture, design, contracting, design-build, and renovation and outdoor specialty companies reported revenues and profits were at or above levels they considered to be “normal” before the recent recession in the first six months of 2015 (see Chart 2 below). Most impressively, a fifth to a quarter of firms reported that business performance was significantly above “normal,” while a quarter to a third reported that performance was somewhat above “normal.”

image

Furthermore, home professionals on Houzz are highly optimistic about continued market growth into 2016. The Q3 Houzz Renovation Barometer released on October 19, 2015 showed year-over-year index scores above 70 in all the three quarters of 2015, indicating that significantly more firms reported increases in new business activity than decreases in 2015 relative to 2014. These year-over-year increases in the number of inquiries and number and size of new projects are an important indicator that home renovation spending will continue to grow into 2016.

image

As consumer demand for renovations continues to grow due, in part, to aging housing stock, stable home prices, and aging-related investment by Baby Boomers, the outlook for the industry will continue to be quite positive. However, the industry is running into some challenges that will make it difficult to sustain further expansion, which I will address in my next post.

Brotzeit: A Houzzer Tradition in Berlin

$
0
0

image

“You don’t have to cook to enjoy great food” – this is the philosophy behind the Bavarian Brotzeit, a small, bread-based meal. Houzzers in our Berlin office have made Brotzeit their own Wednesday potluck lunch tradition. Each week, the team brings salads, different types of cheeses and other components to set a colorful table. The food is consumed in an old German family tradition: paired with very good sourdough or rye bread as well as a mountain of freshly baked pretzels. Guten Appetit!

image

Developing for Apple TV

$
0
0

image

We recently debuted our newest app, Houzz for Apple TV®, bringing home design to the living room. In these blog posts I will share some of the lessons we learned during the development process.

The Big Picture Developing an app for Apple TV is quite different from developing an app for iPhone or iPad, in several ways. To start, an iPhone / iPad user is typically a single user, interacting with the screen from a close distance. The TV experience, on the other hand, is often more communal, with several people sitting together watching the screen, and watching it from a 10-foot distance. This should greatly dictate how you design your app; you want to have a bigger screen presence, and short texts. In general, we found the screen “smaller” than that of an iPhone in terms of the number of items we could show at one time. With the TV screen, we had to show larger items, and have a focused item on screen at all times, yet leave room for the focus engine to do its zoom magic (more on the focus engine later). 

The user interaction model is also quite different in that you don’t touch the screen as you do on iOS, you manage the focus with the remote, moving from one UI element to another. An element always needs to be in focus on screen to receive the touch events from the remote.  

You interact on tvOS with the same gestures you’re familiar with from iOS. Single finger gestures are supported, and the remote supports both a touch and a click. The remote also has an accelerometer and gyro just like an iPhone. The remote has two buttons, which are used to navigate content: the menu button, typically used to navigate back through the view hierarchy; and the play/pause button, used for playing content.

Another difference is that there is no persistent storage on the device. You can write to the caches directory or the NSTemporaryDirectory and expect it to be available while your app is in the foreground, but once moved to the background, the system may purge it and there is no guarantee it will be there on your next app session. Instead, if you need persistent storage, you will need to use iCloud storage. You can also use NSUserDefaults for persistence of key/values, but note NSUserDefaults storage is limited to 500 KB max. iCloud key/value storage is limited to 1 MB max, otherwise you would need to use CloudKit or you can always store things on your own server.

This brings me to another mindset change: the Apple TV is an always-connected device. Wifi is likely to be available, and at a good connection speed, the user will want to stream movies.

Another consideration, which didn’t impact us at Houzz since our bundle size is small, is that the app bundle on Apple TV is limited to 200 MB and you have to use iOS 9 on demand resources if you need more.

tvOS doesn’t support UIWebView or its friends, SFSafariWebViewController and WKWebView. No workaround is available – you just don’t do web content in a native app. You have the option of doing a TVML app, but we didn’t take that route. And at this point, it’s important to mention that the Javascript/ObjC bridge, Core Javascript, is also not available on tvOS.

We also had to strip everything related to social from our TV app. The social frameworks are not available on the Apple TV, including Twitter, MessageUI and the Accounts frameworks, as well as Facebook.

Architecture One of the issues we faced was how to setup our code and project architecture to share code between our iOS app and tvOS app. It was clear most of the UI would have to be re-written for  Apple TV, but we could reuse a lot of our model and communication infrastructure. What helped us to get things rolling quickly was that our code was already structured into a Core Houzz framework that included all of the communication with our server and our data model since we support app extensions on iOS 8. It was a simple matter of recompiling that framework for tvOS. The first thing we encountered is that Xcode doesn’t let you link a framework compiled with iOS to a tvOS app, and that there is no way to have one configuration compiled with the iOS SDK, and one with the tvOS SDK. We ended up duplicating our CoreHouzz framework target to a CoreHouzzTV target that was compiled using the tvOS SDK.

If your project is built similarly, it should be easy to create a framework for the tvOS. Again we encountered some iOS/tvOS differences we had to reconcile. In the code, we used a lot of the pre-compile predicate:

   #if TARGET_OS_TV
   #endif

libsqlite is not available on tvOS, so we had to #if it out. It was used for some persistent storage, which we were able to do without, with some minimal iCloud usage. The UIInterfaceOrientation enum is not defined for tvOS (obviously since no one turns their TV on its side!), though I wish Apple would have left that and given it a value of landscape. All of the rest of the status bar orientation related methods are also unavailable on tvOS. 

Once we had our core framework compiled for tvOS, the rest of the work entailed creating the view controllers and views for our TV app. We did share some very basic views between our iOS and tvOS - views like showing a gradient, loading an image from a URL, displaying a rating, etc.

Get Focused As I’ve mentioned, a big part of the development pertains to managing the focus, as there is always one focused element on screen. You can find out the focused view by:

    UIScreen.mainScreen().focusedView

You can choose the initial focus and the focus engine will move the focus from item to item on the screen based on the user touch input on the remote. You can be notified of these changes. The key is a new protocol, UIFocusEnvironment, that is conformed by UIView and UIViewController. This protocol lets these objects manage the focus in the view hierarchy they control.

Only UIViews and subclasses of UIView can become focused.

    override func canBecomeFocused() -> Bool {
      return true
    }

To indicate a view can get the focus, override the method canBecomeFocused:

To set the initial focus, the focus engine traverses the responder chain, starting from the UIWindow, and asks for the preferredFocusedView, so you need to override it as such:

    override var preferredFocusedView: UIView? {
    
       return theViewToFocusFirst
    }

This, of course, can be done in either UIView subclasses or UIViewController. In the case of UICollectionViewDelegate or UITableViewDelegate there is a different method you can use:


    func tableView(tableView: UITableView, 
                   canFocusItemAtIndexPath ip: NSIndexPath) -> Bool
    func indexPathForPreferredFocusedViewInTableView(tableView: UITableView)  -> NSIndexPath?

    func collectionView(collectionView: UICollectionView, 
    canFocusItemAtIndexPath indexPath: NSIndexPath) -> Bool
    func indexPathForPreferredFocusedViewInCollectionView(collectionView: UICollectionView) -> NSIndexPath?

To get notified of focus changes, you implement the didUpdateFocusInContext function from the UIFocusEnvironment protocol:


func didUpdateFocusInContext(context: UIFocusUpdateContext,
      withAnimationCoordinator coordinator: UIFocusAnimationCoordinator)

The focus update context is an object that tells you the current focused view and the previous focused view. The UICollectionViewDelegate and UITableViewDelegate provide index path based variations of these functions:


   func collectionView(collectionView: UICollectionView, 
        didUpdateFocusInContext context: UICollectionViewFocusUpdateContext,            
        withAnimationCoordinator coordinator: UIFocusAnimationCoordinator)

The UICollectionViewFocusUpdateContext is the same as the focus context object, except it provides index paths for the views.

Finally, each UIView has a focused property you can observe using KVO to be notified when the view focus state changes.

If you need to update the focus programmatically, you can use setNeedsFocusUpdate() and updateFocusIfNeeded(). Any object that controls the currently focused view, i.e. a parent view or a controlling UIViewController, can ask to update the focus. The focus engine then asks the responder chain for their preferredFocusedView as in the initial focus set. UIKit will automatically ask to update the focus on certain events - the focused view is removed from the view hierarchy, a view controller is presented or dismissed, etc.

One case where we needed to update the focus programmatically demonstrates the difference in managing the focus on an Apple TV versus managing user interaction on an iPhone. The scenario was that we wanted to present some information to the user and have them be able to proceed on a tap anywhere. We proceeded like we would on iPhone: we added a clear view on top of our UIViewController’s root view, added a UITapGestureRecognizer to it, and expected it to call us when it detected a tap. The problem was that taps continued to be detected in the views that were underneath our clear view. When we added our clear view, the focus environment didn’t change and the focused view remained the same view that was there before we added it to the view hierarchy. The solution was our view controller called setNeedsFocusUpdate() after adding our clear overlay view and returned it in its preferredFocusedView. Now the new view was the focused view (it had to also override canBecomeFocused on that view) and it received the touch events.

Summary We’ve covered in this post the main differences between iOS and tvOS and what you need to consider when developing for tvOS. Apart from the technical challenges in setting up your Xcode project for both iOS and tvOS, the main difference is in the focus-based navigation and in designing for a 10-foot viewing experience. In the next post we’ll cover some more programming challenges and examples.

Developing for Apple TV, Part II

$
0
0

image

In the last post we covered the main differences developing for tvOS, how to set up your project, and some of the details related to managing the focus. In this post, we’ll dive more into focus management using focus guides. UIFocusGuide inherits from UILayoutGuide and enables finer control over the system focus engine.

Using focus guides
The system focus engine typically only searches horizontally or vertically for the next view to put in focus when the user swipes horizontally or vertically on the remote. This was inadequate for navigating between tags on a photo. Tapping on a product tag in a photo on our iOS and Android apps provides information on the tagged product. We wanted to have a similar experience on the Apple TV, but the user can’t tap on a tag. Instead, the user needs to navigate the focus from tag to tag. The default focus engine behavior wasn’t able to handle the case of navigating between arbitrarily placed views. For this scenario, tvOS has focus guides. You can place focus guides directly horizontally or vertically from the focused view to tell the focus engine what view you want focused next if the user navigates in a particular direction. This problem is similar to placing pins on a map and navigating the focus between them. So let’s see how we solved this:

First, lets make a simple TV project. Make a single view TV app project in xcode where we’ll randomly place pins on the view. To do this, we first need to make a pin view. Our pin view is going to be a simple subclass of UIImageView and it will show a pin image. Here is our pin view class:


    class PinView: UIImageView { 
      override init(image: UIImage?) {
       super.init(image: image)   
       adjustsImageWhenAncestorFocused = true // 1
       userInteractionEnabled = true // 2
      }
        
      required init?(coder aDecoder: NSCoder) { // 3
       fatalError(“init(coder:) has not been implemented")
      }

      override func canBecomeFocused() -> Bool { // 4
        return true
      }
    }

Explanation:

1. We set a property on UIImageView that makes it adjust the image or one of its ancestors when it’s in focus. The UIImageView will zoom the photo and make it respond to the user slightly rubbing his finger on the remote.

2. We enable user interaction, which is off by default on UIImageView. Without this, the view will not get the focus.

3. The required initializer. Without this, Xcode is extremely unhappy…

4. We override canBecomeFocused to allow this view to become focused. The default is false.

Now in our view controller we will simply add a few random pins to the view on viewDidLoad as such:


    class ViewController: UIViewController {  
     var pins = [UIView]()
     
     override func viewDidLoad() {
       super.viewDidLoad()
       
       // add pins
       for _ in 0 ..< 10 {
        let pin = PinView(image: UIImage(named: "pin"))
       pin.center = CGPoint(x: CGFloat(arc4random_uniform(UInt32(view.bounds.size.width))), y: CGFloat(arc4random_uniform(UInt32(view.bounds.size.height))))
       view.addSubview(pin)
       pins.append(pin)
      } 
     }
    }

If you run the app now you’ll see the pins on the view, but none are in focus. We need to tell the focus engine to start by having one of the pins in focus. We do this by overriding the preferredFocusedView property on the view controller as such:


    override var preferredFocusedView: UIView? {
      return pins.first
    }

If you now run the app, you’ll see the pins and one of them (the first in the array) will be in focus, it will be larger than the other pins and if you rub your finger on the remote you’ll see it react. However, if you try to navigate between the pins you’ll see that the focus doesn’t move nicely between them as the scanning of the focus engine is built for a grid, not arbitrarily placed views. We need to help the focus engine by placing focus guides.

Let’s start by placing four focus guides at the edges of the view where the focus engine will always hit them when scanning. In the view controller add four focus guide variables:

    class ViewController: UIViewController {
        var leftGuide = UIFocusGuide()
        var rightGuide = UIFocusGuide()
        var topGuide = UIFocusGuide()
        var bottomGuide = UIFocusGuide()

And in viewDidLoad() let’s place them in the view as follows:

        // add focus guides
    view.addLayoutGuide(topGuide)
        
    NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|[guide]|", 
        options: .DirectionLeadingToTrailing, 
        metrics: nil,
        views: ["guide": topGuide]))
    
    NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[guide(1)]", 
        options: .DirectionLeadingToTrailing, 
        metrics: nil, 
        views: ["guide": topGuide]))

    view.addLayoutGuide(bottomGuide)
       
    NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|[guide]|", 
        options: .DirectionLeadingToTrailing, 
        metrics: nil,
        views: ["guide": bottomGuide]))
        
    NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[guide(1)]|", 
        options: .DirectionLeadingToTrailing, 
        metrics: nil, 
        views: ["guide": bottomGuide]))

    view.addLayoutGuide(leftGuide)
       
    NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[guide]|", 
        options:.DirectionLeadingToTrailing, 
        metrics: nil,
        views: ["guide": leftGuide]))
        
    NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|[guide(1)]", 
        options:.DirectionLeadingToTrailing, 
        metrics: nil, 
        views: ["guide": leftGuide]))

    view.addLayoutGuide(rightGuide)
       
    NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[guide]|", 
        options:.DirectionLeadingToTrailing, 
        metrics: nil,
        views: ["guide": rightGuide]))
        
    NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("[guide(1)]|", 
        options: .DirectionLeadingToTrailing, 
        metrics: nil, 
        views: ["guide": rightGuide]))

Now that we have our focus guides, when the view controller gets notified of a focus change, it will set the next view we want focused if the user swipes in each direction and the focus guide is hit by the focus engine scanning, so in didUpdateFocusInContext we add:



      override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
        if let focusedView = UIScreen.mainScreen().focusedView as? PinView {
            if let nextView = findNextViewFromView(focusedView, searchAngle: 0) {
                rightGuide.enabled = true
                rightGuide.preferredFocusedView = nextView
            } else {
                rightGuide.enabled = false
            }

            if let nextView = findNextViewFromView(focusedView, searchAngle: M_PI) {
                leftGuide.enabled = true
                leftGuide.preferredFocusedView = nextView
            } else {
                leftGuide.enabled = false
            }

            if let nextView = findNextViewFromView(focusedView, searchAngle: -M_PI_2) {
                topGuide.enabled = true
                topGuide.preferredFocusedView = nextView
            } else {
                topGuide.enabled = false
            }

            if let nextView = findNextViewFromView(focusedView, searchAngle: M_PI_2) {
                bottomGuide.enabled = true
                bottomGuide.preferredFocusedView = nextView
            } else {
                bottomGuide.enabled = false
            }
        }
    }



What are we doing here? First we test if the focused view is a PinView (in case we have other views in our view). If it is, using a method we’ll provide soon, findNextViewFromView will find the next logical view to place the focus if the focus direction is searchAngle. We repeat this for all focus guides.
So what is our findNextViewFromView method? We assume we want to focus the nearest view in the search angle within a tolerance of plus or minus 45 degrees. This is expressed by the following method:



    func findNextViewFromView(currentView: UIView, searchAngle: Double) -> UIView? {
        let currentViewCenter = currentView.center
        var foundView: UIView? = nil
        var distanceToFoundView: CGFloat = 0

        // iterate over all pin views
        for aView in pins {
            if aView == currentView { // skip the current view
                continue
            }
            let location = aView.center
            let difference = CGPoint(x:location.x - currentViewCenter.x, y:location.y - currentViewCenter.y)
            var angle = fmod(Double(atan2(difference.y, difference.x)) - searchAngle, 2 * M_PI)

            // bracket the angle to be between -pi & pi
            if angle > M_PI {
                angle -= 2 * M_PI
            } else if angle < -M_PI {
                angle += 2 * M_PI
            }
            if angle > -M_PI_4 && angle < M_PI_4 {
                // it's in a good angle
                let distance2 = difference.x * difference.x + difference.y * difference.y
                if foundView == nil || distance2 < distanceToFoundView {
                    foundView = aView
                    distanceToFoundView = distance2
                }
            }
        }

        // do alternate search criteria if we didn’t find anything
        if foundView == nil {
            if searchAngle == 0 || searchAngle == M_PI {
                foundView = findViewAlongX(currentView, positive: searchAngle == 0)
            } else {
                foundView = findViewAlongY(currentView, positive: searchAngle > 0)
            }
        }

        return foundView
    }

Which iterates over all the pin views and finds the nearest one. If we don’t find a suitable view within a plus or minus 45 degrees, we do a different kind of search. The findViewAlongX and findViewAlongY will search for the view along the X axis in the positive or negative direction whose Y distance is the smallest, and likewise along the Y axis. Here are the implementations:


 func findViewAlongX(currentView: UIView, positive: Bool) -> UIView? {
        let currentViewCenter = currentView.center
        var foundView: UIView? = nil
        var distanceToFoundView: CGFloat = 99999
        for aView in pins {
            if aView == currentView {
                continue
            }
            let location = aView.center
            let difference = CGPoint(x: location.x - currentViewCenter.x, y: location.y - currentViewCenter.y)
            if ((positive && difference.x > 0) || (!positive && difference.x < 0) && fabs(difference.y) < distanceToFoundView) {
                foundView = aView
                distanceToFoundView = fabs(difference.y)
            }
        }

        return foundView
    }

    func findViewAlongY(currentView: UIView, positive: Bool) -> UIView? {
        let currentViewCenter = currentView.center
        var foundView: UIView? = nil
        var distanceToFoundView: CGFloat = 99999
        for aView in pins {
            if aView == currentView {
                continue
            }
            let location = aView.center
            let difference = CGPoint(x: location.x - currentViewCenter.x, y: location.y - currentViewCenter.y)
            if ((positive && difference.y > 0) || (!positive && difference.y < 0) && fabs(difference.x) < distanceToFoundView) {
                foundView = aView
                distanceToFoundView = fabs(difference.x)
            }
        }

        return foundView
    }

Running the app now, you’ll see it’s easy to navigate the focus between the randomly placed views.

Summary

Using focus guides you can enable complex focus navigation behavior. We’ve seen in this post how we handled the focus navigation between arbitrarily placed views.  This is a general problem similar to navigating between pins on a map. You can get the entire code of this blog post on GitHub here.

A Happy Houzzgiving!

$
0
0

image

Last night, Houzzers in our Palo Alto HQ gathered for our annual Thanksgiving feast to celebrate the holiday together as a Houzz family. Of course we had the staples: sliced turkey, roasted sweet potatoes and Brussels sprouts (with brown sugar!), as well as apple and pecan tarts. We had some updated takes on the traditional favorites, too, like butternut squash lasagne. Yum!

image

The extensive spread at the feast.

image

Samantha, Arya and Skylar were all smiles ahead of dinner.

image

Houzzers enjoying the holiday meal.

Happy Thanksgiving from Houzz!


Introducing Sketch, a New Way to Bring Design Ideas to Life

$
0
0

image

Users flip through more than one billion photos on Houzz apps every month, and spend over an hour a month on average on the Houzz app. Today we’re thrilled to introduce Sketch, an entirely new function within the free Houzz app for iPhone® and iPad® devices, that enhances the most popular (and addictive) features of our app – photos and ideabooks. With Sketch, users can communicate more easily through photos and add products from the Houzz Marketplace to any photo. The feature is optimized for the 12.9-inch Retina display on the iPad Pro™ making Houzz photos look even more brilliant, with Apple Pencil™ support.

Sketch was developed based on feedback from our community, and as a tool to enhance the experience on Houzz. Homeowners use the Houzz app at every stage of a home project – whether they’re decorating a small room on a budget or building a custom home and everything in between. Home professionals (contractors, designers, architects, and more) use the app to communicate and collaborate with their clients, as well as with vendors and subcontractors on the jobsite. Sketch enables homeowners to be more specific about what they want, and enriches collaboration with pros and others on Houzz by allowing multiple people to simultaneously annotate the same photo.

We listened to our community to develop many of Sketch’s features. For example, we noticed that many people post hand-drawn floor plans in our Advice section to get input from the community on their design decisions. Now users can select from two dozen Sketch Canvases to create mood boards and floor plans in an easy and lightweight way. People told us they wanted to be able to mark what they like in a photo. With Sketch, users can write notes or select from over 150 stickers to express what they feel about a photo and what they’d like to do for their own design. 

You can read more about Sketch features here. From now until December 25th, Houzz users are automatically entered to win the products they add to their Sketch, up to $1,000 in value. See terms of sweepstakes here.

Happy Sketch’ing! 

A Sweet Gingerbread Showdown

$
0
0

image

To get into the holiday spirit, Houzzers in our Palo Alto office competed in a fun Gingerbread Houzz contest. Each team worked together to design and build a sweet dream home. There are a number of talented gingerbread architects and designers on our team – selecting winners wasn’t easy for our judges, cofounders Adi and Alon and our office team. After a few days of deliberation, these homes were awarded the top prizes:

image

The editorial team won first place for their incredible treehouse, complete with a mini lending library and tiny twinkle lights. The concept was inspired by stories on Houzz, including one on an elaborate kids’ treehouse in Dallas, and one on Little Free Library, a nonprofit that places small neighborhood book exchange boxes all over the world.

image

Second place went to the design team for this midcentury modern masterpiece. The creation even included “save” and “email” buttons, just like photos on Houzz!

image

The data operations team snagged third place for their intricate Hogwarts-themed design.

image

Happy Holidays from Houzz!

Congrats to the Best of Houzz 2016 Winners!

$
0
0

image

You may see a new badge or two on your favorite home pro’s profile. Today we revealed our community’s picks for Best Of Houzz 2016, a homeowner-to-homeowner guide to the top home builders, architects, interior designers, landscape pros and other home remodeling professionals on Houzz. A “Best Of Houzz 2016” badge appears on winners’ profiles, as a sign of their commitment to excellence. These badges help homeowners identify popular and top-rated home professionals in every metro area on Houzz.

The Best Of Houzz is awarded annually in three categories: Design, Customer Service and Photography. Design award winners’ work was the most popular among the more than 35 million monthly users on Houzz. Customer Service honors are based on several factors, including the number and quality of recent client reviews. Architecture and interior design photographers whose images were most popular are recognized with the Photography award. Winners will be announced globally throughout the month.

To check out the most popular designs, go to http://www.houzz.com/best-of-houzz-2016

Houzz App for Android Now Updated with Sketch

$
0
0

image

Our powerful new mobile function, Sketch, is now available on the free Houzz app for Android™. Sketch makes it even easier to communicate through images and to bring design ideas to life by adding products from the Houzz Marketplace to any photo.  

Houzzers can simply tap the Sketch button on any photo on Houzz or upload a photo to an ideabook to start Sketch’ing. You can read more about features here and check out the demo below.

Update your Houzz app on Google Play™ here to get Sketch.

Android Sketch 2016_01_09_08_05_54_0000-0101-revised2

The New “Super Kitchen” Calls for Pro Help, Houzz Survey Finds

$
0
0

image

Transitional Kitchen

Do you entertain in your kitchen? Use it as a home office? Or watch TV while cooking? Our 2016 U.S. Kitchen Trends Study revealed the rise of the “super kitchen,” a multi-functional space that is used as much for living as other traditional living spaces of the home. To create a custom kitchen that works with their lifestyle, more homeowners on Houzz are turning to professional help for their kitchen projects. Out of the 2,400 U.S. survey respondents who are either planning, in the midst of, or recently completed a kitchen project, nine out of ten enlisted the help of a professional – 87%, up from 80% in 2014. Kitchen renovators are turning to general contractors in particular (54%), followed by kitchen designers (27%) and interior designers/decorators (14%).

image

Given the sizeable scope of many kitchen upgrades, it makes sense that a larger share of homeowners is looking for pros to help turn their vision into reality. For instance, nearly half of Houzzers are changing the layout of their kitchen during the project (48%), and 37% are increasing the size of the room. Most Houzzers choose a U-shape for their new layout (35%), followed by an L-shape (28%).

image

Major new built-ins and specialty features abound in updated kitchens, also likely contributing to the increased need for professional help. New built-in features include everything from cabinet pantries (43%) and islands (37%) to coffee/tea (10%), beverage (8%) and baking stations (7%). When it comes to major features, 93% of Houzzers are upgrading their countertops, 89% are tackling their plumbing fixtures and sinks, and 88% are updating their backsplash.

image

For more insights from the 2016 U.S. Houzz Kitchen Trends Study, check out the full report here.

Viewing all 284 articles
Browse latest View live