The CSS Grid Challenge: Build A Template, Win Some Smashing Prizes!

The CSS Grid Challenge: Build A Template, Win Some Smashing Prizes!

Layout on the web has always been tricky, but with CSS Grid being now supported in all major browsers, most of the hacks that helped to achieve complex layouts have become obsolete. Firefox even has a CSS Grid Inspector1 built in, so that there’s nothing to hold you back from making even the most challenging flexible layout reality.

To explore the possibilities and features of CSS Grid together, we’d love to invite you to a little contest. Because there’s nothing better to completely grasp a new technology as getting your hands dirty and playing with it, right?

Show your CSS Grid skills and, with a bit of luck, win a smashing prize.

The Challenge Link

Now, here’s the challenge: You create an interesting, accessible layout with CSS Grid, or use CSS Grid to rebuild an existing layout. What you design is entirely up to you. Feel free to use Flexbox additionally as well, e.g. as fallback for browsers not supporting CSS Grid. The only requirement is that the template you submit doesn’t break in IE9 and is still fully accessible in IE8. Deadline: September 30th.

At the end of the contest, all templates and layouts will be made available to everyone for free download under the MIT license. So you can use them for personal and commercial projects without any restrictions. The aim is to build a community repository full of CSS Grid goodness that inspires fellow developers and helps spread the wide adoption of CSS Grid.

So, What Can You Win? Link

After the deadline has ended, we’ll announce the lucky winners who’ll win a quite extraordinary smashing prize (and a couple of other Smashing extras, see below):

  • a round-trip flight to Barcelona, Spain,
  • full accommodation in a fancy hotel,
  • a ticket to the Smashing Conference Barcelona 20172,
  • a Smashing workshop of your choice,
  • a signed edition of our upcoming book Design Systems3 by Alla Kholmatova,
  • your very own Smashing caricature, designed just for you.

Getting Started With CSS Grid Link

Last but not least, before you dive right into the challenge, here are some helpful resources to kick-start your CSS Grid adventure.

Resources and References Link

Demos Link

Tutorials Link

Talks Link

Inspiration Link

Finally, to get your ideas flowing, some inspiring CodePen experiments that illustrate the magic of CSS Grid:

Responsive Magazine Layout16
Responsive Magazine Layout17 by Heather Buchel
Minimalistic CSS Grid Layout18
Minimalistic CSS Grid Layout19 by Nate Green
CSS Grid Layout and Comics20
CSS Grid Layout and Comics21 by Envato Tuts+
Auto Hexagonal CSS Grid Layout22
Auto Hexagonal CSS Grid Layout23 by Kseso
CSS Grid Layout with @support Flexbox Fallback24
CSS Grid Layout with @support Flexbox Fallback25 by Gustaf Holm
Image Areas in CSS Grid Layout26
Image Areas in CSS Grid Layout27 by Michael Gehrmann
Mondrian Art in CSS Grid28
Mondrian Art in CSS Grid29 by Jen Simmons
CSS Grid Layout Slideshow30
CSS Grid Layout Slideshow31 by Manoela Ilic

Join In! Link

Want to be a part of it? Great, we’d love to see what you’ll come up with!

  • Once you’ve completed your shiny CSS Grid layout, please send us a link to cssgrid@smashingmagazine.com (a CodePen link works just fine),
  • The deadline is September 30.

Ready to take on the challenge? Let’s go! We’re already looking forward to your submissions. Have fun!

Footnotes Link

  1. 1 https://hacks.mozilla.org/2017/06/new-css-grid-layout-panel-in-firefox-nightly/
  2. 2 http://smashingconf.com/barcelona-2017/
  3. 3 https://www.smashingmagazine.com/design-systems-book/
  4. 4 http://cssgridgarden.com/
  5. 5 https://github.com/rachelandrew/gridbugs
  6. 6 https://github.com/valentinogagliardi/awesome-css-grid
  7. 7 https://gridbyexample.com/
  8. 8 https://www.smashingmagazine.com/2016/11/css-grids-flexbox-box-alignment-new-layout-standard/
  9. 9 https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout
  10. 10 https://github.com/ademilter/chrome-css-grid-highlighter
  11. 11 http://labs.jensimmons.com/
  12. 12 https://codepen.io/collection/XRRJGq/
  13. 13 https://www.smashingmagazine.com/2017/06/building-production-ready-css-grid-layout/
  14. 14 https://www.smashingmagazine.com/2017/07/enhancing-css-layout-floats-flexbox-grid/
  15. 15 https://hackernoon.com/getting-started-with-css-grid-layout-8e00de547daf
  16. 16 https://codepen.io/hbuchel/pen/qOxGzW
  17. 17 https://codepen.io/hbuchel/pen/qOxGzW
  18. 18 https://codepen.io/nategreen/pen/GpRLXY
  19. 19 https://codepen.io/nategreen/pen/GpRLXY
  20. 20 https://codepen.io/tutsplus/pen/pNgZpj
  21. 21 https://codepen.io/tutsplus/pen/pNgZpj
  22. 22 https://codepen.io/Kseso/pen/xqNdmO
  23. 23 https://codepen.io/Kseso/pen/xqNdmO
  24. 24 https://codepen.io/primalivet/pen/ryjKmV
  25. 25 https://codepen.io/primalivet/pen/ryjKmV
  26. 26 https://codepen.io/g12n/pen/PPpGvL
  27. 27 https://codepen.io/g12n/pen/PPpGvL
  28. 28 https://codepen.io/jensimmons/pen/aNjXLz
  29. 29 https://codepen.io/jensimmons/pen/aNjXLz
  30. 30 https://tympanus.net/Development/GridLayoutSlideshow/
  31. 31 https://tympanus.net/Development/GridLayoutSlideshow/

↑ Back to topTweet itShare on Facebook

Dwelling On The Past: The Importance Of Project Retrospectives (Part 1)

Dwelling On The Past: The Importance Of Project Retrospectives (Part 1)

We should always look for opportunities to grow and improve. Retrospectives and reflections allow you to codify what you’ve learned from experience, to document mistakes and avoid future ones, and to increase your potential to grow in the future. Agile methodologies typically include time for retrospectives throughout a project. Regardless of your methodology, all teams would benefit from having a retrospective at the conclusion of a project.

Additionally, we can learn from our mistakes, identify what works well, and better understand ourselves through personal reflection. Retrospectives and reflections do not have to be time-consuming. I’ll show you a few approaches that you and your team can immediately incorporate into your practice.

I have found post-project retrospectives to be one of the most effective ways to grow as a professional. I see this in my design team colleagues as well. We’ll walk through post-project retrospectives in this first article. I have also seen evidence of the effectiveness of structured reflection for both personal and professional growth. In a second article, I will present some lessons learned and researched-backed techniques that those who wish to engage in reflection can attempt to include in their routine.

Defining Goals And Outcomes Link

Facilitation leads to better user experiences through smoother, more collaborative and more satisfying design processes. It also helps you understand how people work and how to work better with them. Read more →1

What Is A Retrospective? Link

A retrospective is a structured meeting to review the process and outcomes of a particular project. You can conduct a retrospective at any point in a project. If you practice agile principles, then you probably incorporate retrospectives after every couple of iterations (or sprints). However, everyone would benefit from a postmortem, or post-project retrospective, regardless of your specific design and development methodology.

Retrospectives do not require intense resources to plan or conduct. Some costs are associated with retrospectives, particularly with getting your team together to work on something that will pull them away from their projects. You will need to budget expenses for time if you work with contractors on your team. You will need to consider when to hold the retrospective; you don’t want to pull members away from other work at critical times or to disrupt their productivity.

The rewards of running effective retrospectives outweigh the costs. Effective retrospectives require a commitment to maintain an open mind and open communication with your team, as well as a willingness to be vulnerable. If you engage in retrospectives with these commitments, you can expect your team members to grow individually and as a group. You can expect your team and each member to better understand how to improve their process.

2
Engaging in retrospectives helps to finely tune your team. (Image: Wikimedia3)

What Isn’t A Retrospective? Link

Project retrospectives are an important component of healthily functioning teams. In order to fully benefit from retrospectives, you should keep in mind some limitations and guidelines:

  • Retrospectives do not replace communication or action taken to fix team or project issues at the time of occurrence.
  • Retrospectives are not an excuse to spend an hour complaining (although it is important to let some venting happen during the session).
  • Retrospectives are not an opportunity to lecture your team on what they could have done better. Ideally, you would be proactively coaching your team throughout the project.
  • Retrospectives should not be a huge burden on your time and resources. I recommend 60 to 90 minutes for reflection if you have a team of 5 or 6 people. This gives everyone ample time to discuss each of the broad themes we’ll cover later. This also forces people to be wise with the time they have during the retrospective.

Why Conduct A Retrospective? Link

Your team would benefit greatly from properly planned and executed retrospectives. We learn something new about ourselves, our product and our team in every project. We also risk losing this knowledge or failing to incorporate the lessons if we don’t engage in retrospectives. You codify the lessons learned when you conduct retrospectives. You solve team issues as a team.

Researchers have identified many benefits from software design and development teams engaging in project retrospectives (see the links at the bottom for references). Some of these benefits include:

  • ensuring that team members recognize and remember what they’ve learned,
  • allowing team members to share their experiences with each other,
  • identifying opportunities for the team to improve,
  • providing an opportunity to initiate change,
  • acknowledging what went well during a project.

Project retrospectives are a means to show your commitment to your team. When you engage in retrospectives, you are signalling to others that you take learning from experience seriously. You are telling the team that you understand that perfection isn’t possible; there is always something to learn from experience. You are prioritizing growth and learning over pushing out a product and moving on to the next challenge. Team morale and performance improve when you reflect these values.

Planning A Retrospective Link

Allow for sufficient time to plan your retrospective. Whoever is facilitating the session should have an idea of how the project went. They should have a few talking points for each area to be discussed, in case the conversation needs prompting.

I have participated in retrospectives facilitated by project managers, by team or project leaders and by managers. Appoint someone who has training in facilitating conversations. If you have a team member trained in agile methods, they are likely to have some training on running retrospectives. Regardless of who facilitates the session, they should have a neutral stance towards all of the information that members of the team present. They should be fair in how they run the meeting. They should not be someone in a position of power who might intimidate any team members from speaking up.

Team members should know, preferably at the beginning of the project, that a retrospective will be taking place. You can suggest to team members to keep logs or make diary-type entries in a notebook or online in order to keep track of how they feel about the project as it unfolds. It’s difficult to recall specific things that worked well or that needed improvement at the end of a project. Proactively logging one’s experience helps to avoid this.

Your team’s logs could look similar to the prompts used during a retrospective:

Project Name and Date
What’s working well? Notes
We are all on the same page with the work being done. We frequently meet internally to discuss who is doing what. We are keeping our sprint backlog up to date.
What isn’t working well? Notes
The client has complained that communication isn’t streamlined. We were given multiple points of contact (PoC) at the kickoff meeting. We have had trouble getting replies from one of them. Maybe this is why.
How could we improve? Notes
Reduce the number of people we are going through to get permission. Determine who needs to be contacted and what we need to contact them about. We need to determine a single PoC for our team and their team. The client feels that not all of their team needs to be involved in our communication.

Most retrospectives require very few resources to be planned. At a basic level, you can conduct a retrospective with a comfortable meeting room, a whiteboard, dry-erase markers (at least three different colors), a conference-call line, and screen-sharing software or video (for remote team members to participate). Finding a time that works for all team members can be the most difficult part of planning a retrospective.

Whiteboard and dry-erase markers4
Conducting a retrospective does not require a lot of resources. (Image: StartupStockPhotos5) (View large version6)

Below are some specific steps to take to plan your retrospective. Incorporate others as relevant.

Preparing as a Facilitator Link

Determine your list of participants; make sure everyone involved is invited (even remote folks!). Your retrospective is only as good as the people you include. It would be more effective if everyone who has been involved in the project is invited to attend. Perhaps one designer took over for another designer halfway through the project — invite them both. You would benefit from understanding how the transition went, from the viewpoint of both the designer who started on the project and the one who took over. You would benefit from a deeper understanding of the bumps along the road if you include people who were a part of the process in unique ways. However, including some people might not be necessary if their role was extremely limited.

Remote staff are critical to a project retrospective. These team members have a unique perspective. You’ll want to know whether they felt included and actively engaged with their on-site colleagues. You’ll also want to know whether they have suggestions to make their lives easier as remote staff. Likewise, your on-site staff should have a voice regarding what it felt like to work with remote staff and any suggestions they have to improve collaboration with remote team members. We often include video options such as WebEx or FaceTime on iPads to give our remote staff a greater presence at retrospectives.

Ask your team to review their notes and come with the following input:

  • What went well

    For example, “Good communication between research, design and development throughout the project.”
  • What didn’t go well

    For example, “Finalization of deliverables felt rushed throughout the project.”
  • How to fix it

    For example, “Clearly state deadlines throughout the project; have frequent progress check-ins; build in time to review deliverables so that changes can be made.”

Have your team do this prior to the retrospective. You don’t want to put your team on the spot in the meeting. Be clear in the invitation about what the topics of discussion will be. Also, be clear that everyone attending is expected to participate in the discussion.

Reach out to see who is going to say what. You don’t want to get blindsided during the retrospective. You need to know whether something major happened that is going to lead to a longer discussion, in which case you’ll need to plan the right amount of time for that discussion. You also want to try to defuse anything that might seem personal prior to the session. Likewise, if you find that no one has anything critical to say about the project, then you might encourage them to think of some things they could mention.

Important: The point here is not to reach out to argue with team members you don’t agree with, but to have an idea of what folks are going to bring up. Take action prior to the retrospective only if absolutely necessary. You aren’t doing it right if team members feel shut down prior to the session.

Determine your assessment of the project. You should know where the project succeeded and where the project fell short, according to your expectations and performance indicators. You can use these to focus the conversation and to support any arguments made for or against certain issues in the project.

Make the retrospective a celebration of your team. Provide food and drink or some type of treats. Team members will appreciate the effort to create a positive atmosphere, and it will reduce the potential distractions of hunger and thirst.

Preparing as a Participant Link

A retrospective participant shouldn’t have to invest much time preparing. But coming to the session prepared is important. I’ve suggested keeping a log or journal noting how the project unfolded. You can use this yourself as part of your preparation for the retrospective. Come up with a list of three or four things that went well in the project, and three or four things that could have gone better.

Once you’ve refined the list, make sure you haven’t created a list of gripes and personal complaints. Those are valid, but they don’t serve to create a positive retrospective. Resolve any personal issues you’ve had with team members in a more appropriate setting than a retrospective. Convert gripes into problem statements that you can then use to identify solutions in the retrospective.

Conducting A Project Retrospective Link

Many resources are available for conducting a retrospective. Esther Derby provides a five-step approach for retrospectives7 in Scrumpedia. Although the focus is on two-week retrospectives, you can use the same steps for a post-project retrospective. Derby’s steps include: (1) set the stage, (2) gather data, (3) generate insights, (4) decide what to do, and (5) close the retrospective.

Elise Keith presents a three-step process on the Lucid Meetings Blog8: (1) review the project, (2) discuss what worked well and what didn’t, and (3) action planning: identify specific ways to improve future work.

Norman Kerth’s handbook on project retrospectives9 provides four questions to guide a retrospective: (1) What did we learn? (2) What should we do differently next time? (3) What did we do well? (4) What still puzzles us?

There isn’t one right way to do a retrospective. A quick search on Google yields dozens more articles on how to conduct a retrospective. Below, I discuss some key features that every retrospective needs to include.

Managing Discussion Link

Time management is critical for a successful retrospective. You run the risk of having to cut people off if you don’t schedule enough time. You run the risk of people losing interest if your meeting is too long.

Allow discussion to occur when necessary, but with a focus on the solution. You will often find that people agree in a number of areas. For example, everyone might think the project’s timeline was too tight. You can save time by asking people to indicate their agreement with something stated and not bring it up again when it’s their turn.

Be aware of the order you expect people to speak. You can determine the order at random by assigning everyone a number and drawing from a hat. You might want to use a predetermined order based on your awareness of the reality. For example, you might want to encourage junior staff to contribute their own ideas and ask them to go first to discourage them from echoing what senior staff say.

Create a Safe Atmosphere for Sharing Link

This is the most important step. Your retrospectives are worthless if people are not comfortable sharing their true thoughts and feelings. The facilitator should make it immediately clear to participants that everyone’s viewpoint needs to be respected. Ground rules should be set: no confrontational comments or personal attacks, but also no sugarcoating problems.

There will be situations in which specific aspects that need improvement are related to the attitude or skills of an individual team member. I encourage managers or team leads to find ways to have this discussion individually, outside of the retrospective.

On the other hand, if there is an issue related to an individual making decisions that didn’t work out, that’s appropriate to discuss as a group. You can approach these types of situations in a less threatening way by referring to the group rather than the individual. For example, rather than saying, “Victor dragged his feet with starting to recruit people to participate in research, so we fell behind schedule,” you could say, “We thought it would be a good idea to hold off on identifying our research participants, but this led to us falling behind schedule.” This allows the discussion to lead to the conclusion that the person in charge of recruitment should be more proactive about scheduling in the future.

Your retrospective should take place in a comfortable setting, with ample time set aside for attendees to provide feedback. You could consider holding the retrospective off site, in order to put participants at ease.

Create Ownership Link

The project team owns the result of the project. They also own the quality of the retrospective and the ideas coming from it. Challenge your team to constantly improve. You are the facilitator, but the team is tasked with solving issues that arose during the project.

Don’t excuse areas where improvement can be found. For example, if your team struggled with fitting in all the project tasks in a timely manner, don’t provide the excuse that many team members were busy on multiple projects. Instead, push for how to better provide a balance among team members’ duties and other obligations.

Document Everything, Even If Only One Person Says It Link

Ensuring that everyone has a voice is a part of the purpose of a retrospective. You don’t need to gain a consensus on every item someone brings up. You show respect for the individual experience when you acknowledge everyone’s thoughts. You gain buy-in and trust when you do this. Documenting thoughts on the white board allows everyone to see what was said and enables you to track what has been said.

Celebrate the Good Link

Everyone should have something positive to say, even if it’s just “Hey, everyone is alive!” Your team likely contains a mix of personalities. You help to create a positive vibe for the whole group when you call out people for jobs well done and congratulate those who made progress and accomplishments over the course of the project. You also increase team members’ receptiveness to criticism when you provide positive feedback in a retrospective. Did anyone get a promotion during the project? Celebrate that. Did anyone gain a new skill or tool? Celebrate that. Find things to celebrate.

Discuss What Worked Well Link

Do you want the good news first or the bad news? My preference is the good news. We often have much longer discussions about what didn’t work so well for our projects. You don’t want to run out of time and not talk about what worked. Discuss what worked before discussing what your team could have done better.

Discuss What Didn’t Work Link

You’re rarely perfect. Even in a feel-good project, you can find areas to improve. Often, you’ll identify areas around communication that could use tweaking. At one point during an otherwise smooth-running project, I called a meeting to review how we were incorporating research findings into our design concepts. My managing director said something like, “Now let’s hear what development has to say.” I had forgotten to include anyone from development in the meeting, so there was no response. Actually, I hadn’t even thought of the need to include development — we were talking about design and research, right? I had become complacent at that point in the project, forgetting to include key team members in a meeting. We discussed why this happened and the need to invite people to our retrospective throughout the duration of the project.

Identify a Specific Path to Improvement Link

Your team should engage in dialogue to identify possible remedies for the areas in need of improvement. The solutions should be as specific as possible. For example, instead of saying “Invite everyone relevant to each meeting,” say “Invite representatives from every discipline (research, design, development and engagement) to each meeting.” Instead of saying “Begin the process of recruiting research participants earlier,” say “Draft the recruitment screener and email prior to the kickoff meeting, and send the recruitment email immediately following the kickoff meeting, or earlier if possible.”

Come to a Conclusion Link

A project retrospective is meant to be all-encompassing. Cover the project from start to finish, major milestones and deliverables and all other aspects relevant to the project. Your team should feel that they’ve put everything out and had it recorded on the white board. Any issues should have solutions identified. No one should leave the retrospective feeling they didn’t have a chance to participate fully. No issue should be left unresolved, or at least not without a concrete timeline for you to come back to address it.

Post-Retrospective Link

You’ll need to go beyond the retrospective to fully realize its benefit. Document every retrospective and the outcomes your team agreed on. Include a list of who attended, the purpose of the project and any other details to explain the context of the retrospective. You will look back on these at a time when the project will not be as clear in your memory as it is immediately following the retrospective.

You don’t need to do anything time-consuming to document the session. We typically write out everything from the session on a white board. The facilitator takes pictures of the white board and later transfers the information into a document. You can use a simple chart to record what was said:

What worked well? What didn’t work well? Specific steps to improve

Retrospectives become wonderful data points for tracking a team’s progress. Proactively remind your team members of what was agreed upon in the retrospective, and ask them to show evidence that they’ve followed through on any solutions proposed. Track your retrospectives across time to see whether what was in the “Needs improvement” column eventually moves out or even into the “What worked well” column. If you see that the same items continue to find their way into the “Needs improvement” column, then your solutions either aren’t effective or aren’t being implemented. Create a spreadsheet with different tabs based on the projects completed. Record the results of each project’s retrospective in a separate tab. This allows you to consolidate your retrospectives in a way that makes it easy to review progress.

Save the tracking spreadsheet to a storage space that all staff can access. Another benefit of tracking retrospectives is the opportunity to implement successful improvements across projects. You won’t always have the same team members in every project. You can disseminate your findings to the broader team when you track retrospectives. If a solution to a problem in project A is successful, you could try implementing the same solution if you see the issue pop up in a retrospective for project B. You avoid having to reinvent the wheel this way. Similarly, you can avoid solutions that don’t work for problems that reappear in other projects in the future.

A chart showing an increase in performance10
Tracking retrospectives enables you to observe the team’s performance over time. (Image: janjf9311) (View large version12)

So, you’ve conducted a few retrospectives and seen growth. You can call it quits, right? No. Your team members will change over time. Your projects will change in complexity and purpose. By making project retrospectives a standard part of your practice, you reduce volatility and continue on the path of growth.

Case Study: Using Retrospectives With The Same Team Across One Year Of Projects Link

I had a unique opportunity to serve as a core member of a team that spent a year working together on various projects. I served as the lead researcher for each project. The lead designer and lead developer also remained consistent for each project. Our usual model for staffing projects does not specify that teams should stay the same, so this was an experiment.

We conducted a retrospective at the end of each project. At the end of the year, we realized that issues we identified as “What didn’t work well” in earlier projects had moved to the “What worked well” column in later projects. We used this information to create a list of best practices.

Our managing director led the retrospectives. She had played an oversight role for all of the projects, so she had a working knowledge of the topics, successes and challenges we faced. The bulk of each retrospective was spent answering the questions:

  • What worked well?
  • What didn’t work well?
  • What specific ways can we improve our future work?

I’m going to focus on real examples of what came up during our retrospectives. For the sake of brevity, I’m going to provide only a few examples. Our actual lists for each question listed above were extensive. I’ve added highlights to track the progression of issues whose status changed over the course of multiple projects. Each highlight color corresponds to a particular issue as it was tracked across retrospectives.

Project A Link

What worked well? What didn’t work well? Ways to improve
Client working session at our studio Research participant recruitment began too late. We relied on the client to recruit participants due to the sensitive nature of their relationship with users. • Emphasize the importance of clients beginning recruitment ASAP during kickoff meeting.

• Draft recruitment email and send to client for use immediately following kickoff meeting.
Research findings integrated seamlessly into design concepts. Transition to visual design was difficult. Visual design needs were minimal; we waited to identify a visual designer until the project was half-finished. Look for additional opportunities to have clients visit our studio.
Technology assessment findings and user research findings were presented as separate sections. (Would prefer to have seamless presentation of all research and to have tech assessment themes align with user research themes where possible.) Technology and research to meet to integrate findings better into final report.

Project A’s retrospective identified a number of things our team had done well. Specifically, we held a client working session at our studio that went very well and that helped to set up a great final presentation. We continued to look for these opportunities as a way to document their importance.

We also identified three specific issues that could have been better executed on:

  • We were relying on the client to recruit research participants due to the user types we needed access to. Our client had not begun the process of recruiting participants when the project kicked off. This led to a delay in starting the research according to the initial timeline.
  • We limited the involvement of the visual designer until it was absolutely necessary. This was not ideal — the visual designer didn’t have insight into the reasoning for certain design decisions, and getting everyone on the same page took longer, which led to personal frustration for the visual designer assigned to the project.
  • Our technology assessment was presented separate from our research findings, which felt disjointed. This aligned with how we traditionally reported these findings. However, we felt we could challenge ourselves to evolve.

Working as a group, we came up with a list of potential ways to improve on these three areas. Our managing director documented the retrospective and preserved our takeaways in a brief report that we were able to access through our shared storage.

Project B Link

What worked well? What didn’t work well? Ways to improve
Client working session at our studio Research participant recruitment began too late. We relied on the client to recruit participants due to the sensitive nature of their relationship with users. • Emphasize the importance of clients beginning recruitment in pre-kickoff phone call.

• Draft recruitment email and send to client prior to the kickoff meeting.
Seamless transition between all project phases and disciplines. Technology assessment findings and user research findings were presented together, but themes felt disconnected. Technology and research teams work together throughout project to ensure alignment on research themes.

Project B’s retrospective identified that we had done a better job of identifying who would be involved from all disciplines from the start of the project. This led to a sense that the project unfolded seamlessly as we went from research to design and then development.

We also realized that we still fell short of completely resolving two of our previous issues:

  • We were relying on the client to recruit research participants due to the user types we needed access to. Our client had not begun the process of recruiting participants when the project kicked off. This led to a delay in starting the research according to the initial timeline.

We had attempted to address this issue by coming to the kickoff meeting prepared with some of the critical items that we knew our clients would need in order to recruit participants.

  • Technology assessment findings and user research findings were presented together, but the themes felt disconnected.

We improved on this issue between project A and project B, but we didn’t feel we had completely addressed it. The technology assessment findings were presented alongside the user research in the “Research findings” section, yet the themes remained distinct.

Working as a group, we came up with a list of potential ways to improve on these three areas. Our managing director documented the retrospective and preserved our takeaways in a brief report that we were able to access through our shared storage.

Project C Link

What worked well? What didn’t work well? Ways to improve
Client working session at our studio Staff vacations overlapped key meetings and dates. • Avoid overlap between team member vacations and key project dates.

• Identify potential substitutes ASAP for vacation coverage, preferably at the start of the project or as soon as vacation is known about.
Seamless transition between all project phases and disciplines. Create and implement guidelines for information shared during pre-kickoff calls, so that future projects benefit.
Pre-kickoff phone call alleviated issues of time with user recruitment. Continue pre-kickoff calls.
Research, design and technology themes presented seamlessly. Continue involving technology team in analysis of research from the beginning.

Project C was when our team really started to gel. This also marked six months of working together as a stable core team. We’d had time to learn how each other works and to support each other better. We were able to move both of the issues identified as “not working well” in project B to the “worked well” column in project C.

We had refined our process to the point that we were identifying the minor bumps that can arise over the course of a project as the ones we needed to focus on for improvement in future. We would not have been able to get to this point without conducting retrospectives after each project. Retrospectives enabled us to focus on what we were doing well in order to make sure we kept doing those things. We were also able to identify issues in need of improvement, with specific potential solutions to implement in the next project.

We did not achieve perfection by the end of our year-long experiment. But we did refine our process to the point that we had gotten beyond simply meeting our key performance indicators. We were actively looking for opportunities to implement better solutions; we were able to accomplish more, faster and with fewer resources; and we had developed positive healthy working relationships across the team.

Conclusion Link

You will find many potential benefits from conducting project retrospectives. You don’t need to invest a lot of time or money in them. There is no one-size-fits-all approach. I’ve given you some of the lessons I’ve learned as both a participant and a facilitator of retrospectives in digital design projects. Feel free to try what you want, and only use what works well for your team and situation.

However, we don’t always have the luxury of working in teams or having team retrospectives. I’ll focus on personal reflection in the second article of this two-part series. I’ll provide examples of written and verbal reflection that practitioners and students can apply to grow both personally and professionally.

Stay tuned!

References Link

  1. 1 https://www.smashingmagazine.com/2017/01/becoming-better-facilitator/
  2. 2 https://www.smashingmagazine.com/wp-content/uploads/2017/08/Gears-800w-opt.jpg
  3. 3 https://commons.wikimedia.org/wiki/File:Reduction_Gear.jpg
  4. 4 https://www.smashingmagazine.com/wp-content/uploads/2017/08/tools-large-opt.jpg
  5. 5 https://pixabay.com/p-593370/?no_redirect
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2017/08/tools-large-opt.jpg
  7. 7 http://scrumpedia.com/articles/a_five-step_approach_to_retrospectives
  8. 8 http://blog.lucidmeetings.com/blog/how-to-lead-a-successful-project-retrospective-meeting
  9. 9 https://www.amazon.com/Project-Retrospectives-Handbook-Team-Reviews/dp/0932633447/ref=sr_1_1?ie=UTF8&qid=1327347085&sr=8-1
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2017/08/Progress-large-opt.png
  11. 11 https://pixabay.com/en/graphic-progress-chart-1714230/
  12. 12 https://www.smashingmagazine.com/wp-content/uploads/2017/08/Progress-large-opt.png
  13. 13 https://www.idi.ntnu.no/~dingsoyr/ieee_software2002_birk_dingsoyr_stalhane_postmortem_never_leave_a_project_without_it.pdf
  14. 14 http://www.pinnacleprojects.com/index.php/project-retrospectives
  15. 15 http://misqe.org/ojs2/index.php/misqe/article/view/85</ee&gt

↑ Back to topTweet itShare on Facebook

A Guide To Virtual Reality For Web Developers

A Guide To Virtual Reality For Web Developers

Recently, there has been a proliferation of virtual reality (VR) web browsers and VR capabilities added to traditional browsers. In this article, we’ll look at the state of browsers in VR and the state of VR on the web via the WebVR APIs.

The State Of Virtual Reality And The Web Link

The web community has experimented with VR before, with VRML, but now WebVR takes a new approach to VR, one more suited to the modern web. We’ve accelerated 3D on the web since 2011 with the release of WebGL. Now the web can handle VR thanks to new web APIs that take advantage of VR hardware using WebGL.

These APIs enable WebGL content to be displayed in 3D with a VR headset. They also provide headset and controller tracking information to give the user presence in the virtual world.

WebVR was first developed in 2014 at Mozilla. In 2016, an earlier version of the standard was available for desktop Chrome, Firefox and Samsung’s virtual reality web browser: Samsung Internet for Gear VR.

These days, the standard is incredibly well supported on phones and desktop computers for almost all major headsets.

Mozilla Firefox Google Chrome Microsoft Edge Oculus Browser Samsung Internet Safari on iOS
HTC Vive Developer Edition Chromium Experimental build
Oculus Rift Developer Edition Chromium Experimental build
Windows Mixed Reality Windows 10 with Creators Update and Developer Mode enabled
Samsung Gear VR supported supported
Google Daydream Chrome for Android (with Origin Trial)
Cardboard Chrome for Android via polyfill1

WebVR support as of June 2017 (Source: Mozilla Blog2)

The WebVR standards are worked on in the open, and they represent a collaboration between Mozilla, Google, Samsung, Oculus, Microsoft and, recently, Apple.

This means that a single website that uses WebVR can make an immersive scene and deliver it to all major VR platforms at once, desktop and mobile!

The web’s ability to handle VR content allows one to easily share a VR experience in a URL and view it in the browser without the complicated app stores and long downloading times associated with native VR.

WebVR APIs demonstrated in Samsung Internet for Gear VR

Additional VR-Related Web APIs In Samsung Internet Link

These APIs are not part of the WebVR API but are useful for viewing immersive content on traditional websites in an immersive web browser without needing to use WebGL.

These APIs are being developed for Samsung Internet for Gear VR. We hope they will be picked up by other browsers and standardized.

Developing For Virtual Reality Link

Any developer can create content for VR nowadays. To get a better understanding of VR development, working a demo project can help. Read more →3

Panoramic Video Link

This involves the ability to play panoramic videos (monoscopic and stereoscopic) immersively by setting the type="dimension=360;" attribute on a video tag. These videos also get enhanced in Samsung Internet 5.0 by allowing the user to pan around within the video using their fingertips.

Possible values:

  • dimension=3d-lr: side-by-side 3D video
  • dimension=3d-tb: top-to-bottom 3D video
  • dimension=360: 360-degree video
  • dimension=360-lr: side-by-side 3D 360-degree video
  • dimension=360-tb: top-to-bottom 3D 360-degree video
  • dimension=180: 180-degree video
  • dimension=180-lr: side-by-side 3D 180-degree video
  • dimension=180-tb: top-to-bottom 3D 180-degree video
<video src="/360.webm" type="video/webm; dimension=360;"></video> 

Changing the Sky Link

Another API available in Samsung Internet for Gear VR is a JavaScript API for changing the background image of the VR web browser to one of the developer’s choosing.

Your traditional 2D website will still be visible, but the surroundings will be set to one that matches the environment of your website.

window.SamsungChangeSky({ sphere: 'http://site.com/blue-sky.jpg' }); 
Example of changing the Skybox with JavaScript in Samsung Internet for Gear VR

What Is WebVR? Link

WebVR is a set of cross-browser JavaScript APIs that provide a variety of VR-related utilities to place the user in an immersive environment generated using WebGL.

By providing side-by-side rendered 3D images, these APIs will handle all of the complexity involved in displaying an undistorted stereoscopic 3D image to the user.

I won’t go into the details of implementing the standard here because the standard is still changing. Most users will never need to deal with them directly, because WebGL tools and libraries often handle the WebVR APIs for you.

State Of The WebVR APIs Link

The current version of the API is known internally as version 1.1. Version 2.0 will change some of the method names and remove some unused methods. It will also add some additional functionality for some hardware and use cases which were not anticipated during the first iteration of the API.

The precise details of the APIs can be read on the Mozilla Developer Network4, and the standards are discussed on GitHub5. There is interest from within the WebVR community group6 and the W3C to move to a W3C working group once they are ready.

Essentially, the WebVR API provides the following:

  • Headset tracking allows the user to look around in the virtual environment. Frame interpolation is built in, so that it is always tracking the user’s head, even if you skip the occasional frame.
Pass-through camera, demonstrating head tracking in VR
  • “Six degrees of freedom” and “three degrees of freedom” controller support allows controllers like those of the HTC Vive and the Gear VR to work in virtual reality. It allows the user to use their hands to interact with the virtual environment.
  • Information is given about how the headset needs the 3D information rendered, such as the field of view and how to position the render for each eye on the canvas.
  • A new headset-specific requestAnimationFrame is synced to the refresh rate of the display in the headset.
  • There is a method of submitting the rendered frames to the headset in the form of a WebGL-enabled canvas element.
7
Diagram describing the loop for VR. The headset provides position and rotation data; the developer uses this data to render the scene from the user’s point of view, then sends the rendered data to the headset to be distorted and displayed to the user. (View large version8)

What Does It Mean To Build A WebVR Immersive Experience? Link

Surprisingly, building a virtual reality website raises many of the same problems as building a good mobile website or progressive web app.

Starting Fast Link

One of the biggest problems being tackled on the web today is network performance, which is important because:

  • user attention spans are shrinking,
  • networks are getting more congested,
  • websites are getting bigger than ever.

WebGL and WebVR websites are certainly no exception to size. They can get very large if one is not careful!

Right now, VR content has an edge over traditional content because it is novel and interesting enough that users will likely wait a bit longer to have a go. Still, getting your 3D experience started in under a few seconds is extremely important. Users are impatient and only getting more so.

Before your VR-capable website has loaded, it is just a 2D website and a promise of cool things to come.

My advice here is to not preload everything. Instead load just enough for the user to get started, then dynamically load and start caching the rest. This behavior should be familiar if you have read about Google’s PRPL pattern9.

Even just showing a blurred 360 skybox and some low-poly content, allowing the user to look around, will buy you precious seconds of engagement to bring in additional content and to bootstrap an engaging experience.

Showing something basic but fast is far better than losing the user because they’ve gotten bored waiting for a loading bar to complete.

But bear in mind, network operations can be CPU-intensive and block the main thread. This could give the user a bad experience if it happens a lot, so it is a fine line to walk.

Perhaps one or two very intensive assets need to be preloaded to avoid breaking the experience. However, if you have so many that it is taking a long time to start, then perhaps it’s worth thinking about finding a more performant alternative.

Making good use of a service worker and the Cache API10 to cache static assets for fast return visits is a great way to keep users coming back for more.

Progressive Enhancement Link

The two main platforms for VR are polar opposites: high-end desktop computers with advanced controllers, and mid- to high-level mobile phones, which might have only a single rotation-tracked controller or no controller at all!

11
A photo of an HTC Vive with a position-tracking controller, Samsung Gear VR, Google Daydream and a pile of Google Cardboards in the back. (View large version12)

This presents us with two challenges:

  • maintaining a consistent frame rate across platforms with wildly differing performance capabilities,
  • presenting a user-friendly experience across VR devices with a wide range of inputs.

Phones have by far the largest reach due to the popularity of Gear VR and Daydream and the cheap price and high availability of the Google Cardboard headsets.

Below, I have described some typical controller configurations. You don’t need to support them all, but handling the “no controller” situation as a baseline and also supporting another controller option if applicable will allow everyone to experience something. Supporting all controller configurations would be nice, but in my opinion is not a reasonable expectation.

Some libraries, such as Universal Controls from A-Frame Extras13, try to make the best out of whatever is available.

14
Web-compatible controllers with increasing levels of immersion. From left to right: Gaze-Based Tracking, Traditional Gaming Controllers, Rotation-Tracked Controllers, Position- and Rotation-Tracked Controllers, Full Gesture Recognition. (Eye illustration: Wikimedia Commons) (View large version15)
Interaction mechanism How it increases engagement Hardware and support
Gaze-based interaction Look at something to use it. (Most users will require this.) Cardboard-like headsets; users with limited mobility for controllers
Traditional controllers (e.g. Xbox, Playstation) Works with widely supported Gamepad API16 Can be used anywhere the API is supported on desktop and mobile (needs latest Safari)
Rotation-Tracked Controllers Allows the user to gesture like a laser pointer Can be used in Daydream devices and Gear VR to similar effect to the fully tracked controllers
Position- and Rotation-Tracked Controllers Fully tracked hands; allows great immersion and interaction. Most high-end VR has these, such as HTC Vive and Occulus Touch
Hand Tracking Allows user’s hands to interact with the scene; great immersion Built into Hololens, can be added by using the Leap Motion tracker

Asymmetric Play Link

As with progressive enhancement on the web, supporting all levels of hardware does not mean you need to deliver the same experience to all.

A user with two fully tracked hands in the virtual world will have a much more engaging experience and should not be limited by being delivered the same experience as someone with no controller.

For example, a VR app in which you produce VR artwork could use tracked controllers to produce art on high-powered machines; on mobile, a user would be able to view this art in VR but be unable to edit it.

Another example would be a networked VR multiplayer game in which players use tracked controllers to play the game; a mobile viewer could watch it and use gazed-based interactions to choose different points of view.

Test as You Develop Link

Like modern web design, the key is to design mobile-first. As you build your scene, regularly test it on real mid-level smartphones with no controllers to ensure it will work for the majority of your users.

WebVR allows you to target both platforms at once. However, delivering the same content to both could result in mobile devices struggling or desktops not being used to their full potential.

There is no problem having very well-performing graphics. A stylized low-poly appearance can look fantastic and render very quickly.

To upgrade graphics, one solution is to provide options for graphical quality before the user starts using WebVR. If the user requests high quality, then start downloading the large or difficult-to-render graphics.

Something more difficult but more seamless would be to start on the lowest graphical setting and detect how well the device is performing using commands such as requestIdleCallback or measure how long the rendering takes. If the device is running well, then maybe increase the graphics settings. If frames start getting skipped, then dynamically reduce them.

When you are upgrading your scene, you might decide to do a few things:

  • increase draw distance,
  • download and use high-resolution models or textures,
  • use more complex shaders.

This will ensure that users on mobile and desktop get the best possible experience. For most use cases, though, it is probably fine if desktop users get the mobile experience, because you can guarantee it will maintain a great frame rate on the desktop if it also does on mobile.

After all, there is more to a great scene than visual fidelity. Highly stylized games such as Team Fortress 2 still look great today, whereas “realistic” games from the same era have not aged so well.

A great scene should have a well-designed graphical style, with bold colors and strong silhouettes. This will help low-power and low-resolution devices look good, but will also still look great on desktop devices, needing only a bit of extra polish.

In VR, bear in mind that most users will have the equivalent of poor eyesight. So, minimize text or anything that will cause the user to strain to see something.

What Does the Web Bring to VR? Link

The web is trying to solve some of the problems currently facing VR.

One of the biggest issues is that the user has to make a big commitment for a one-off experience that they might not want to come back to.

In native mobile and desktop VR, one has to download the app from an app store such as the Oculus store on Gear VR or from Steam for the HTC Vive or Oculus Rift.

This app store pattern lends itself well to expensive video games, in which users have already invested some money and so are going to return again and again. But for a one-off experience such as shopping, viewing a movie or trying a new social platform, this can be a high barrier to entry.

Users tend to be put off by the idea of having apps lying around on their device, taking up space or using up a large amount of their data allowance to download — especially users whose mobile devices have limited disk space or network data caps.

On the web, once the user leaves a page, they don’t have to worry about content hanging around, because the browser will clean it up if space is needed. If space is available, the developer can cache content on the device for when the user returns, letting the developer have their cake and eat it, too.

Of course, this requires the developer to make VR websites that are not stored as a single giant bundle; otherwise, the gains the web can provide will have been lost.

By delivering VR assets dynamically and separately like those of a web page, you can take advantage of all of the smart caching that the web can provide from the CDN, all the way down to the HTTP cache and the service worker’s Cache API on the device.

Furthermore, the user can jump right into your VR experience with very little waiting.

A highly optimized WebVR website should render the first frame within a single second of the user landing on the website — totally cutting out any lengthy initial downloads or app stores, and massively increasing engagement.

An experience can be shared with nothing but a URL, which can be distributed by social media or email or even written on a wall or displayed on a TV, making it much more likely that your VR content will go viral due to its low barrier to entry.

Making the Most Out of the Quick Web Link

One feature that many WebVR websites have is that, before entering VR, the user can view and interact with the scene on their 2D display. The view will often rotate with the phone, giving the appearance of a magical window into a virtual space.

This magical window is a powerful pattern. It gives the user a preview of the VR scene without the need for a VR headset. This is great for when they don’t have their VR gear on hand or are on public transportation and don’t want to wear VR equipment in public.

Once the user has gotten a taste, they will be encouraged to bookmark your website to try it in VR at a time more suitable for them.

The Web Has High-Level Interfaces to Low-Level APIs, Bringing Advanced Technology to Any Developer Link

Many web APIs you may have heard of or used have become massively more relevant in a VR context:

  • WebSockets

    These are used to stream text and binary data to a server in real time. For VR, they can be used to sync hundreds of users in real time to enjoy a shared experienced and to view avatars representing each other. I recently produced an open-source demo in which I did this live for over 150 users at a conference17.
  • WebRTC

    To expand upon shared VR, one can also use WebRTC to maintain peer-to-peer connections for binary data and video and audio streaming. This can be used to allow two avatars to voice chat or to sync the position and posture of a VR avatar without going through a central server. This can be used to connect six to eight users at a time.
  • WebAudio

    WebAudio18 is one of the most surprisingly powerful APIs. The browser contains everything you need for audio manipulation and analysis. One can even use a panner node for 3D spatial audio in VR. For producing virtual environments that have an immersive feel, WebAudio is more important than ever.
  • SpeechRecognition

    Newer browsers contain a built-in speech recognition engine! This is useful for giving commands and entering text when a real or virtual keyboard is difficult or unwieldy. Samsung has built a great example for VR19.

What Effect Might VR Have On The Web In The Long Term? Link

VR has already had an effect on the web platform; the WebVR APIs have been implemented across multiple platforms; and there are discussions about creating a WebVR working group within the W3C.

VR is already going mainstream, and with augmented-reality and mixed-reality devices starting to enter the consumer realm, it is important that the web be ready to take advantage of the new platforms.

WebVR as we know it today relies entirely on WebGL. Optimizing for WebGL will mean that browser vendors will have to look at taking advantage of hardware optimizations to increase rendering speed towards that of a natively compiled app. Speed is important, because dropping frames in VR can have disastrous effects, even to the point of making the user ill!

WebGL 2 will soon be reaching stable browsers. Version 2 brings WebGL closer to the OpenGL ES 3.0 specification. Greater visual fidelity and faster ways to do advanced graphics will make VR truly an incredible visual experience.

WebAudio might be required to produce more accurate 3D audio transformations, known as head-related transfer functions, to better reproduce the high-quality 3D audio required by big-budget productions. Accurate 3D audio will be essential to delivering high-quality immersive video content such as 360-degree movies and immersive audio experiences.

Scripting on the web would benefit from significant performance improvements as well. A number of JavaScript APIs are in the works that can be used to increase performance on the web.

JavaScript itself can be optimized and precompiled. Another option is to compile other languages to WebAssembly (WASM). This can speed things up across the board, providing a bundle that is smaller to download and faster to parse and execute. If used wisely and modularly, WASM could be used to make the core rendering engine of a WebVR experience, which we could still interact with using JavaScript as we do today.

The browser can make use of web workers to enable calculations that do not block the main thread. This is good because the main thread is primarily used for rendering. Web workers are useful for manipulating large amounts of data with CPU-intensive calculations such as physics engines. By isolating the calculations from the main thread in this way, they are less likely to trigger frame drops.

Unfortunately, some cost is associated with sending data to and from web workers to use them in the main thread. This is alleviated partially by transferable objects. Transferable objects such as ArrayBuffers allow you to change the owner of the object, but handling the transferring of this object can be difficult and error-prone if a mistake is made. (I’ve written about using ArrayBuffers on the web20.)

A new API called SharedArrayBuffer will allow multiple workers to share the same ArrayBuffer, which is useful for this case.

On the topic of workers, part of the issue is that, right now, the thread that renders the web page also needs to be used to render the WebGL scene. So, any side effects of other code that you run on the main thread, such as garbage collection or CPU-bound functions, could cause frames to be dropped.

OffscreenCanvas enables rendering to be performed in a web worker. This will help the very important and sensitive rendering loop to be isolated from the other threads.

The other important rendering use case is prerecorded 2D and 3D video. These can be used as textures in WebGL. But they lack fine-grained control. Just as we have an audio element and an AudioContext in JavaScript, we will need to add a videoContext to enable performant video manipulation to assist with playing 360-degree videos in 3D.

An area where VR currently lies at odds with the web as a whole is the rendering of documents. Displaying documents is the core functionality of the web platform, but displaying a document in WebGL is nigh impossible without some very slow, very clever rerendering.

It would be great to bring them together by having the browser expose rendered DOM content to WebGL. This would enable us to take advantage of the web’s power for 2D interfaces, but it could potentially be a security and privacy risk!

Another Path Link

WebGL-based VR doesn’t necessarily have to be the future of VR on the web. Having to perform even the simplest use case for WebVR in WebGL seems shortsighted at best and potentially fatal for VR on the web in the long run.

Part of the strength of the web is that HTML is a declarative language. Browsers can interpret the language according to the platform. You won’t see the exact same website on your desktop computer as you would on your phone or TV. VR is yet another platform in the variety of media to experience the web.

By being declarative, like HTML or CSS, VR on the web could automatically handle rendering to balance rendering speed and visual fidelity. A high-end computer could use advanced shaders and detailed models; a low-power mobile phone could automatically use simple shading and low-poly models — much like the way the picture element can download images that are of the correct resolution and then crop for the given device.

HTML could be extended to include some common VR use cases, such as playing 360-degree and 3D videos and images, displaying 3D models, and moving bits of a web page outside of the 2D viewport into 3D space.

Samsung has started to look at some of these use cases in the web browser, Samsung Internet for Gear VR.

It has built-in support for 3D video using the video element. Displaying a side-by-side 3D, 360-degree video requires just an HTML tag:

<video controls src="360video.mp4" type="video/mp4; dimension=360-lr;"> 

The Middle Path Link

Of course, these needn’t be mutually exclusive. The web can partially handle and optimize for simple VR use cases, while also providing optimizations for building immersive VR from scratch with WebGL.

The Extensible Web manifesto hinges on the idea that the web does not have to sacrifice extensibility for ease of use, that the community can use the low-level tools provided to extend the web platform using libraries.

VR is one case where this vision seems very relevant. We already have the low-level tools of WebGL and the WebVR APIs.

The A-Frame21 library provides custom HTML elements to build WebGL-based 3D scenes. A-Frame is usable on its own or with popular frameworks such as React and Angular.

A-Frame enables any web developer with HTML experience to describe VR-ready 3D scenes and to control them using familiar JavaScript. Even tools such as jQuery, Angular and React can be used to change a scene because, at the end of the day, it is still just HTML.

Conclusion Link

The web has the power to bring virtual reality to the world, to every consumer, to every developer.

It is still early days for VR on the web, but now is the time to get building, to see what works and what doesn’t.

The web can show that VR is for more than video games. VR can be used to enhance everything we currently do on the web and even enable new interactions only possible in an immersive medium.

As developers, we can start building VR experiences on the web today. By getting involved and giving feedback about the standards process, we can ensure that VR on the web becomes a robust standard, paving the way for future developers to build on.

Even if you don’t think VR is mature yet, with mixed-reality and augmented-reality devices around the corner, what we build today will still be relevant then. The interface patterns we build for VR apply to all immersive media. Don’t get left behind.

Together, we will build the web of tomorrow.

(rb, vf, yk, al, il)

Footnotes Link

  1. 1 https://github.com/googlevr/webvr-polyfill/
  2. 2 https://blog.mozilla.org/press/2017/06/mozilla-brings-virtual-reality-to-all-firefox-users/
  3. 3 https://www.smashingmagazine.com/2016/09/developing-for-virtual-reality-what-we-learned/
  4. 4 https://developer.mozilla.org/en-US/docs/Web/API/WebVR_API
  5. 5 https://w3c.github.io/webvr/
  6. 6 https://www.w3.org/community/webvr/
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2017/08/image4-large-opt.png
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2017/08/image4-large-opt.png
  9. 9 https://developers.google.com/web/fundamentals/performance/prpl-pattern/
  10. 10 https://medium.com/samsung-internet-dev/a-beginners-guide-to-service-workers-f76abf1960f6
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2017/08/image3-large-opt.jpg
  12. 12 https://www.smashingmagazine.com/wp-content/uploads/2017/08/image3-large-opt.jpg
  13. 13 https://github.com/donmccurdy/aframe-extras
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2017/08/image1-large-opt.png
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2017/08/image1-large-opt.png
  16. 16 https://medium.com/samsung-internet-dev/the-gamepad-reloaded-5ba866770003#.8tzhs8qz2
  17. 17 https://medium.com/samsung-internet-dev/wow-that-was-some-night-in-vr-ba091be38794
  18. 18 https://medium.com/samsung-internet-dev/web-audio-on-different-platforms-67fc9ffc2c4e
  19. 19 https://samsunginter.net/word-drop/
  20. 20 https://medium.com/samsung-internet-dev/being-fast-and-light-using-binary-data-to-optimise-libraries-on-the-client-and-the-server-5709f06ef105
  21. 21 https://aframe.io

↑ Back to topTweet itShare on Facebook

Content Marketing For Millennials – Stop Interrupting and Start Entertaining!

Guy Sheetrit
 Millennials are people who are born between 1977 and 2000. They are a set of audience who are early adopters of technology. They make up 21% of the US population which means that they have the direct buying power of over a trillion dollars. Moreover, they have a huge influence on the older generations and are known to be loyal customers.

As a marketer, it is extremely crucial to target [easyazon_link identifier=”1433670038″ locale=”US” tag=”americanfid09-20″]millennials[/easyazon_link] in order to tap into the power of direct purchase decisions and improve sales. As Skyler Huff points out in her article published on Millennial marketing, content falls under one of the below four quadrants:

  1. Branded Content
  2. Rooted Content
  3. Social Care Content
  4. Social Satellite Content

content-mix.png

(Image credit millennialmarketing)

Rooted content is what the brands actually want to convey to their audiences. This content is planned and promotional in nature. Editorial authority is important before you start publishing such content, as aggressive rooted content publishing might keep the millennials away.

Social care content is based on the one-on-one interaction that the brands have with their target audiences. Content pieces that are a part of a social customer care process or a problem-solving piece shared to build brand loyalty fall under this category. Once again, editorial authority is needed before any message is posted on behalf of your business in the social channels. Remember, a wrong message can be extremely harmful for the reputation as negativity travels much faster across social channels as compared to positivity.

Branded content also falls into the planned category as writers are fully prepared before they publish content on the brand media channels. An editorial review should be a part of this process and value should be given when creating content which solves a need of the target audience on a large scale.

Social satellite content often known as the brand newsroom refers to the group of content writers who constantly keep a watch across brand mentions on social media and prepare content based on the received reactions. The goal here is to proactively manage brand promotion.

Do Not Interrupt! Help Them, Engage Them and Entertain Them

Traditional advertising mediums like television, radio, newspapers, hoardings, etc. are a form of push advertising. Such forms of push advertising often cause irritation in the minds of the millennials and do not inspire true brand love.

Use content as an opportunity to reach the consumers when they need you. Google offers some great insights reaching the customers during the crucial micro moments.

micromoments.png

(Image displaying some of the crucial travel moments that businesses need to get right. Image credit: think with Google)

  • Understand the needs of the millennials. Obtain a data driven view and note the patterns of the individual journeys. Smart marketing strategy recognizes the uniqueness of each customer and engages them to take actions.
  • Create user personas based on their needs, goals and observed behavior patterns. Having personas will allow you to segment contacts and assign them to workflows. You can use tools like HubSpot to create user personas.
  • Create new opportunities for your brand to get in front of the customers. However, do not force feed a brand message. Only deliver when they need it.
  • Millennials like content that is entertaining, Visual, Brief, Personal, Original and Educational/Informative. Brands have even started to leverage the power of augmented reality to engage the audiences.
  • Making a connection with the Millennials is the most crucial factor because once a connection is made, then they can prove to be the most loyal customers on the planet today.

Create Agility in Your Content Marketing Efforts

If you expect your brand to receive a positive response from your content marketing efforts, then it is important to create agile content. Think about creating content pieces based on genuine user feedback and real customer data instead of choosing a content topic randomly. This is what Agile content is all about. Agile content pieces are revised regularly depending on user feedback thereby increasing its value and lifetime and reducing the risk of failure. An example would be to create blog posts based on the questions that your customers are regularly asking.

  • Agile content helps to leverage the power of real time news and events that have the power to engage people in conversations.
  • The content strategy adopted should be actionable, scalable and achievable.
  • Consumer, product and social data are combined to understand the audience behavior to produce agile content.
  • The major goal should be creating content pieces that the Millennials would be willing to share across their social networks.

Here Are 4 Ways You Can Create Agile Content:

Step 1: Read well! A good writer should be a good reader first. Keep an eye on the latest industry trends and focus on fresh and fast moving news. You can try creating a content feed using Feedly or Scoop.it that collects news and information from several places together. This saves time as it eliminates the need to visit several sites on a daily basis to compile information. You need to visit your feed as often as possible because you never know when a new story will hit and go viral.

Step 2: Ask questions and gather data. Make use of the site search feature under Google Analytics and look out for the FAQ’s left by the users in the chatbot database to collect as much data as possible. Moreover, create survey forms and find out what problems your customers are facing so that you can create content based on the real problems faced by the users, instead of choosing random topics that might have worked well for any other business. Remember every business is unique, and you need to create content that satisfies the needs of your current and potential customers.

Step 3: Build a content calendar. No mission is successful without proper planning. Content marketing is an ongoing activity that needs full planning that starts with topic preparation. Creating a content calendar always helps because it allows your organization to produce constant and frequent content.

Step 4: Repurpose your content. Take help of all those creative brains who are working in your content writing team to repurpose your content. This will open new channels of obtaining traffic and solidify your branding efforts without having to spend extra time or money. You can convert a popular webinar into a series of blog posts, or you can turn a blog post into an infographic. You can try such content changes to constantly publish new and improved varieties of articles that segmented users will love to read and share.

Capitalize on the Power of FOMO

FOMO stands for ‘Fear of Missing Out’ and the millennial generation, especially the women, do not want to miss out on the opportunities that your content pieces can generate.

jealousy-1.jpg

(Image credit: Psy Blog)

Social media was able to garner success only because a large number of the social user base is millennials. They do not want to miss out on important news, events or personal invites and this is the reason they regularly remain logged into their social accounts; to stay connected and remain updated. They love to share things that are popular and can generate more engagement, and they love to comment on stories where they can speak up their mind.

Content created for the purpose of ‘fear of missing out’ surely has better chances of performing well in social media, and in that process, a lot of social shares and comments are generated.

Here are some ways through which you can leverage the power of FOMO in your content marketing strategy:

  • Create urgency because it has the power to consistently entice customers to spend more money.
  • Your content should motivate the customers to act, or they might miss out.
  • Make use of visuals like an automatic timer or a series of reminders to keep the trigger of FOMO constant.
  • Create user stories of your past customers and share them across social media. People are more keen to make a reactionary purchase because they witness your past customers experience across social media. I call it “personal experience FOMO or the testimonial FOMO”. You can try it too as it works really well.
  • Make your content pieces exclusive like member only. People love exclusive things, and when they feel they are missing out exclusive stuff because they are not part of that elite club, they will quickly subscribe to it.
  • Invite your customers to try out things. Generate content invitations where the scope of personal interaction is enhanced. A music festival or a party is a great way to fulfill the needs of your target audiences along with delivering your brand message and boosting your brand awareness.
  • Create interactive content pieces that allow readers to engage and participate with the content to have the full experience. You can use web elements like checkbox, finger swipes, object destructions, etc. to improve the overall engagement. The addition of interactive items like these not only increase the time spent by the reader on your site, but it also helps to indirectly improve the search engine rankings of your site. Google does calculate the time on page spent by the visitor before ranking any pages, and you can fully capitalize on this ranking factor by using interactive content pieces on your website.

Here are some examples of interactive content:

Stay Mobile! Create Pages That Are Optimized for Mobile

Preparing content and publishing it on a desktop friendly site is not okay! Millennials spend a ton of time on their mobile devices, so producing content that is not readable on mobile is similar to producing no content at all. Stay mobile and create landing pages that are easy to read on mobile.

Here are some steps to have a mobile optimized content marketing strategy: 

  • Prepare content that is easy for the eyes of the mobile audience. Write short paragraphs and use proper bullet points with minimal distraction so that it becomes easier for the user to scan the content.
  • Prepare long form content as it adds more value to the readers. Ensure the content is rendered seamlessly across a variety of devices.
  • Take the mobile friendly test on your site and check if your page is mobile friendly.
  • Understand and track the habits of your mobile audiences like what activities they do on your site when they are browsing it using their mobile phones.
  • Mobile headlines are relevant and shorter so ensure the headline fits into the screen of the standard mobile device.
  • Make use of big fonts as they are easier to read and get to the point fast. People don’t like to wait when they are reading using a mobile device.
  • Check the Fleisch-Kincaid readability score and ensure that your content falls under the 8th standard level of English readability.
  • A bonus strategy is connecting with influencers. Millennials are largely connected to both macro and micro influencers. Rather than working on the traditional outbound advertisement model, make use of the inbound influencer marketing to convert your target audiences into loyal brand followers.

Remember Authenticity

Millennials value content that is authentic. Your potential audience should learn from the content you provide. So, never try to hard sell. Instead, focus on speaking the millennial language when delivering the content. Information that resembles those coming directly from peers is trusted more and appear to be more authentic in the eyes of the millennials.

It would be a great idea to ask a millennial to contribute to an existing content piece in some way or the other. Empower your audiences with the power of interaction and the engagement levels are bound to increase.

Marketing to millennials is incredibly intuitive. Offer authentic experiences that can engage the readers. Acquire some influencers to share your story, and the millennials will follow. Have you used any specific strategy to target millennials?

Guy Sheetrit
Founder and CEO of Over The Top SEO. He holds broad expertise in the areas of SEO, Social Media, Digital Marketing, B2B, B2C Brand Development and online lead generation.

Comments

Goodbye Summer, Hello Autumn! Inspiring Wallpapers To Start September Off Right (2017 Edition)

Goodbye Summer, Hello Autumn! Inspiring Wallpapers To Start September Off Right (2017 Edition)

As designers we usually turn to different sources of inspiration, and, well, sometimes the best inspiration lies right in front of us. With that in mind, we embarked on a special creativity mission nine years ago: to provide you with inspiring and unique desktop wallpapers1 every month. Wallpapers that are a bit more distinctive as the usual crowd and that are bound to fuel your ideas.

We are very thankful to all artists and designers who have contributed and are still diligently contributing to this mission, who challenge their artistic abilities each month anew to keep the steady stream of wallpapers flowing. This post features their artwork for September 2017. All wallpapers come in two versions — with and without a calendar — and can be downloaded for free. Time to freshen up your desktop!

Please note that:

  • All images can be clicked on and lead to the preview of the wallpaper,
  • You can feature your work in our magazine2 by taking part in our Desktop Wallpaper Calendars series. We are regularly looking for creative designers and artists to be featured on Smashing Magazine. Are you one of them?

Summer Ending

“As summer comes to an end, all the creatures pull back to their hiding places, searching for warmth within themselves and dreaming of neverending adventures under the tinted sky of closing dog days.” — Designed by Ana Masnikosa3 from Belgrade, Serbia.

4

Summer Is Leaving

“It is inevitable. Summer is leaving silently. Let us think of ways to make the most of what is left of the beloved season.” — Designed by Bootstrap Dashboards46 from India.

Summer Is Leaving47

Talk Like A Pirate Day

“This calendar was inspired by International Talk Like a Pirate Day (September 19) — one of the many obscure and quirky days we celebrate in New Orleans. Our fair, colorfully corrupt city has entertained its share of outlaws over the years, but none as infamous as the pirate Jean Lafitte, a Frenchman who terrorized sailors and ships in the Gulf of Mexico and distributed his booty from a warehouse in New Orleans in the early 1800s. This calendar is a playful tribute to all of the misfits, outcasts and swashbucklers who call New Orleans home.” — Designed by Sonnie Sulak73 from New Orleans, LA.

Talk Like A Pirate Day74

Maryland Pride

“As summer comes to a close, so does the end of blue crab season in Maryland. Blue crabs have been a regional delicacy since the 1700s and have become Maryland’s most valuable fishing industry, adding millions of dollars to the Maryland economy each year. With more than 455 million blue crabs swimming in the Chesapeake Bay, these tasty critters can be prepared in a variety of ways and have become a summer staple in many homes and restaurants across the state. The blue crab has contributed so much to the state’s regional culture and economy, in 1989 it was named the State Crustacean, cementing its importance in Maryland history.” — Designed by The Hannon Group108 from Washington DC.

Maryland Pride109

Still In Vacation Mood

“It’s officially the end of the summer and I’m still in vacation mood, dreaming about all the amazing places I’ve seen. This illustration is inspired by a small town in France, on the Atlantic coast, right by the beach.” — Designed by Miruna Sfia135 from Romania.

Still In Vacation Mood136

Autumn Rains

“This autumn, we expect to see a lot of rainy days and blues, so we wanted to change the paradigm and wish a warm welcome to the new season. After all, if you come to think of it: rain is not so bad if you have an umbrella and a raincoat. Come autumn, we welcome you!” — Designed by PopArt Studio178 from Serbia.

Autumn Rains179

Funny Cats

“Cats are beautiful animals. They’re quiet, clean and warm. They’re funny and can become an endless source of love and entertainment. Here for the cats!” — Designed by UrbanUI223 from India.

Funny Cats224

September Explorer

“After leading a photographic tour through Northwestern Argentina and while discovering its magical ravines and rock formations, I decided to make a wallpaper inspired by the Devil’s throat formation. Use human for scale!” — Designed by Diego Waisman248 from the United States.

September Explorer249

Geometric Autumn

“I designed this wallpaper to remind everyone that autumn is here and they are still reading the best design website, Smashing Magazine” — Designed by Advanced Web Ranking271 from Romania.

Geometric Autumn272

Fall Is Here

“Since it is already September, the leaves are falling and the days are getting shorter and shorter. It is also getting colder so therefore this lovely wallpaper to warm you up.” — Designed by Melissa Bogemans296 from Belgium.

Fall Is Here297

Umbrella

“Adapt to the seasons of life, change and transformation” — Designed by Pluscharts337 from India.

Umbrella338

Sweet Time Under The Banana Tree

“I was visiting a beautiful garden, taking pictures of details within the plants. The colors of this leaf were so brilliant with the sun behind.” — Designed by Philippe Brouard362 from France.

Sweet Time Under The Banana Tree363

Geometric Leaf

“Autumn is coming, so I decided to try out a geometric leaf design this month!” — Designed by James Mitchell389 from the United Kingdom.

Geometric Leaf390

September Festivals In India

“India is a world in itself, with the richness of its heritage and culture. The beautiful festivals are a means of removing all the negativity in our minds and refreshing our souls from within. The festivals are filled with bright colors and uplifting music which rejuvenates our senses and ignites our soul with confluence of multiple energies drawn from several auspicious moments of the past. These festivals are a delight for the creative minds due to their vibrant concepts, energy, colors and art blended in to beautiful form. Every festival has a special significance and aura, I would like to communicate it to the world through this wallpaper.” — Designed by Shyam Pawar410 from India.

September Festivals In India411

Dreams Don’t Work Unless You Do

Designed by Metrovista437 from Orlando, FL.

Dreams Don’t Work Unless You Do438

The World Is Yours

“Travel and change of place adds new vigor to the mind. Take a break, forget your worries and travel. Create stories of new places and adventures to tell. Meet new people, learn new languages, taste new cuisines, experience the beauty of different culture and traditions, and lose your spirit to the soul of the universe which lies in traveling. On World Tourism Day, start a new journey of your life, rejuvenate and breathe and live happily while traveling across roads you have never taken before.” — Designed by Acodez IT Solutions464 from India.

The World Is Yours465

When Music Reckons Your Soul

“A touch on guitar’s strings, soft caresses on the piano’s pins, resurrecting waves of joy, of love from the heart within. Come, let’s get immersed in the sound of music…” — Designed by IPIX Technologies507 from India.

When Music Reckons Your Soul508

Dry The Leaves

Designed by StarAdmin Bootstrap Admin Dashboard550 from India.

Dry The Leaves551

Happy Birthday Roald!

“September the 13th is the birthday of legendary author, Roald Dahl. If you haven’t heard of him, where have you been? I have even included an inspirational quote from the Charlie and the Chocolate Factory book.” — Designed by Safia Begum577 from the United Kingdom.

Happy Birthday Roald!578

Four Friends

Designed by Doud – Elise Vanoorbeek596 from Belgium.

Four Friends597

#Spring

“Such a lovely time of the year in Melbourne!” — Designed by Tazi619 from Australia.

#Spring620

World Alzheimer’s Day

“We remember their love when they can no longer remember.” — Designed by Color Mean Creative Studio644 from Dubai.

World Alzheimer’s Day645

Join In Next Month! Link

Please note that we respect and carefully consider the ideas and motivation behind each and every artist’s work. This is why we give all artists the full freedom to explore their creativity and express emotions and experience throughout their works. This is also why the themes of the wallpapers weren’t anyhow influenced by us, but rather designed from scratch by the artists themselves.

A big thank you to all designers for their participation. Join in next month689!

What’s Your Favorite? Link

What’s your favorite theme or wallpaper for this month? Please let us know in the comment section below.

Footnotes Link

  1. 1 https://www.smashingmagazine.com/tag/wallpapers/
  2. 2 https://www.smashingmagazine.com/desktop-wallpaper-calendars-join-in/
  3. 3 https://www.creitive.com/
  4. 4 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/sept-17-summer-ending-full.png
  5. 5 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/sept-17-summer-ending-preview.png
  6. 6 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-320×480.png
  7. 7 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-640×480.png
  8. 8 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-800×480.png
  9. 9 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-800×600.png
  10. 10 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-1024×768.png
  11. 11 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-1024×1024.png
  12. 12 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-1152×864.png
  13. 13 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-1280×720.png
  14. 14 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-1280×800.png
  15. 15 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-1280×960.png
  16. 16 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-1280×1024.png
  17. 17 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-1400×1050.png
  18. 18 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-1440×900.png
  19. 19 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-1600×1200.png
  20. 20 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-1680×1050.png
  21. 21 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-1680×1200.png
  22. 22 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-1920×1080.png
  23. 23 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-1920×1200.png
  24. 24 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-1920×1440.png
  25. 25 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/cal/sept-17-summer-ending-cal-2560×1440.png
  26. 26 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-320×480.png
  27. 27 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-640×480.png
  28. 28 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-800×480.png
  29. 29 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-800×600.png
  30. 30 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-1024×768.png
  31. 31 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-1024×1024.png
  32. 32 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-1152×864.png
  33. 33 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-1280×720.png
  34. 34 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-1280×800.png
  35. 35 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-1280×960.png
  36. 36 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-1280×1024.png
  37. 37 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-1400×1050.png
  38. 38 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-1440×900.png
  39. 39 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-1600×1200.png
  40. 40 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-1680×1050.png
  41. 41 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-1680×1200.png
  42. 42 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-1920×1080.png
  43. 43 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-1920×1200.png
  44. 44 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-1920×1440.png
  45. 45 http://files.smashingmagazine.com/wallpapers/sept-17/summer-ending/nocal/sept-17-summer-ending-nocal-2560×1440.png
  46. 46 https://www.bootstrapdash.com
  47. 47 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/sept-17-summer-is-leaving-full.png
  48. 48 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/sept-17-summer-is-leaving-preview.png
  49. 49 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/cal/sept-17-summer-is-leaving-cal-360×640.png
  50. 50 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/cal/sept-17-summer-is-leaving-cal-1024×768.png
  51. 51 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/cal/sept-17-summer-is-leaving-cal-1280×720.png
  52. 52 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/cal/sept-17-summer-is-leaving-cal-1280×800.png
  53. 53 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/cal/sept-17-summer-is-leaving-cal-1280×960.png
  54. 54 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/cal/sept-17-summer-is-leaving-cal-1280×1024.png
  55. 55 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/cal/sept-17-summer-is-leaving-cal-1366×768.png
  56. 56 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/cal/sept-17-summer-is-leaving-cal-1400×1050.png
  57. 57 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/cal/sept-17-summer-is-leaving-cal-1440×900.png
  58. 58 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/cal/sept-17-summer-is-leaving-cal-1600×900.png
  59. 59 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/cal/sept-17-summer-is-leaving-cal-1680×1200.png
  60. 60 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/cal/sept-17-summer-is-leaving-cal-1920×1080.png
  61. 61 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/nocal/sept-17-summer-is-leaving-nocal-360×640.png
  62. 62 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/nocal/sept-17-summer-is-leaving-nocal-1024×768.png
  63. 63 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/nocal/sept-17-summer-is-leaving-nocal-1280×720.png
  64. 64 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/nocal/sept-17-summer-is-leaving-nocal-1280×800.png
  65. 65 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/nocal/sept-17-summer-is-leaving-nocal-1280×960.png
  66. 66 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/nocal/sept-17-summer-is-leaving-nocal-1280×1024.png
  67. 67 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/nocal/sept-17-summer-is-leaving-nocal-1366×768.png
  68. 68 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/nocal/sept-17-summer-is-leaving-nocal-1400×1050.png
  69. 69 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/nocal/sept-17-summer-is-leaving-nocal-1440×900.png
  70. 70 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/nocal/sept-17-summer-is-leaving-nocal-1600×900.png
  71. 71 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/nocal/sept-17-summer-is-leaving-nocal-1680×1200.png
  72. 72 http://files.smashingmagazine.com/wallpapers/sept-17/summer-is-leaving/nocal/sept-17-summer-is-leaving-nocal-1920×1080.png
  73. 73 https://www.reignmade.co/
  74. 74 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/sept-17-talk-like-a-pirate-day-full.jpg
  75. 75 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/sept-17-talk-like-a-pirate-day-preview.jpg
  76. 76 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/cal/sept-17-talk-like-a-pirate-day-cal-640×480.jpg
  77. 77 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/cal/sept-17-talk-like-a-pirate-day-cal-800×480.jpg
  78. 78 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/cal/sept-17-talk-like-a-pirate-day-cal-800×600.jpg
  79. 79 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/cal/sept-17-talk-like-a-pirate-day-cal-1024×768.jpg
  80. 80 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/cal/sept-17-talk-like-a-pirate-day-cal-1280×720.jpg
  81. 81 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/cal/sept-17-talk-like-a-pirate-day-cal-1280×800.jpg
  82. 82 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/cal/sept-17-talk-like-a-pirate-day-cal-1280×960.jpg
  83. 83 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/cal/sept-17-talk-like-a-pirate-day-cal-1400×1050.jpg
  84. 84 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/cal/sept-17-talk-like-a-pirate-day-cal-1440×900.jpg
  85. 85 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/cal/sept-17-talk-like-a-pirate-day-cal-1600×1200.jpg
  86. 86 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/cal/sept-17-talk-like-a-pirate-day-cal-1680×1050.jpg
  87. 87 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/cal/sept-17-talk-like-a-pirate-day-cal-1680×1200.jpg
  88. 88 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/cal/sept-17-talk-like-a-pirate-day-cal-1920×1080.jpg
  89. 89 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/cal/sept-17-talk-like-a-pirate-day-cal-1920×1200.jpg
  90. 90 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/cal/sept-17-talk-like-a-pirate-day-cal-1920×1440.jpg
  91. 91 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/cal/sept-17-talk-like-a-pirate-day-cal-2560×1440.jpg
  92. 92 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/nocal/sept-17-talk-like-a-pirate-day-nocal-640×480.jpg
  93. 93 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/nocal/sept-17-talk-like-a-pirate-day-nocal-800×480.jpg
  94. 94 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/nocal/sept-17-talk-like-a-pirate-day-nocal-800×600.jpg
  95. 95 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/nocal/sept-17-talk-like-a-pirate-day-nocal-1024×768.jpg
  96. 96 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/nocal/sept-17-talk-like-a-pirate-day-nocal-1280×720.jpg
  97. 97 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/nocal/sept-17-talk-like-a-pirate-day-nocal-1280×800.jpg
  98. 98 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/nocal/sept-17-talk-like-a-pirate-day-nocal-1280×960.jpg
  99. 99 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/nocal/sept-17-talk-like-a-pirate-day-nocal-1400×1050.jpg
  100. 100 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/nocal/sept-17-talk-like-a-pirate-day-nocal-1440×900.jpg
  101. 101 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/nocal/sept-17-talk-like-a-pirate-day-nocal-1600×1200.jpg
  102. 102 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/nocal/sept-17-talk-like-a-pirate-day-nocal-1680×1050.jpg
  103. 103 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/nocal/sept-17-talk-like-a-pirate-day-nocal-1680×1200.jpg
  104. 104 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/nocal/sept-17-talk-like-a-pirate-day-nocal-1920×1080.jpg
  105. 105 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/nocal/sept-17-talk-like-a-pirate-day-nocal-1920×1200.jpg
  106. 106 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/nocal/sept-17-talk-like-a-pirate-day-nocal-1920×1440.jpg
  107. 107 http://files.smashingmagazine.com/wallpapers/sept-17/talk-like-a-pirate-day/nocal/sept-17-talk-like-a-pirate-day-nocal-2560×1440.jpg
  108. 108 http://bit.ly/TheHannonGroup
  109. 109 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/sept-17-marylandpride-full.png
  110. 110 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/sept-17-marylandpride-preview.png
  111. 111 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/cal/sept-17-marylandpride-cal-320×480.png
  112. 112 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/cal/sept-17-marylandpride-cal-640×480.png
  113. 113 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/cal/sept-17-marylandpride-cal-800×600.png
  114. 114 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/cal/sept-17-marylandpride-cal-1024×768.png
  115. 115 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/cal/sept-17-marylandpride-cal-1280×960.png
  116. 116 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/cal/sept-17-marylandpride-cal-1440×900.png
  117. 117 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/cal/sept-17-marylandpride-cal-1600×1200.png
  118. 118 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/cal/sept-17-marylandpride-cal-1680×1050.png
  119. 119 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/cal/sept-17-marylandpride-cal-1680×1200.png
  120. 120 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/cal/sept-17-marylandpride-cal-1920×1080.png
  121. 121 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/cal/sept-17-marylandpride-cal-1920×1440.png
  122. 122 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/cal/sept-17-marylandpride-cal-2560×1440.png
  123. 123 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/nocal/sept-17-marylandpride-nocal-320×480.png
  124. 124 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/nocal/sept-17-marylandpride-nocal-640×480.png
  125. 125 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/nocal/sept-17-marylandpride-nocal-800×600.png
  126. 126 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/nocal/sept-17-marylandpride-nocal-1024×768.png
  127. 127 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/nocal/sept-17-marylandpride-nocal-1280×960.png
  128. 128 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/nocal/sept-17-marylandpride-nocal-1440×900.png
  129. 129 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/nocal/sept-17-marylandpride-nocal-1600×1200.png
  130. 130 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/nocal/sept-17-marylandpride-nocal-1680×1050.png
  131. 131 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/nocal/sept-17-marylandpride-nocal-1680×1200.png
  132. 132 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/nocal/sept-17-marylandpride-nocal-1920×1080.png
  133. 133 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/nocal/sept-17-marylandpride-nocal-1920×1440.png
  134. 134 http://files.smashingmagazine.com/wallpapers/sept-17/marylandpride/nocal/sept-17-marylandpride-nocal-2560×1440.png
  135. 135 https://www.behance.net/mirunasfia
  136. 136 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/sept-17-still-in-vacation-mood-full.png
  137. 137 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/sept-17-still-in-vacation-mood-preview.png
  138. 138 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-320×480.png
  139. 139 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-640×480.png
  140. 140 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-800×480.png
  141. 141 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-800×600.png
  142. 142 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-1024×768.png
  143. 143 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-1024×1024.png
  144. 144 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-1152×864.png
  145. 145 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-1280×720.png
  146. 146 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-1280×800.png
  147. 147 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-1280×960.png
  148. 148 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-1280×1024.png
  149. 149 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-1440×900.png
  150. 150 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-1440×1050.png
  151. 151 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-1600×1200.png
  152. 152 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-1680×1050.png
  153. 153 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-1680×1200.png
  154. 154 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-1920×1080.png
  155. 155 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-1920×1200.png
  156. 156 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-1920×1440.png
  157. 157 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/cal/sept-17-still-in-vacation-mood-cal-2560×1440.png
  158. 158 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-320×480.png
  159. 159 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-640×480.png
  160. 160 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-800×480.png
  161. 161 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-800×600.png
  162. 162 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-1024×768.png
  163. 163 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-1024×1024.png
  164. 164 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-1152×864.png
  165. 165 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-1280×720.png
  166. 166 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-1280×800.png
  167. 167 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-1280×960.png
  168. 168 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-1280×1024.png
  169. 169 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-1440×900.png
  170. 170 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-1440×1050.png
  171. 171 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-1600×1200.png
  172. 172 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-1680×1050.png
  173. 173 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-1680×1200.png
  174. 174 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-1920×1080.png
  175. 175 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-1920×1200.png
  176. 176 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-1920×1440.png
  177. 177 http://files.smashingmagazine.com/wallpapers/sept-17/still-in-vacation-mood/nocal/sept-17-still-in-vacation-mood-nocal-2560×1440.png
  178. 178 https://www.popwebdesign.net/web-design-agency.html
  179. 179 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/sept-17-autumn-rains-full.jpg
  180. 180 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/sept-17-autumn-rains-preview.jpg
  181. 181 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-320×480.jpg
  182. 182 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-640×480.jpg
  183. 183 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-800×480.jpg
  184. 184 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-800×600.jpg
  185. 185 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-1024×768.jpg
  186. 186 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-1024×1024.jpg
  187. 187 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-1152×864.jpg
  188. 188 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-1280×720.jpg
  189. 189 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-1280×800.jpg
  190. 190 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-1280×960.jpg
  191. 191 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-1280×1024.jpg
  192. 192 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-1366×768.jpg
  193. 193 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-1400×1050.jpg
  194. 194 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-1440×900.jpg
  195. 195 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-1600×1200.jpg
  196. 196 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-1680×1050.jpg
  197. 197 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-1680×1200.jpg
  198. 198 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-1920×1080.jpg
  199. 199 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-1920×1200.jpg
  200. 200 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-1920×1440.jpg
  201. 201 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/cal/sept-17-autumn-rains-cal-2560×1440.jpg
  202. 202 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-320×480.jpg
  203. 203 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-640×480.jpg
  204. 204 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-800×480.jpg
  205. 205 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-800×600.jpg
  206. 206 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-1024×768.jpg
  207. 207 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-1024×1024.jpg
  208. 208 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-1152×864.jpg
  209. 209 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-1280×720.jpg
  210. 210 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-1280×800.jpg
  211. 211 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-1280×960.jpg
  212. 212 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-1280×1024.jpg
  213. 213 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-1366×768.jpg
  214. 214 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-1400×1050.jpg
  215. 215 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-1440×900.jpg
  216. 216 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-1600×1200.jpg
  217. 217 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-1680×1050.jpg
  218. 218 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-1680×1200.jpg
  219. 219 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-1920×1080.jpg
  220. 220 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-1920×1200.jpg
  221. 221 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-1920×1440.jpg
  222. 222 http://files.smashingmagazine.com/wallpapers/sept-17/autumn-rains/nocal/sept-17-autumn-rains-nocal-2560×1440.jpg
  223. 223 http://www.urbanui.com
  224. 224 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/sept-17-funny-cats-full.png
  225. 225 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/sept-17-funny-cats-preview.png
  226. 226 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/cal/sept-17-funny-cats-cal-360×640.png
  227. 227 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/cal/sept-17-funny-cats-cal-1024×768.png
  228. 228 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/cal/sept-17-funny-cats-cal-1280×720.png
  229. 229 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/cal/sept-17-funny-cats-cal-1280×800.png
  230. 230 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/cal/sept-17-funny-cats-cal-1280×960.png
  231. 231 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/cal/sept-17-funny-cats-cal-1280×1024.png
  232. 232 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/cal/sept-17-funny-cats-cal-1366×768.png
  233. 233 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/cal/sept-17-funny-cats-cal-1400×1050.png
  234. 234 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/cal/sept-17-funny-cats-cal-1440×900.png
  235. 235 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/cal/sept-17-funny-cats-cal-1680×1200.png
  236. 236 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/cal/sept-17-funny-cats-cal-1920×1080.png
  237. 237 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/nocal/sept-17-funny-cats-nocal-360×640.png
  238. 238 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/nocal/sept-17-funny-cats-nocal-1024×768.png
  239. 239 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/nocal/sept-17-funny-cats-nocal-1280×720.png
  240. 240 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/nocal/sept-17-funny-cats-nocal-1280×800.png
  241. 241 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/nocal/sept-17-funny-cats-nocal-1280×960.png
  242. 242 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/nocal/sept-17-funny-cats-nocal-1280×1024.png
  243. 243 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/nocal/sept-17-funny-cats-nocal-1366×768.png
  244. 244 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/nocal/sept-17-funny-cats-nocal-1400×1050.png
  245. 245 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/nocal/sept-17-funny-cats-nocal-1440×900.png
  246. 246 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/nocal/sept-17-funny-cats-nocal-1680×1200.png
  247. 247 http://files.smashingmagazine.com/wallpapers/sept-17/funny-cats/nocal/sept-17-funny-cats-nocal-1920×1080.png
  248. 248 http://www.waisman.info/blog
  249. 249 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/sept-17-september-explorer-full.jpg
  250. 250 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/sept-17-september-explorer-preview.jpg
  251. 251 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/cal/sept-17-september-explorer-cal-1280×1024.jpg
  252. 252 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/cal/sept-17-september-explorer-cal-1440×900.jpg
  253. 253 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/cal/sept-17-september-explorer-cal-1440×1050.jpg
  254. 254 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/cal/sept-17-september-explorer-cal-1600×1200.jpg
  255. 255 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/cal/sept-17-september-explorer-cal-1680×1050.jpg
  256. 256 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/cal/sept-17-september-explorer-cal-1680×1200.jpg
  257. 257 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/cal/sept-17-september-explorer-cal-1920×1080.jpg
  258. 258 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/cal/sept-17-september-explorer-cal-1920×1200.jpg
  259. 259 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/cal/sept-17-september-explorer-cal-1920×1440.jpg
  260. 260 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/cal/sept-17-september-explorer-cal-2560×1440.jpg
  261. 261 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/nocal/sept-17-september-explorer-nocal-1280×1024.jpg
  262. 262 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/nocal/sept-17-september-explorer-nocal-1440×900.jpg
  263. 263 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/nocal/sept-17-september-explorer-nocal-1440×1050.jpg
  264. 264 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/nocal/sept-17-september-explorer-nocal-1600×1200.jpg
  265. 265 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/nocal/sept-17-september-explorer-nocal-1680×1050.jpg
  266. 266 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/nocal/sept-17-september-explorer-nocal-1680×1200.jpg
  267. 267 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/nocal/sept-17-september-explorer-nocal-1920×1080.jpg
  268. 268 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/nocal/sept-17-september-explorer-nocal-1920×1200.jpg
  269. 269 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/nocal/sept-17-september-explorer-nocal-1920×1440.jpg
  270. 270 http://files.smashingmagazine.com/wallpapers/sept-17/september-explorer/nocal/sept-17-september-explorer-nocal-2560×1440.jpg
  271. 271 https://www.advancedwebranking.com/
  272. 272 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/sept-17-geometric-autumn-full.png
  273. 273 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/sept-17-geometric-autumn-preview.png
  274. 274 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/cal/sept-17-geometric-autumn-cal-800×600.png
  275. 275 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/cal/sept-17-geometric-autumn-cal-1024×768.png
  276. 276 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/cal/sept-17-geometric-autumn-cal-1280×800.png
  277. 277 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/cal/sept-17-geometric-autumn-cal-1280×1024.png
  278. 278 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/cal/sept-17-geometric-autumn-cal-1440×900.png
  279. 279 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/cal/sept-17-geometric-autumn-cal-1440×1050.png
  280. 280 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/cal/sept-17-geometric-autumn-cal-1600×1200.png
  281. 281 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/cal/sept-17-geometric-autumn-cal-1680×1200.png
  282. 282 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/cal/sept-17-geometric-autumn-cal-1920×1200.png
  283. 283 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/cal/sept-17-geometric-autumn-cal-1920×1440.png
  284. 284 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/cal/sept-17-geometric-autumn-cal-2560×1440.png
  285. 285 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/nocal/sept-17-geometric-autumn-nocal-800×600.png
  286. 286 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/nocal/sept-17-geometric-autumn-nocal-1024×768.png
  287. 287 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/nocal/sept-17-geometric-autumn-nocal-1280×800.png
  288. 288 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/nocal/sept-17-geometric-autumn-nocal-1280×1024.png
  289. 289 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/nocal/sept-17-geometric-autumn-nocal-1440×900.png
  290. 290 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/nocal/sept-17-geometric-autumn-nocal-1440×1050.png
  291. 291 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/nocal/sept-17-geometric-autumn-nocal-1600×1200.png
  292. 292 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/nocal/sept-17-geometric-autumn-nocal-1680×1200.png
  293. 293 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/nocal/sept-17-geometric-autumn-nocal-1920×1200.png
  294. 294 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/nocal/sept-17-geometric-autumn-nocal-1920×1440.png
  295. 295 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-autumn/nocal/sept-17-geometric-autumn-nocal-2560×1440.png
  296. 296 http://melissa.bogemans.com
  297. 297 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/sept-17-fall-is-here-full.png
  298. 298 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/sept-17-fall-is-here-preview.png
  299. 299 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-320×480.png
  300. 300 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-640×480.png
  301. 301 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-800×480.png
  302. 302 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-800×600.png
  303. 303 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-1024×768.png
  304. 304 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-1024×1024.png
  305. 305 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-1152×864.png
  306. 306 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-1280×720.png
  307. 307 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-1280×800.png
  308. 308 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-1280×960.png
  309. 309 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-1280×1024.png
  310. 310 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-1400×1050.png
  311. 311 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-1440×900.png
  312. 312 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-1600×1200.png
  313. 313 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-1680×1050.png
  314. 314 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-1680×1200.png
  315. 315 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-1920×1200.png
  316. 316 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-1920×1440.png
  317. 317 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/cal/sept-17-fall-is-here-cal-2560×1440.png
  318. 318 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-320×480.png
  319. 319 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-640×480.png
  320. 320 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-800×480.png
  321. 321 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-800×600.png
  322. 322 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-1024×768.png
  323. 323 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-1024×1024.png
  324. 324 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-1152×864.png
  325. 325 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-1280×720.png
  326. 326 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-1280×800.png
  327. 327 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-1280×960.png
  328. 328 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-1280×1024.png
  329. 329 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-1400×1050.png
  330. 330 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-1440×900.png
  331. 331 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-1600×1200.png
  332. 332 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-1680×1050.png
  333. 333 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-1680×1200.png
  334. 334 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-1920×1200.png
  335. 335 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-1920×1440.png
  336. 336 http://files.smashingmagazine.com/wallpapers/sept-17/fall-is-here/nocal/sept-17-fall-is-here-nocal-2560×1440.png
  337. 337 https://www.bootstrapdash.com
  338. 338 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/sept-17-umbrella-full.png
  339. 339 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/sept-17-umbrella-preview.png
  340. 340 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/cal/sept-17-umbrella-cal-360×640.png
  341. 341 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/cal/sept-17-umbrella-cal-1024×768.png
  342. 342 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/cal/sept-17-umbrella-cal-1280×800.png
  343. 343 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/cal/sept-17-umbrella-cal-1280×960.png
  344. 344 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/cal/sept-17-umbrella-cal-1280×1024.png
  345. 345 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/cal/sept-17-umbrella-cal-1366×768.png
  346. 346 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/cal/sept-17-umbrella-cal-1400×1050.png
  347. 347 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/cal/sept-17-umbrella-cal-1440×900.png
  348. 348 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/cal/sept-17-umbrella-cal-1600×900.png
  349. 349 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/cal/sept-17-umbrella-cal-1680×1200.png
  350. 350 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/cal/sept-17-umbrella-cal-1920×1080.png
  351. 351 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/nocal/sept-17-umbrella-nocal-360×640.png
  352. 352 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/nocal/sept-17-umbrella-nocal-1024×768.png
  353. 353 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/nocal/sept-17-umbrella-nocal-1280×800.png
  354. 354 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/nocal/sept-17-umbrella-nocal-1280×960.png
  355. 355 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/nocal/sept-17-umbrella-nocal-1280×1024.png
  356. 356 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/nocal/sept-17-umbrella-nocal-1366×768.png
  357. 357 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/nocal/sept-17-umbrella-nocal-1400×1050.png
  358. 358 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/nocal/sept-17-umbrella-nocal-1440×900.png
  359. 359 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/nocal/sept-17-umbrella-nocal-1600×900.png
  360. 360 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/nocal/sept-17-umbrella-nocal-1680×1200.png
  361. 361 http://files.smashingmagazine.com/wallpapers/sept-17/umbrella/nocal/sept-17-umbrella-nocal-1920×1080.png
  362. 362 https://www.behance.net/philippebrouard
  363. 363 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/sept-17-sweet-time-under-the-banana-tree-full.jpg
  364. 364 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/sept-17-sweet-time-under-the-banana-tree-preview.jpg
  365. 365 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/cal/sept-17-sweet-time-under-the-banana-tree-cal-320×480.jpg
  366. 366 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/cal/sept-17-sweet-time-under-the-banana-tree-cal-800×480.jpg
  367. 367 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/cal/sept-17-sweet-time-under-the-banana-tree-cal-800×600.jpg
  368. 368 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/cal/sept-17-sweet-time-under-the-banana-tree-cal-1024×768.jpg
  369. 369 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/cal/sept-17-sweet-time-under-the-banana-tree-cal-1280×800.jpg
  370. 370 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/cal/sept-17-sweet-time-under-the-banana-tree-cal-1280×1024.jpg
  371. 371 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/cal/sept-17-sweet-time-under-the-banana-tree-cal-1366×768.jpg
  372. 372 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/cal/sept-17-sweet-time-under-the-banana-tree-cal-1600×1200.jpg
  373. 373 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/cal/sept-17-sweet-time-under-the-banana-tree-cal-1920×1080.jpg
  374. 374 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/cal/sept-17-sweet-time-under-the-banana-tree-cal-1920×1200.jpg
  375. 375 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/cal/sept-17-sweet-time-under-the-banana-tree-cal-2560×1440.jpg
  376. 376 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/cal/sept-17-sweet-time-under-the-banana-tree-cal-2560×1600.jpg
  377. 377 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/nocal/sept-17-sweet-time-under-the-banana-tree-nocal-320×480.jpg
  378. 378 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/nocal/sept-17-sweet-time-under-the-banana-tree-nocal-800×480.jpg
  379. 379 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/nocal/sept-17-sweet-time-under-the-banana-tree-nocal-800×600.jpg
  380. 380 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/nocal/sept-17-sweet-time-under-the-banana-tree-nocal-1024×768.jpg
  381. 381 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/nocal/sept-17-sweet-time-under-the-banana-tree-nocal-1280×800.jpg
  382. 382 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/nocal/sept-17-sweet-time-under-the-banana-tree-nocal-1280×1024.jpg
  383. 383 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/nocal/sept-17-sweet-time-under-the-banana-tree-nocal-1366×768.jpg
  384. 384 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/nocal/sept-17-sweet-time-under-the-banana-tree-nocal-1600×1200.jpg
  385. 385 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/nocal/sept-17-sweet-time-under-the-banana-tree-nocal-1920×1080.jpg
  386. 386 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/nocal/sept-17-sweet-time-under-the-banana-tree-nocal-1920×1200.jpg
  387. 387 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/nocal/sept-17-sweet-time-under-the-banana-tree-nocal-2560×1440.jpg
  388. 388 http://files.smashingmagazine.com/wallpapers/sept-17/sweet-time-under-the-banana-tree/nocal/sept-17-sweet-time-under-the-banana-tree-nocal-2560×1600.jpg
  389. 389 https://www.behance.net/jamesmitchell23
  390. 390 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/sept-17-geometric-leaf-full.png
  391. 391 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/sept-17-geometric-leaf-preview.png
  392. 392 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/cal/sept-17-geometric-leaf-cal-1280×720.png
  393. 393 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/cal/sept-17-geometric-leaf-cal-1280×800.png
  394. 394 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/cal/sept-17-geometric-leaf-cal-1366×768.png
  395. 395 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/cal/sept-17-geometric-leaf-cal-1440×900.png
  396. 396 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/cal/sept-17-geometric-leaf-cal-1680×1050.png
  397. 397 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/cal/sept-17-geometric-leaf-cal-1920×1080.png
  398. 398 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/cal/sept-17-geometric-leaf-cal-1920×1200.png
  399. 399 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/cal/sept-17-geometric-leaf-cal-2560×1440.png
  400. 400 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/cal/sept-17-geometric-leaf-cal-2880×1800.png
  401. 401 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/nocal/sept-17-geometric-leaf-nocal-1280×720.png
  402. 402 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/nocal/sept-17-geometric-leaf-nocal-1280×800.png
  403. 403 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/nocal/sept-17-geometric-leaf-nocal-1366×768.png
  404. 404 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/nocal/sept-17-geometric-leaf-nocal-1440×900.png
  405. 405 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/nocal/sept-17-geometric-leaf-nocal-1680×1050.png
  406. 406 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/nocal/sept-17-geometric-leaf-nocal-1920×1080.png
  407. 407 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/nocal/sept-17-geometric-leaf-nocal-1920×1200.png
  408. 408 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/nocal/sept-17-geometric-leaf-nocal-2560×1440.png
  409. 409 http://files.smashingmagazine.com/wallpapers/sept-17/geometric-leaf/nocal/sept-17-geometric-leaf-nocal-2880×1800.png
  410. 410 http://www.innatesign.com/
  411. 411 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/sept-17-september-festivals-in-india-full.png
  412. 412 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/sept-17-september-festivals-in-india-preview.png
  413. 413 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/cal/sept-17-september-festivals-in-india-cal-1024×768.png
  414. 414 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/cal/sept-17-september-festivals-in-india-cal-1152×864.png
  415. 415 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/cal/sept-17-september-festivals-in-india-cal-1280×720.png
  416. 416 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/cal/sept-17-september-festivals-in-india-cal-1280×800.png
  417. 417 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/cal/sept-17-september-festivals-in-india-cal-1280×960.png
  418. 418 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/cal/sept-17-september-festivals-in-india-cal-1280×1024.png
  419. 419 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/cal/sept-17-september-festivals-in-india-cal-1400×1050.png
  420. 420 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/cal/sept-17-september-festivals-in-india-cal-1440×900.png
  421. 421 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/cal/sept-17-september-festivals-in-india-cal-1600×1200.png
  422. 422 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/cal/sept-17-september-festivals-in-india-cal-1680×1050.png
  423. 423 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/cal/sept-17-september-festivals-in-india-cal-1680×1200.png
  424. 424 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/cal/sept-17-september-festivals-in-india-cal-1920×1080.png
  425. 425 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/nocal/sept-17-september-festivals-in-india-nocal-1024×768.png
  426. 426 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/nocal/sept-17-september-festivals-in-india-nocal-1152×864.png
  427. 427 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/nocal/sept-17-september-festivals-in-india-nocal-1280×720.png
  428. 428 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/nocal/sept-17-september-festivals-in-india-nocal-1280×800.png
  429. 429 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/nocal/sept-17-september-festivals-in-india-nocal-1280×960.png
  430. 430 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/nocal/sept-17-september-festivals-in-india-nocal-1280×1024.png
  431. 431 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/nocal/sept-17-september-festivals-in-india-nocal-1400×1050.png
  432. 432 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/nocal/sept-17-september-festivals-in-india-nocal-1440×900.png
  433. 433 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/nocal/sept-17-september-festivals-in-india-nocal-1600×1200.png
  434. 434 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/nocal/sept-17-september-festivals-in-india-nocal-1680×1050.png
  435. 435 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/nocal/sept-17-september-festivals-in-india-nocal-1680×1200.png
  436. 436 http://files.smashingmagazine.com/wallpapers/sept-17/september-festivals-in-india/nocal/sept-17-september-festivals-in-india-nocal-1920×1080.png
  437. 437 http://metrovista.com
  438. 438 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/sept-17-dreams-dont-work-unless-you-do-full.png
  439. 439 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/sept-17-dreams-dont-work-unless-you-do-preview.png
  440. 440 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/cal/sept-17-dreams-dont-work-unless-you-do-cal-640×480.png
  441. 441 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/cal/sept-17-dreams-dont-work-unless-you-do-cal-800×600.png
  442. 442 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/cal/sept-17-dreams-dont-work-unless-you-do-cal-1024×768.png
  443. 443 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/cal/sept-17-dreams-dont-work-unless-you-do-cal-1152×864.png
  444. 444 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/cal/sept-17-dreams-dont-work-unless-you-do-cal-1280×720.png
  445. 445 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/cal/sept-17-dreams-dont-work-unless-you-do-cal-1280×960.png
  446. 446 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/cal/sept-17-dreams-dont-work-unless-you-do-cal-1366×768.png
  447. 447 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/cal/sept-17-dreams-dont-work-unless-you-do-cal-1400×1050.png
  448. 448 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/cal/sept-17-dreams-dont-work-unless-you-do-cal-1600×1200.png
  449. 449 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/cal/sept-17-dreams-dont-work-unless-you-do-cal-1920×1080.png
  450. 450 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/cal/sept-17-dreams-dont-work-unless-you-do-cal-1920×1440.png
  451. 451 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/cal/sept-17-dreams-dont-work-unless-you-do-cal-2560×1440.png
  452. 452 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/nocal/sept-17-dreams-dont-work-unless-you-do-nocal-640×480.png
  453. 453 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/nocal/sept-17-dreams-dont-work-unless-you-do-nocal-800×600.png
  454. 454 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/nocal/sept-17-dreams-dont-work-unless-you-do-nocal-1024×768.png
  455. 455 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/nocal/sept-17-dreams-dont-work-unless-you-do-nocal-1152×864.png
  456. 456 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/nocal/sept-17-dreams-dont-work-unless-you-do-nocal-1280×720.png
  457. 457 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/nocal/sept-17-dreams-dont-work-unless-you-do-nocal-1280×960.png
  458. 458 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/nocal/sept-17-dreams-dont-work-unless-you-do-nocal-1366×768.png
  459. 459 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/nocal/sept-17-dreams-dont-work-unless-you-do-nocal-1400×1050.png
  460. 460 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/nocal/sept-17-dreams-dont-work-unless-you-do-nocal-1600×1200.png
  461. 461 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/nocal/sept-17-dreams-dont-work-unless-you-do-nocal-1920×1080.png
  462. 462 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/nocal/sept-17-dreams-dont-work-unless-you-do-nocal-1920×1440.png
  463. 463 http://files.smashingmagazine.com/wallpapers/sept-17/dreams-dont-work-unless-you-do/nocal/sept-17-dreams-dont-work-unless-you-do-nocal-2560×1440.png
  464. 464 http://acodez.in/
  465. 465 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/sept-17-the-world-is-yours-full.png
  466. 466 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/sept-17-the-world-is-yours-preview.png
  467. 467 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-320×480.png
  468. 468 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-640×480.png
  469. 469 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-800×480.png
  470. 470 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-800×600.png
  471. 471 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-1024×768.png
  472. 472 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-1024×1024.png
  473. 473 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-1152×864.png
  474. 474 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-1280×720.png
  475. 475 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-1280×960.png
  476. 476 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-1280×1024.png
  477. 477 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-1366×768.png
  478. 478 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-1400×1050.png
  479. 479 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-1440×900.png
  480. 480 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-1600×1200.png
  481. 481 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-1680×1050.png
  482. 482 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-1680×1200.png
  483. 483 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-1920×1080.png
  484. 484 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-1920×1200.png
  485. 485 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-1920×1440.png
  486. 486 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/cal/sept-17-the-world-is-yours-cal-2560×1440.png
  487. 487 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-320×480.png
  488. 488 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-640×480.png
  489. 489 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-800×480.png
  490. 490 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-800×600.png
  491. 491 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-1024×768.png
  492. 492 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-1024×1024.png
  493. 493 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-1152×864.png
  494. 494 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-1280×720.png
  495. 495 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-1280×960.png
  496. 496 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-1280×1024.png
  497. 497 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-1366×768.png
  498. 498 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-1400×1050.png
  499. 499 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-1440×900.png
  500. 500 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-1600×1200.png
  501. 501 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-1680×1050.png
  502. 502 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-1680×1200.png
  503. 503 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-1920×1080.png
  504. 504 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-1920×1200.png
  505. 505 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-1920×1440.png
  506. 506 http://files.smashingmagazine.com/wallpapers/sept-17/the-world-is-yours/nocal/sept-17-the-world-is-yours-nocal-2560×1440.png
  507. 507 https://www.ipixtechnologies.com/
  508. 508 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/sept-17-when-music-reckons-your-soul-full.jpg
  509. 509 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/sept-17-when-music-reckons-your-soul-preview.jpg
  510. 510 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-320×480.jpg
  511. 511 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-640×480.jpg
  512. 512 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-800×480.jpg
  513. 513 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-800×600.jpg
  514. 514 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-1024×768.jpg
  515. 515 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-1024×1024.jpg
  516. 516 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-1152×864.jpg
  517. 517 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-1280×720.jpg
  518. 518 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-1280×800.jpg
  519. 519 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-1280×960.jpg
  520. 520 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-1280×1024.jpg
  521. 521 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-1366×768.jpg
  522. 522 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-1440×1050.jpg
  523. 523 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-1600×1200.jpg
  524. 524 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-1680×1050.jpg
  525. 525 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-1680×1200.jpg
  526. 526 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-1920×1080.jpg
  527. 527 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-1920×1200.jpg
  528. 528 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-1920×1440.jpg
  529. 529 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/cal/sept-17-when-music-reckons-your-soul-cal-2560×1440.jpg
  530. 530 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-320×480.jpg
  531. 531 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-640×480.jpg
  532. 532 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-800×480.jpg
  533. 533 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-800×600.jpg
  534. 534 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-1024×768.jpg
  535. 535 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-1024×1024.jpg
  536. 536 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-1152×864.jpg
  537. 537 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-1280×720.jpg
  538. 538 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-1280×800.jpg
  539. 539 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-1280×960.jpg
  540. 540 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-1280×1024.jpg
  541. 541 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-1366×768.jpg
  542. 542 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-1440×1050.jpg
  543. 543 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-1600×1200.jpg
  544. 544 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-1680×1050.jpg
  545. 545 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-1680×1200.jpg
  546. 546 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-1920×1080.jpg
  547. 547 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-1920×1200.jpg
  548. 548 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-1920×1440.jpg
  549. 549 http://files.smashingmagazine.com/wallpapers/sept-17/when-music-reckons-your-soul/nocal/sept-17-when-music-reckons-your-soul-nocal-2560×1440.jpg
  550. 550 https://github.com/BootstrapDash/StarAdmin-Free-Bootstrap-Admin-Template
  551. 551 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/sept-17-dry-the-leaves-full.png
  552. 552 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/sept-17-dry-the-leaves-preview.png
  553. 553 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/cal/sept-17-dry-the-leaves-cal-360×640.png
  554. 554 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/cal/sept-17-dry-the-leaves-cal-1024×768.png
  555. 555 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/cal/sept-17-dry-the-leaves-cal-1280×720.png
  556. 556 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/cal/sept-17-dry-the-leaves-cal-1280×800.png
  557. 557 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/cal/sept-17-dry-the-leaves-cal-1280×960.png
  558. 558 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/cal/sept-17-dry-the-leaves-cal-1280×1024.png
  559. 559 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/cal/sept-17-dry-the-leaves-cal-1366×768.png
  560. 560 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/cal/sept-17-dry-the-leaves-cal-1400×900.png
  561. 561 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/cal/sept-17-dry-the-leaves-cal-1440×768.png
  562. 562 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/cal/sept-17-dry-the-leaves-cal-1600×900.png
  563. 563 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/cal/sept-17-dry-the-leaves-cal-1680×1200.png
  564. 564 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/cal/sept-17-dry-the-leaves-cal-1920×1080.png
  565. 565 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/nocal/sept-17-dry-the-leaves-nocal-360×640.png
  566. 566 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/nocal/sept-17-dry-the-leaves-nocal-1024×768.png
  567. 567 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/nocal/sept-17-dry-the-leaves-nocal-1280×720.png
  568. 568 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/nocal/sept-17-dry-the-leaves-nocal-1280×800.png
  569. 569 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/nocal/sept-17-dry-the-leaves-nocal-1280×960.png
  570. 570 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/nocal/sept-17-dry-the-leaves-nocal-1280×1024.png
  571. 571 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/nocal/sept-17-dry-the-leaves-nocal-1366×768.png
  572. 572 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/nocal/sept-17-dry-the-leaves-nocal-1400×900.png
  573. 573 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/nocal/sept-17-dry-the-leaves-nocal-1440×768.png
  574. 574 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/nocal/sept-17-dry-the-leaves-nocal-1600×900.png
  575. 575 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/nocal/sept-17-dry-the-leaves-nocal-1680×1200.png
  576. 576 http://files.smashingmagazine.com/wallpapers/sept-17/dry-the-leaves/nocal/sept-17-dry-the-leaves-nocal-1920×1080.png
  577. 577 https://www.safiabegum.com/
  578. 578 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/sept-17-happy-birthday-roald-full.png
  579. 579 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/sept-17-happy-birthday-roald-preview.png
  580. 580 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/cal/sept-17-happy-birthday-roald-cal-800×450.png
  581. 581 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/cal/sept-17-happy-birthday-roald-cal-1280×720.png
  582. 582 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/cal/sept-17-happy-birthday-roald-cal-1366×768.png
  583. 583 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/cal/sept-17-happy-birthday-roald-cal-1440×810.png
  584. 584 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/cal/sept-17-happy-birthday-roald-cal-1600×900.png
  585. 585 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/cal/sept-17-happy-birthday-roald-cal-1680×945.png
  586. 586 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/cal/sept-17-happy-birthday-roald-cal-1920×1080.png
  587. 587 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/cal/sept-17-happy-birthday-roald-cal-2560×1440.png
  588. 588 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/nocal/sept-17-happy-birthday-roald-nocal-800×450.png
  589. 589 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/nocal/sept-17-happy-birthday-roald-nocal-1280×720.png
  590. 590 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/nocal/sept-17-happy-birthday-roald-nocal-1366×768.png
  591. 591 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/nocal/sept-17-happy-birthday-roald-nocal-1440×810.png
  592. 592 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/nocal/sept-17-happy-birthday-roald-nocal-1600×900.png
  593. 593 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/nocal/sept-17-happy-birthday-roald-nocal-1680×945.png
  594. 594 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/nocal/sept-17-happy-birthday-roald-nocal-1920×1080.png
  595. 595 http://files.smashingmagazine.com/wallpapers/sept-17/happy-birthday-roald/nocal/sept-17-happy-birthday-roald-nocal-2560×1440.png
  596. 596 http://www.facebook.com/doud.design
  597. 597 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/sept-17-four-friends-full.jpg
  598. 598 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/sept-17-four-friends-preview.jpg
  599. 599 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/cal/sept-17-four-friends-cal-1280×1024.jpg
  600. 600 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/cal/sept-17-four-friends-cal-1366×768.jpg
  601. 601 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/cal/sept-17-four-friends-cal-1440×900.jpg
  602. 602 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/cal/sept-17-four-friends-cal-1440×1050.jpg
  603. 603 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/cal/sept-17-four-friends-cal-1600×1200.jpg
  604. 604 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/cal/sept-17-four-friends-cal-1680×1050.jpg
  605. 605 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/cal/sept-17-four-friends-cal-1920×1080.jpg
  606. 606 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/cal/sept-17-four-friends-cal-1920×1200.jpg
  607. 607 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/cal/sept-17-four-friends-cal-1920×1440.jpg
  608. 608 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/cal/sept-17-four-friends-cal-2560×1440.jpg
  609. 609 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/nocal/sept-17-four-friends-nocal-1280×1024.jpg
  610. 610 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/nocal/sept-17-four-friends-nocal-1366×768.jpg
  611. 611 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/nocal/sept-17-four-friends-nocal-1440×900.jpg
  612. 612 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/nocal/sept-17-four-friends-nocal-1440×1050.jpg
  613. 613 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/nocal/sept-17-four-friends-nocal-1600×1200.jpg
  614. 614 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/nocal/sept-17-four-friends-nocal-1680×1050.jpg
  615. 615 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/nocal/sept-17-four-friends-nocal-1920×1080.jpg
  616. 616 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/nocal/sept-17-four-friends-nocal-1920×1200.jpg
  617. 617 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/nocal/sept-17-four-friends-nocal-1920×1440.jpg
  618. 618 http://files.smashingmagazine.com/wallpapers/sept-17/four-friends/nocal/sept-17-four-friends-nocal-2560×1440.jpg
  619. 619 http://www.tazi.com.au
  620. 620 http://files.smashingmagazine.com/wallpapers/sept-17/spring/sept-17-spring-full.jpg
  621. 621 http://files.smashingmagazine.com/wallpapers/sept-17/spring/sept-17-spring-preview.jpg
  622. 622 http://files.smashingmagazine.com/wallpapers/sept-17/spring/cal/sept-17-spring-cal-320×480.jpg
  623. 623 http://files.smashingmagazine.com/wallpapers/sept-17/spring/cal/sept-17-spring-cal-640×480.jpg
  624. 624 http://files.smashingmagazine.com/wallpapers/sept-17/spring/cal/sept-17-spring-cal-800×600.jpg
  625. 625 http://files.smashingmagazine.com/wallpapers/sept-17/spring/cal/sept-17-spring-cal-1024×768.jpg
  626. 626 http://files.smashingmagazine.com/wallpapers/sept-17/spring/cal/sept-17-spring-cal-1152×864.jpg
  627. 627 http://files.smashingmagazine.com/wallpapers/sept-17/spring/cal/sept-17-spring-cal-1280×720.jpg
  628. 628 http://files.smashingmagazine.com/wallpapers/sept-17/spring/cal/sept-17-spring-cal-1280×960.jpg
  629. 629 http://files.smashingmagazine.com/wallpapers/sept-17/spring/cal/sept-17-spring-cal-1600×1200.jpg
  630. 630 http://files.smashingmagazine.com/wallpapers/sept-17/spring/cal/sept-17-spring-cal-1920×1080.jpg
  631. 631 http://files.smashingmagazine.com/wallpapers/sept-17/spring/cal/sept-17-spring-cal-1920×1440.jpg
  632. 632 http://files.smashingmagazine.com/wallpapers/sept-17/spring/cal/sept-17-spring-cal-2560×1440.jpg
  633. 633 http://files.smashingmagazine.com/wallpapers/sept-17/spring/nocal/sept-17-spring-nocal-320×480.jpg
  634. 634 http://files.smashingmagazine.com/wallpapers/sept-17/spring/nocal/sept-17-spring-nocal-640×480.jpg
  635. 635 http://files.smashingmagazine.com/wallpapers/sept-17/spring/nocal/sept-17-spring-nocal-800×600.jpg
  636. 636 http://files.smashingmagazine.com/wallpapers/sept-17/spring/nocal/sept-17-spring-nocal-1024×768.jpg
  637. 637 http://files.smashingmagazine.com/wallpapers/sept-17/spring/nocal/sept-17-spring-nocal-1152×864.jpg
  638. 638 http://files.smashingmagazine.com/wallpapers/sept-17/spring/nocal/sept-17-spring-nocal-1280×720.jpg
  639. 639 http://files.smashingmagazine.com/wallpapers/sept-17/spring/nocal/sept-17-spring-nocal-1280×960.jpg
  640. 640 http://files.smashingmagazine.com/wallpapers/sept-17/spring/nocal/sept-17-spring-nocal-1600×1200.jpg
  641. 641 http://files.smashingmagazine.com/wallpapers/sept-17/spring/nocal/sept-17-spring-nocal-1920×1080.jpg
  642. 642 http://files.smashingmagazine.com/wallpapers/sept-17/spring/nocal/sept-17-spring-nocal-1920×1440.jpg
  643. 643 http://files.smashingmagazine.com/wallpapers/sept-17/spring/nocal/sept-17-spring-nocal-2560×1440.jpg
  644. 644 https://colormean.ae/
  645. 645 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/sept-17-world-alzheimers-day-full.jpg
  646. 646 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/sept-17-world-alzheimers-day-preview.jpg
  647. 647 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-320×480.jpg
  648. 648 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-640×480.jpg
  649. 649 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-800×480.jpg
  650. 650 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-800×600.jpg
  651. 651 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-1024×768.jpg
  652. 652 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-1024×1024.jpg
  653. 653 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-1152×864.jpg
  654. 654 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-1280×720.jpg
  655. 655 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-1280×800.jpg
  656. 656 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-1280×960.jpg
  657. 657 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-1280×1024.jpg
  658. 658 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-1366×768.jpg
  659. 659 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-1400×1050.jpg
  660. 660 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-1440×900.jpg
  661. 661 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-1600×1200.jpg
  662. 662 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-1680×1050.jpg
  663. 663 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-1680×1200.jpg
  664. 664 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-1920×1080.jpg
  665. 665 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-1920×1200.jpg
  666. 666 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-1920×1440.jpg
  667. 667 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/cal/sept-17-world-alzheimers-day-cal-2560×1440.jpg
  668. 668 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-320×480.jpg
  669. 669 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-640×480.jpg
  670. 670 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-800×480.jpg
  671. 671 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-800×600.jpg
  672. 672 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-1024×768.jpg
  673. 673 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-1024×1024.jpg
  674. 674 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-1152×864.jpg
  675. 675 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-1280×720.jpg
  676. 676 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-1280×800.jpg
  677. 677 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-1280×960.jpg
  678. 678 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-1280×1024.jpg
  679. 679 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-1366×768.jpg
  680. 680 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-1400×1050.jpg
  681. 681 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-1440×900.jpg
  682. 682 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-1600×1200.jpg
  683. 683 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-1680×1050.jpg
  684. 684 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-1680×1200.jpg
  685. 685 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-1920×1080.jpg
  686. 686 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-1920×1200.jpg
  687. 687 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-1920×1440.jpg
  688. 688 http://files.smashingmagazine.com/wallpapers/sept-17/world-alzheimers-day/nocal/sept-17-world-alzheimers-day-nocal-2560×1440.jpg
  689. 689 https://www.smashingmagazine.com/desktop-wallpaper-calendars-join-in/

↑ Back to topTweet itShare on Facebook

An Introduction To Gravit Designer: Designing A Weather App (Part 2)

An Introduction To Gravit Designer: Designing A Weather App (Part 2)

Welcome back to the second part of this tutorial on Gravit Designer. In the first part1 we took a general look at Gravit and set everything up, created the background image in the weather app and the status bar, and then started to make the initial elements of the design’s content.

Let’s continue where we left off.

Sunny With A Chance Of Rain Link

Having created the main text layers of the content area in part one2 of this tutorial, let’s continue with the weather conditions for the different times of day.

3
Figure 1: The weather app, completed. (Go to Part 14)

Start with a simple circle of 56 pixels in diameter (remember to hold Shift), with a white 2-pixel inside border, with no fill outside of the “Status bar” group (figure 1a). Move it to “32” (X) and “368” (Y) in the “Position” fields in the Inspector.

Because we want to reuse this style for other shapes, we will create a new “Shared Style.” This allows you to sync all styling properties between various layers and to update changes with a click. To create a shared style, click on the dropdown field for “Style” in the Inspector that says “No shared style” and select “Create New Shared Style.” Now you can define which properties you want to take over — let’s keep everything checked. For the name, use “Icon outline.”

5
Figure 1a: The base for the different weather conditions is a white circle with a border. Create a “Shared Style” in the Inspector, so that you can bring over the styling to other elements. (View large version6)

Let’s turn to the icon itself now, a sun partly covered by a cloud. It consists of various shapes combined into a single form, and a few paths (for the rays).

First, the cloud (figure 2). Draw a rectangle (R) with a size of 28 × 14 pixels, with fully rounded corners (“7” — drag the slider all the way to the right) inside the circle. Because aligning the various parts of the icon to the grid wouldn’t make sense, switch it off for now with Alt + Command + G (on Windows and Linux, Alt + Control + G). Before we continue, use the zoom function with Z to zoom into the rectangle so that it’s easier to work on the following steps. If you intend to zoom in with Command + + instead, then select the shape beforehand so that Gravit Designer takes it as a reference when zooming and zooms to its center.

Note: Before drawing the rectangle, make sure that the circle isn’t selected or else it will take over all of the properties, including the shared style. This is important for when we add new shapes later: If another element is already selected, then all of its properties will be taken over; if nothing is selected, then the new element will be drawn with a default gray fill and no border. That’s also the style you can use for the rectangle for now.

Now add an ellipse (E) above the rectangle that is 15 × 15 pixels in size, that is away 3 pixels from the left edge of the rectangle and that juts out 7 pixels at the top. Clone it with Shift + Command + D (or, on Windows and Linux, Shift + Control + D), resize it to 12 × 12 in the Inspector, and offset it 10 pixels to the right and 3 pixels to the bottom. Looks like a cloud already!

7
Figure 2: The cloud consists of a rectangle with fully rounded corners and two circles. (View large version8)

However, we want an outline instead of a solid fill, so we’ll need to bring the “Merge” function into play (also called Boolean operations in other applications, such as Sketch). Select the three shapes and click on “Merge” in the toolbar; this will combine everything into a single form and allow us to assign a border in its entirety later on (figure 3). The advantage here is that you can expand the “Compound Shape” group in the Layers panel and still move the elements individually. It’s even possible to adapt the type of merge function — for example, if you want to cut the right-most circle from the other shapes (“Subtract,” the third option). Have a look at “Boolean” in the Inspector to perform this change. The lesser used types here are “Intersect” and “Difference,” which just show the part where the shapes overlay or the exact opposite, respectively.

With the “Compound Shape” group selected, change from a fill to a white inside border with 1.5 pixel thickness. Remember that you can alter the position of the border in the “Advanced stroke settings.” Now it will become immediately apparent what the Merge function has done to the shapes.

9
Figure 3: The “Merge” function combines multiple elements into a single shape but still allows you to modify them individually. After you have “merged” the shapes of the cloud, apply a white border. (Click to play video10)

Complete the cloud by giving it a proper name.

On to the sun now. Create another circle with a 12-pixel diameter outside of the other big circle. With the cloud still selected, this will take over the styling. This time, however, we need a centered border (you will see why later). Switch to the Line tool with L and draw a vertical one 3 pixels in length above the circle. Make sure that the circle is already selected (to take over the styling yet again), and hold Shift while drawing to constrain the movement. The line should be centered to the circle horizontally and have a gap of 4 pixels in the vertical direction.

Note: To directly transfer the styling from one element to another, proceed as follows: Select the root element, press Command + C (on Windows and Linux, Control + C), click on the layer (object) that you want to take the styling over to, and hit F4. Done! Try it — it’s a nice little time-saver!

A Ray Of Light Link

How do we do the other rays now? We need to combine two techniques here (figure 4). An integral part is the “Transform” function in the top section of the Inspector, which is quite a handy tool to apply transformations to objects. It allows you not only to move, rotate and skew objects by a certain amount, but also to resize a layer relatively with percentages.

The thing that interests us most with the Transform feature at the moment, however, is the ability to adapt the rotation point of a shape — the orange rhombus at the center of the line. It defines the point around which a shape is rotated. To continue, perform the following steps:

  1. Clone the line (Mac: Shift + Command + D, Windows and Linux: Shift + Control + D) while it is selected.
  2. Switch to the Transform tool with a click on the button in the Inspector.
  3. Drag the rotation point (the orange rhombus) down so that it is at the center of the circle.
  4. Hold Shift to trigger the rotation mode, and drag the line until the “Angle” field in the Inspector says “-45°.” You might need to release Shift again to catch this exact value.

This rotated line will be the reference for the other rays. First, select and duplicate the initial unrotated line again, but this time with Command + D (on Windows and Linux, Control + D). Then, bring this duplicate to the exact same position and rotation as the other line we just adapted with the Transform function: Drag it there, and rotate it with the “Angle” field in the Inspector. (You might also need to switch off “Snap” in the toolbar for this to work.)

Now press Command + D again until all remaining six rays appear. You might need to align them individually afterward, so that all have the same distance and alignment. Also, delete the duplicate of the second ray.

11
Figure 4: Use the “Transform” feature to change the rotation point of the line, so that it can be duplicated around the circle. (click to play video12)

As with the cloud, we want to combine all of the elements of the sun into a single shape so that we are able to style it as a whole. Select everything (ideally in the Layers panel), and click on “Merge” again in the toolbar. Alternatively, you can press Command + M (on Windows and Linux, Control + M). Rename this group to “Sun.”

Note: Please make sure that the lines (i.e. the rays) are above the circle in the layer hierarchy. The styling of the bottom-most layer is always applied to the other layers when you use the “Merge” function.

One final touch is left for the sun: rounded ends for the rays. Open “Advanced stroke setting” in the Inspector again, and select the second option (“Round”) in “Ends.” Looks great!

The individual parts of the icon (the sun and cloud) are ready now, so let’s bring them together somehow. Be sure to switch on the snapping again in the toolbar. First, bring the sun to the top-right corner of the cloud, then move it about 9 pixels to the top and 8 pixels to the right with the arrow keys on the keyboard.

Now, clone both weather symbols so that we have a backup for later (Mac: Shift + Command + D, Windows and Linux: Shift + Control + D). Note: When selecting two groups, you might want to press Command (on Windows and Linux, Control) instead of Shift, to have everything working correctly. While the second sun can be hidden (use the eye symbol in the Layers panel), we will need to manipulate the copy of the cloud for the further steps. (see figure 5 for all of the steps.)

Right-click on the cloud shape and select “Convert to Path,” which will create a path with individual points instead of the compound shape. We also need to do something similar for the sun, but instead of converting the shape itself, we want to transform its border to a path. This is also possible with a right-click on the shape, but with “Vectorize Border.”

Now you can combine these two elements again to create the partly covered sun: Select both, click on the arrow next to the “Merge” icon in the toolbar, and pick “Subtract.” Just make sure that the sun is behind the cloud in the layer hierarchy.

Name this new icon “Sun” again, and delete the rays that overlap with the cloud. The easiest way is to use the Lasso tool. It can be used to draw a selection of multiple vector points — which is quite different to how a Lasso tool will perform in other applications (like Photoshop, for example, where it serves to select parts of a bitmap image).

To use it for the removal of the rays, pick the “Compound Path” within the sun group, switch to the Lasso tool with O, and drag a selection around the redundant rays. Then, delete them with Backspace (on Windows and Linux, Delete).

Finally, combine this glimpse of the sun with the copy of the cloud into a group named “Cloudy,” and align it with the bigger circle. Group them again into an overarching “Icon” group.

13
Figure 5: Subtract the sun from the cloud so that it looks as if it’s partly covered. (click to play video14)

Once we have added a description of the weather condition, we will have finished our first daytime view (figure 6). Add a text layer above the icon (press T), with the following properties in the Inspector:

  • Color: white
  • Size: 14 pixels
  • Weight: Regular
  • Line spacing: 16 px (click on the “%” label to switch to pixels)
  • Content: “7:00” followed by a break, followed by “Few Clouds.”
  • Alignment: center (the second icon).

After that, select the time within the text layer, and give it a “Semi-Bold” weight. Make sure that it is horizontally centered to the icon, with a vertical distance of about 12 pixels. Show the grid again with Alt + Command + G (on Windows and Linux, Alt + Control + G) so that you can align everything properly. Create one last group from the text and the “Icon” group, named “Icon left,” and we will be ready.

15
Figure 6: The first weather condition is ready. (View large version16)

Before continuing, let’s bring some order to the Layers panel. Drag the “Status bar” group to the very top (or press Shift + Command + up arrow key on the Mac (on Windows and Linux, Shift + Control + up), followed by the three text layers, the copy of the sun and the “Icon left” group.

From Bad To Worse Link

It’s easy to get the other weather symbols from here. Duplicate the current one (“Icon left”), center it to the page and move it to a Y position of “297,” which should align everything neatly to the grid. The group’s name of this new symbol should be “Icon middle”; for the text, use “14:00 Light rain.” Be sure that everything is centered again.

Because this one will represent the current weather condition, select the circle with a Command-click (on Windows and Linux, Control-click) to change from the border to a white fill. Create a new shared style named “Icon full.”

Now go to the Layers panel, where you will select the “Cloud” group within “Icon” → “Cloudy.” Enter the color dialog and use the color-picker symbol to pick a light-blue color for the surrounding of the icon. Now employ the “Mix” area at the bottom of the dialog to change to a darker shade, so that the icon comes to the fore against the white background. Align it to the center of the surrounding circle with the alignment icons, remove the “Cloudy” group with Shift + Command + G (on Windows and Linux, Shift + Control + G), and delete the redundant “Sun” group in the layers panel. See figure 7 for the entire process.

17
Figure 7: Create a new shared style for the middle icon, adapt the cloud and delete the redundant sun. It’s supposed to rain soon! (Click to play video18)

The first steps for the rain symbol are accomplished, but one vital part remains: the raindrops. Just like for the sun in the other icon, we need to convert the cloud to outlines first for the subsequent steps (figure 8). Right-click and select “Vectorize border” like before (which converts to a “Compound Path” group). Now we can create a rectangle of 16 × 6 pixels at the bottom, which will act as the hole for the raindrops. It should be 5 pixels away from the left edge of the cloud and overlap its bottom line. You might want to zoom (press Z) to have a better view and switch off the grid again.

Select the rectangle together with the “Compound Path” group, and create another “Subtract” operation from “Merge” in the toolbar. For it to work correctly, make sure that the rectangle is on top. After that, drag it into the “Icon middle” → “Icon” group again, and also reset its name to “Cloud.”

19
Figure 8: Vectorize the border of the cloud shape and cut away a rectangle. (Click to play video20)

Next task: the raindrops (figure 9). They consist of three vertical lines — two 10 pixels long and one 15. The distance from the first to the second should be 5 pixels, and from the second to the third 4 pixels. Start with the first one of 10 pixels in length: Switch to the Line tool with L and hold Shift to constrain the movement to the vertical axis. Assign a centered border with 1.5 pixel thickness and rounded ends (from “Advanced stroke settings”) and that has the same color as the cloud (either take it over with the color picker or use the “In use” area in the color dialog.)

Now follow these steps:

  1. Clone the line.
  2. Move it 4 pixels to the right with the arrow key.
  3. Switch to the Subselect tool with D, and move the bottom point down by 5 pixels with the arrow key.
  4. Select the first line again.
  5. Make a second copy and move it 9 pixels to the right.
  6. Now select and merge all of the lines (Mac: Command + M, Windows and Linux: Control + M), which will let you transform them all together with the Transform tool in the Inspector.
  7. Enter “-30°” for “Skew” and click on “Apply.” Make sure that all other fields are set to “0” or “100%.”
  8. Leave the tool with another click on “Transform,” so that you are able to align the skewed lines to the cloud, with a distance of 7 pixels to the left edge and 12 pixels to the top edge.
21
Figure 9: Create the lines for the raindrops, and skew them with the “Transform” tool. (View large version22)

For the correct measurement to show up, you might need to press Command + Alt (on Windows and Linux, Control + Alt) to drill into the group. To finish the icon, rename the “Compound Shape” group to “Raindrops” and create a new “Icon inner” container with the “Cloud” group. When selecting the two groups, make sure to use Command (on Windows and Linux, Control) instead of Shift. Also, drag it into the “Icon middle” → “Icon” group and align it properly to the circle again. With this, we have finished the second weather symbol. On to the third and last one!

Still No Improvement Link

To start, zoom out to 100% (Mac: Command + 0, Windows and Linux: Control + 0) for a better view. Select the first symbol — the “Icon left” group — and clone it to an “Icon right” group. Move it to the right of the page with the fifth alignment icon (“Align Right”), and select the “Icon” group within. It should have a gap of 32 pixels from the right edge — the grid will definitely help you here. The text of this symbol should read “22:00 Cloudy.” Like before, make sure that it is centered to the icon. Because we have cloudy weather now, we don’t need the sun anymore. Select its group in the Layers panel and delete it. As well, center the cloud to the circle again in both dimensions. That’s it! We’ve just completed all of the daytimes (figure 10).

23
Figure 10: All three daytimes are ready. (View large version24)

Full View Link

The last element of the weather app (actually, its center part) is the enlarged display of the current weather condition at the bottom of the screen, surrounded by some elegant half circles.

Create the first half circle with a diameter of 464 pixels (figure 11) — switching off the grid might help. Proceed here as follows:

  1. Switch to the Ellipse tool with E.
  2. Move the cursor to the bottom center of the page until the smart guides show this spot.
  3. Hold Shift to create a circle and Alt to start from the middle.
  4. Move this shape down by 16 pixels (add “+16” to the “Position” → “Y” field).
  5. Assign #708AB5 as the fill color.
  6. Set the “Blending” to “Soft light.”
  7. Rename it to “Ellipse 1.”

To set it off from the background image, assign an Inner Shadow at the bottom of the Inspector with a click on the “+” icon on the right. Use the following properties:

  • X: 0
  • Y: 1
  • Blur: 1
  • Opacity: 70%
  • Color: black

As with the other styling properties, multiple shadows can be stacked on top of each other. Create another inner shadow in the same way as above: It should share all values with its sibling, except for the “Blur” — set this one to “20.” Before you continue, create a new layer in the Layers panel (in the top-right), name it “Bottom,” drag it right above the “Overlay” layers, and move this first circle in. If you’d like, you can also assign a different color to this layer so that it differs from the status bar.

25
Figure 11: The first half circle at the bottom of the screen. (View large version26)

We need three more circles (figure 12). Clone the first circle with Shift + Command + D (on Windows and Linux, Shift + Control + D), and resize it to 416 pixels from the center (hold Shift + Alt and drag the bottom-right handle). Style the second circle as follows:

  • Fill: #809AC6
  • First inner shadow: 0/1/1/50% (X/Y/blur/opacity)
  • Second inner shadow: 0/1/12/60%
  • Name: “Ellipse 2”

Create a copy from this second circle, this one with the following properties:

  • Size: 392 pixels in diameter
  • Fill: #CCE0FF
  • First inner shadow: 0/1/1/50%
  • Second inner shadow: 0/1/8/100%
  • Name: “Ellipse 3”

For the fourth and last circle, use these settings:

  • Size: 370 pixels in diameter
  • No fill
  • Blending: Normal
  • Just one inner shadow: 0/1/3/25%
  • Name: “Ellipse with image”

The reason why this last circle has no fill is that it will contain another image of a cloudy sky, alongside some dark overlays. Grab the image27 and bring it into Gravit Designer. Now move it so that it fully covers the last circle, and drag the image into it in the Layers panel, which will clip it automatically to the shape. Another way to create such a mask would be to select both — the shape and image — and pick “Mask with Shape” from the right-click menu. Just make sure that the mask (i.e. the circle) is above the to-be-masked content (the bitmap image) in the layer hierarchy.

After that, create a rectangle within this new mask group (drag it in after it has been created), which will also cover the circle, and give it a black fill with a “Soft light” blending. This will make the image darker; but we need more, so create a clone of this rectangle.

28
Figure 12: The four half circles — the last one with the clipped image and the two dark overlays. (View large version29)

The last element here is an enlarged version of the rain symbol above (figure 13). Proceed as follows:

  1. Select it (“Icon inner” in “Icon middle” → “Icon”).
  2. Duplicate it and move the icon into the “Bottom” Layer group, in the top position.
  3. After that, drag it to the bottom of the page on the canvas (with the Pointer tool — V).
  4. To make it visible in front of the background image, select the “Raindrops” group and change the border color to white, as well as the fill color of the “Cloud” group.
  5. The final move is to enlarge the icon massively to 128 pixels in width and center it to the semi-circle. Make sure that “Keep Ratio” is switched on between the width and height fields in the Inspector and that “Autoscale Borders” is selected in the “Advanced stroke settings” of the raindrops. Otherwise, they will remain at the original border thickness.

To make the icon stand out from the background even more, we could also apply a drop shadow with the properties “-3/3/0/15%.” The same goes for the text layers, but with the values “-1/2/0/10%,” except for the temperature, which harmonizes better with “-2/3/0/5%.”

After so much work, we have finally finished the first screen of the app. Press Command + 0 (on Windows and Linux, Control + 0) to set it in its full glory.

But we want more. In a second iteration, we want to show it with some friendlier conditions.

30
Figure 13: The finished enlarged icon at the bottom — and with it, the entire screen. Make sure to select “Keep Ratio” in the Inspector when resizing the icon. (View large version31)

Finally Sunny Link

Up until now, we’ve worked exclusively in single-page mode, meaning that we’ve had only a single page on the canvas. For the iteration, we need another one (see figure 15 for the result). To enable multi-page mode, click on the toggle next to the “Pages” label (figure 14). Now you can select the current page on the canvas with a click on the title, and press Command + D (on Windows and Linux, Control + D) to duplicate it and keep working there. Rename the first one to “Light rain” with a double-click in the page list and the second to “Sunny” so that there is no ambiguity.

Pages are ideal if you want to create different versions of a screen, to try out variations or just to fiddle around and see all iterations next to each other.

The first task for the new page is to change the time in the status bar to “07:30,” to indicate that we are at another time of day now. Also, modify the day (“Saturday, Jun 16”), as well as the temperature (“28 °C”). Furthermore, we want to display other weather conditions: The left-most and middle should be “Sunny,” the right one “Cloudy.” Ensure that all text layers are centered again. Because we have sunny weather now, this should be reflected in the background image. Unlock the current one, delete it and drag in the new image32. Ensure that it is at the bottom of the layer hierarchy again.

The easiest way to move it there is to press Shift + Command + down arrow on the keyboard (on Windows and Linux, Shift + Control + down arrow). Then, bring it back to the original size with the respective button in the Inspector (“Original size”), and center it to the page in both dimensions with the fourth and seventh alignment icons from the left in the Inspector. This time, the blur should have a slightly smaller radius of “15”; be sure to lock the image again. In addition to dark overlays, we will create a third one, with the full size of the page, a black fill and a “Soft light” blending. Name it “Overlay 3,” and put it right above the image in the layer hierarchy (also locked).

We also need an updated image for the semi-circle at the bottom, within the “Bottom” → “Ellipse with image” groups. Delete the old one and drag in a new bitmap33. It should be clipped and horizontally centered to the circle again and also be displayed at the original size. Drag it vertically until it shows a view that appeals to you. The two overlays are too dark now, so we need to adapt them. Change one to a fill color of #000560 and a “Screen” blending, and the other to #033572 with “Hard light” and an opacity of 12%.

34
Figure 14: A friendlier version of the screen, created on a separate page. Use the toggle in the “Pages” area to change from single- to multi-page mode. We’ve already started to adapt some of its parts. (View large version35)

Fixer Of Icons Link

The only thing left to do is to fix the icons so that they match the text. You can switch to single-page mode again if you like. Because the left icon says “Sunny,” we just need the sun symbol — good that we saved it before tearing it apart earlier. Look for the hidden “Sun” group in the Layers panel and show it again. Delete the old “Cloudy” icon within “Icon left” → “Icon,” and drag the sunny pendant to its place (in the Layers panel and on the canvas). The icon could be a bit bigger, though, about 30 pixels. Continue as follows:

  1. Fully zoom into the icon with “View” → “Fit Selection” from the menu bar.
  2. Zoom out two steps again with Command + - (on Windows and Linux, Control + -).
  3. Grab the bottom handle, hold Shift and Alt, and drag until the width in the Inspector says about 30 pixels. Make sure that “Autoscale Borders” is selected in the “Advanced stroke settings” of the icon.

We also need to give the icon a selected state, because the current time is 7:30. First, change the border color of the sun to the same as for 14:00 — the easiest way is to use the color picker in the color dialog. Now, select the outer circle and change it from the “Icon outline” shared style to “Icon full” in the Inspector. Do the same for the middle weather condition, but in reverse. You also need to replace the rainy icon (“Icon inner”) with the sun there, but with a white outline.

The third place where the sun should appear is within the half circle at the bottom, but at a much larger size. Copy the white version and paste it right above the “Ellipse with image” group. Follow the steps above to resize it to a width of 120 pixels. Finally, use the same shadow as before (-3/3/0/15%) to give it a stronger appearance against the background image.

36
Figure 15: The finished iteration. It’s going to be very hot today! (View large version37)

Export It Link

We now have two versions of the app, showing different times of day and weather conditions (figure 16). Let’s export them in the final step, which is quite a snap in Gravit Designer. Either click on the export icon to the right of the toolbar or press Shift + Command + E (on Windows and Linux, Shift + Control + E) to enter the Export dialog. There, in the “Canvas” tab, you can already see the two pages, ready for exporting.

38
Figure 16: The two pages, ready for exporting in the “Export” dialog. You can open the dialog with the respective icon in the toolbar. (View large version39)

While the default settings should work just fine, you have many different options here to tweak the output to your liking. The “Format” should be pretty self-explanatory, but the “Size” holds a few hidden values: “2x” lets you export at double size for high-resolution displays (“3x” and “4x” work, too), and you can define a fixed width or height (append “w” or “h”) or both dimensions. Lastly, it’s also possible to set the DPI resolution for print designs.

Besides exporting entire pages, you can also get individual layers (objects) out of Gravit Designer. If you select a layer before entering the export dialog, it will show up in the “Selection” tab; “Assets” can be defined when you click on the “+” icon in “Make exportable” in the bottom-left in the main window. There, you have similar options like in the export dialog and can also define multiple types at the same time.

40
Figure 17: You can also export individual elements if you click on the “+” icon in “Make exportable.” They then show up in the “Assets” tab in the export dialog. (View large version41)

I hope you have enjoyed this tutorial and that it has given you valuable insight into Gravit Designer. It was just a small glimpse into the application and its features, because Gravit is capable of creating many different types of designs. Go to designer.io42 to use it online or to download the desktop application.

If you have questions, feel free to ask in the comments below.

You can always reach out to the Gravit team on Twitter43 and Facebook44, and there is also the very friendly discussion board45 where you can post your questions and ideas.

(mb, al)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/2017/08/introduction-gravit-designer-designing-weather-app-part-1/
  2. 2 https://www.smashingmagazine.com/2017/08/introduction-gravit-designer-designing-weather-app-part-1/
  3. 3 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig1-Gravit-Design-Tutorial-large-opt.png
  4. 4 https://www.smashingmagazine.com/2017/08/introduction-gravit-designer-designing-weather-app-part-1/
  5. 5 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig1a-Gravit-Design-Tutorial-large-opt.png
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig1a-Gravit-Design-Tutorial-large-opt.png
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig2-Gravit-Design-Tutorial-large-opt.png
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig2-Gravit-Design-Tutorial-large-opt.png
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig3-Gravit-Design-Tutorial.gif
  10. 10 https://vimeo.com/230184786
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig4-Gravit-Design-Tutorial.gif
  12. 12 https://vimeo.com/230185564
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig5-Gravit-Design-Tutorial.gif
  14. 14 https://vimeo.com/230186283
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig6-Gravit-Design-Tutorial-large-opt.png
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig6-Gravit-Design-Tutorial-large-opt.png
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig7-Gravit-Design-Tutorial.gif
  18. 18 https://vimeo.com/230449984
  19. 19 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig8-Gravit-Design-Tutorial.gif
  20. 20 https://vimeo.com/230450376
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig9-Gravit-Design-Tutorial-large-opt.png
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig9-Gravit-Design-Tutorial-large-opt.png
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig10-Gravit-Design-Tutorial-large-opt.png
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig10-Gravit-Design-Tutorial-large-opt.png
  25. 25 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig11-Gravit-Design-Tutorial-large-opt.png
  26. 26 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig11-Gravit-Design-Tutorial-large-opt.png
  27. 27 https://www.dropbox.com/s/mbppbb7xvyj1aa2/rainy2.png?dl=0
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig12-Gravit-Design-Tutorial-large-opt.png
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig12-Gravit-Design-Tutorial-large-opt.png
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig13-Gravit-Design-Tutorial-large-opt.png
  31. 31 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig13-Gravit-Design-Tutorial-large-opt.png
  32. 32 https://www.dropbox.com/s/lidtmi4a794ai01/sunny1.png?dl=0
  33. 33 https://www.dropbox.com/s/bfe0nb0m5wyycn4/sunny2.PNG?dl=0
  34. 34 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig14-Gravit-Design-Tutorial-large-opt.png
  35. 35 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig14-Gravit-Design-Tutorial-large-opt.png
  36. 36 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig15-Gravit-Design-Tutorial-large-opt.png
  37. 37 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig15-Gravit-Design-Tutorial-large-opt.png
  38. 38 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig16-Gravit-Design-Tutorial-large-opt.png
  39. 39 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig16-Gravit-Design-Tutorial-large-opt.png
  40. 40 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig17-Gravit-Design-Tutorial-large-opt.png
  41. 41 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig17-Gravit-Design-Tutorial-large-opt.png
  42. 42 https://designer.io/
  43. 43 https://twitter.com/gravitdesigner
  44. 44 https://www.facebook.com/GravitDesigner/
  45. 45 https://discuss.gravit.io

↑ Back to topTweet itShare on Facebook

Is Success Down To The Quality Of Your Work?

Is Success Down To The Quality Of Your Work?

One of the biggest fallacies of our industry is that good work speaks for itself. It is a self-delusional lie that those with a good reputation tell themselves to explain their success.

Success means many things to many people. Some think it is getting to work on projects they love; others believe it is earning a lot of money, still others consider it is getting to spend more time with the family.

However you choose to define success, it will require other people’s cooperation. It will involve landing the right job, winning the right kind of work and being able to charge enough money for your services.

It would be great if that were all defined by the quality of your work, but it’s not. There is another factor at play here; your reputation.

I will let you in on a secret; I am not that amazing at my job. Don’t get me wrong; I am good. But I am not a leading mind in our industry or anything. But, people often talk as if I am.

I get invited to speak at conferences, I write for leading publications like Smashing Magazine1 and have a sizeable following on social media2. All this, despite the fact that there are thousands of people who know what I know and can do what I do.

3
My terrifying secret is that despite speaking at conferences and writing regularly for big name publications like Smashing Magazine, I am just not that talented. (Large preview4)

I would love to claim this was down to talent. But in truth, it is because I shamelessly self-promote. Hell, I am doing it right now, and I am even being paid to write this post!

I will be honest, doing so makes me feel uncomfortable. It might be because I am British. We hate talking about ourselves and despise people who are full of self-importance. But from a career perspective, it was the best thing I ever did.

It has helped me to win work to the point where I can now pick and choose the work I do. But it also had another unexpected benefit; my projects tend to run much more smoothly. That is because my clients respect me more. They know I have a reputation and so listen to what I have got to say.

Think of reputation as a currency. A currency that you can spend to advance your career, win new clients or ensure projects run that little bit easier. It a currency that you can spend to achieve your version of success.

Of course, none of this is fair. People should respect ability, not reputation. But most clients don’t know what good looks like and so have to fall back on how other people talk about you. That means that reputation is about a lot more than the quality of your work.

Staying Productive In Everything You Do Link

Every web professional is different, but no one likes to work on weekends and extra hours. Managing your time is vital, and with just a few other tricks you can easily get work done without working more hours. Read more →5

Your Reputation Is About More Than Your Work Link

For a start, producing great work won’t build your reputation if people aren’t aware of it. Sure, word of mouth from satisfied clients is important, but that will only take you so far.

If you don’t get out there and talk about your work, then nobody will ever know about it. That is why most of us haven’t heard of Duncan Haldane6 despite having won the Nobel Prize in Physics, but you have heard of Stephen Hawking who hasn’t.

7
Stephen Hawking has a much higher profile than Duncan Haldane despite the fact he has never won a Nobel Prize. (Large preview8)

Then you also need to ensure people remember you. People have short memories and reputations can quickly fade if not constantly reinforced.

Finally, they have to like you. You can produce the best work in the world, but if you are obnoxious, then you will end up with entirely the wrong sort of reputation.

So if the quality of your work isn’t enough to build a solid reputation, then what is?

The Secrets To Building A Better Reputation Link

Look, I am no Gary Vaynerchuk9. I am not a Times bestseller who has built a business empire based on his ‘personal brand’. But in my little way, I have done okay.

10
Gary Vaynerchuk has built a phenomenal business empire largely based on his personal brand. (Large preview11)

I would like to say that what success I have had in self-promotion has been down to careful planning, but that would be a lie. A good degree of it was blind luck and timing. For example, when I started a web design podcast12 there was nothing else on the subject. I had a monopoly. That gives you a good head start!

You could argue that my success came from grasping the opportunity. But again that was more luck than judgement, and anyway, that is not something you can replicate in your situation.

But among all the blind luck, I have done a few things right. I could drone on about writing great posts, or why my podcast has been a success. But much of my success has boiled down to two things.

The first is my pigheadedness.

Never give up, never surrender Link

When it comes to reputation building, people give up too quickly. They start a blog and then get demoralised when nobody reads it. They submit talks to a conference but give up after a few rejections. So it goes on, a string of half arsed attempts.

Reputation building takes time, not weeks, not months, but years. Years of nobody paying you a blind bit of attention. It took me years before the number of people subscribed to my podcast got above 600. Years more before I was asked to speak at a conference or invited to write a book.

When it comes to reputation building, you need to think long term. That means that you need a reason to do what you do beyond reputation. I blogged because I wanted to get down in writing all the things I was learning. I recorded my podcast every week because I enjoyed chatting with people. Without those extra motivations, I would have given up, too.

But stubbornness plays a big part as well. It would have been easy to skip the occasional podcast episode or conclude client work was more important than posting an article nobody would read. However, you can’t think like that. If you do, self-promotion will always be at the bottom of your task list and will never happen.

To this day, I will without fail, post an article every Tuesday and a podcast every Thursday. My newsletter will go out every other Friday because I know how important it is to stay in the front of people’s minds. The only time I take a break is when I am on vacation. Because if I start slacking off, people will quickly forget me like that 80’s boy band you loved so much.

But putting out regular content is not enough. It has to be the right type of content too.

Know who you are targeting Link

While my pigheadedness proved a benefit, my ego did not, especially when it came to building a reputation. If I’m truthful, my motivation in the early days was to win the approval of the “cool kids” of the web design world. I wanted to be a star of the web design community, and that is what drove my writing and podcasting.

Not only did this mean I found myself frustrated when nothing happened, but it also led to me writing for entirely the wrong audience. Instead of writing for people who might potentially hire me, I spent my time writing articles aimed at impressing other web designers.

Don’t misunderstand me; there is nothing wrong with sharing your knowledge with your peers. In fact, it is something we should all be doing. But, we need to remember why exactly we want to build our reputation. Ultimately it is to progress our careers and win work. That means we need to think long and hard about where we invest our time. Do we speak at a jQuery conference that we have always respected and admired, or at some soulless business event full of potential clients? Personally, I would pick the latter every time.

We also need to be focused in who we target. The larger the number of people you are trying to build a reputation with the harder it is going to be. Becoming a global superstar in web design is extremely challenging. But becoming the go-to web designer within a particular sector or niche is much easier. With limited resources at our disposal, it makes much more sense to focus on a specific area in which to build our reputation.

13
When it comes to reputation building, it is better to be a big fish in a small pond. (Large preview14)

Although the above advice will help, it is not enough on its own. Even if you became an expert in every aspect of reputation building you may still not succeed. That is because our attitude becomes our worst enemy.

Overcoming Your Excuses Link

I’m sick of people making excuses about why they can never build the reputation I have been talking about in this article. They have failed even before they have begun because of their mindset.

So let’s take a moment to address some of the defeatist attitudes that may be rattling around in your brain.

People keep rejecting me Link

Maybe you’ve been dismissed as a speaker or submitted a post to Smashing Magazine that got turned down. Maybe you want to write a book but can’t find a publisher. Whatever the case, get over it. You don’t need any of those things to build a reputation.

If you get turned down as a speaker, start offering webinars. If you can’t get a book deal, self-publish. If people don’t accept your articles, start a blog. You don’t need a gatekeeper to reach an audience.

15
We don’t need gatekeepers to approve our content. If you want to write a book, self publish. (Large preview16)

Sure, you will reach fewer people initially, but it gives you time to hone your craft. Given enough time you will become good enough to attract the attention of those with larger audiences. Eventually, they will be banging down your door.

I don’t have enough time Link

I want to let you in on a shocking truth; we all have the same number of hours in a day. My life is just as busy as yours, but I find time to post an article and podcast episode every week.

Partly this is because I manage my time well17. But mainly, it is because I prioritise it.

You may feel that you do not have the time because you are barely making ends meet by working weekends and evenings already. Well, you have bigger problems and should read my article on pricing your time18.

I don’t know enough Link

Many people are afraid to share their thoughts online for fear of criticism. They don’t think they know enough and don’t want to look like an idiot. Trust me, I get this, and everybody struggles with the same thing.

But please do not let that hold you back. In truth, there is always somebody out there who knows less than you. Admittedly, there will be people who know more, but that doesn’t mean you have nothing of value to add.

I recommend starting with sharing your personal experiences of projects that you have run. By talking about your own experience, you are on safe ground. Nobody can tell you you are wrong because you are only sharing what happened to you. Also, nobody else had that experience, and so there is nobody who is better placed to share it. Do that for a while, and you will find your confidence grows.

Note: Denise Jacobs excellent book19 is a great starting point to build confidence in putting yourself out there.

I hate writing and speaking Link

Finally, I hear a lot of people say that they find public speaking or writing incredibly hard. Believe it or not, this is something that I found hard at the start. As a child, I used to have a stutter and found it incredibly hard to speak in a group. I’ve also always struggled with spelling and grammar which put me off of writing for years.

But speaking and writing are just like any other skill. You eventually become good at it. That is why I don’t regret the fact that I had such a small audience for so long. It gave me time to get better and growing confidence.

Ultimately that is what building a reputation is all about. It is about growing in confidence and being willing to step out from the shadows. It is not easy especially if you are a more introverted character such as myself, but it is worthwhile. You do have something of value to share and those people you look up to are no different to you.

(il)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/author/paul-boag/
  2. 2 http://twitter.com/boagworld/
  3. 3 https://www.smashingmagazine.com/wp-content/uploads/2017/08/PAB5-large-opt.jpg
  4. 4 https://www.smashingmagazine.com/wp-content/uploads/2017/08/PAB5-large-opt.jpg
  5. 5 https://www.smashingmagazine.com/2015/12/getting-work-done-without-simply-working-hours/
  6. 6 https://en.wikipedia.org/wiki/Duncan_Haldane
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2017/08/hawking-large-opt.jpg
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2017/08/hawking-large-opt.jpg
  9. 9 https://www.garyvaynerchuk.com/
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2017/08/Gary_Vaynerchuk-large-opt.jpg
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2017/08/Gary_Vaynerchuk-large-opt.jpg
  12. 12 https://boagworld.com/show/
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2017/08/big-fish-small-pond-shutterstock-large-opt.jpg
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2017/08/big-fish-small-pond-shutterstock-large-opt.jpg
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2017/08/self-publish-large-opt.jpeg
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2017/08/self-publish-large-opt.jpeg
  17. 17 https://boagworld.com/digital-strategy/finding-time/
  18. 18 https://www.smashingmagazine.com/2017/08/what-to-charge-clients/
  19. 19 http://innercriticbook.com/

↑ Back to topTweet itShare on Facebook

Launching An App? Make App Store Optimization Your Foundation For Growth

Launching An App? Make App Store Optimization Your Foundation For Growth

Most apps developed and released in Google’s Play store are abandoned by their developers. Over half of these apps get fewer than 5000 downloads, and most apps are considered unprofitable. This article is not going to make you the next Instagram, but it will hopefully help you get a nice base level of users that you can grow from.

To give you some better understanding of numbers, the example app in this article received 100,000 downloads in eight weeks. This is with a marketing budget of zero and very little work since launch. We’ll cover the basic app store optimizations that will help bring people to your Google Play page. Getting them to download and stay is up to you and up to the value your app provides.

To launch an Android app, you need a plan. Without a plan, you are destined to fail. Your hopes, dreams and code will lie untouched, hidden at the bottom of Google Play for the rest of time or until Google decides to do a clean up and wipes your failure from existence. Of course, to get traction, you need to pick a topic in which enough people are interested, and then the quality of your build is what is going to help keep these users.

Staying Up To Date With Current Trends Link

The mobile app market is a growing industry, making it even more important for designers and developers to stay up to date with current trends and future prospects. And the explosive growth in the mobile app market isn’t stopping anytime soon. Read more →1

Our Example App Link

The app I am going to use as my example is Learn How to Draw372, which I launched in December 2016 in cooperation with artist Will Sliney3. We will talk about our launch goals and techniques. We will also share our results in the form of installations, usage and many more statistics, which we have directly pulled from the Google Developer Console. Hopefully, they will give you some context for what to expect.

Launch Goal Link

Everyone has an idea for an app. Some possess the right skills (or have enough money) to turn that idea into reality, but very few launch successfully. The primary problem with most launches is that the developer goes for the vanity metric: “How many downloads can I get in as short a period as possible?” They want the big bang. They want to show the world they are a big success on day one. The problem with this approach is that what goes up fast and doesn’t have a good product-market fit will come down even faster. Spiking on launch followed by a loss of all your newly acquired users the same week might be worse than not spiking at all.

The goal of our launch was to find a nice steady stream of new users. From these users, you can learn what is working and, more importantly, what is not working with your product. Yes, getting articles written about you also helps with app store optimization, but putting time into this should only happen once your foundation is in place. “Thank you for stating the obvious — just tell us how you did it,” I hear you say. No problem. Here it is.

Launch Strategy Link

When looking into launch strategies, I categorize our user acquisition work into three categories.

  • Big bang

    The big bang is when you get a big number of users up front, and then it dries up. An example here would be getting an article in a high-profile newspaper or getting a retweet from Mark Cuban. Yes, you will get some users long after the day of the tweet, but the majority will have come up front. There are a lot of reasons why a big-bang launch can actually have negative effects on your app. First, if you attract the wrong users, they are very likely to uninstall your app. Having a high rate of uninstallations will have a negative effect on your app store optimization. These users will also now be part of any analytics you have set, making it really difficult to know what your actual customers of interest are doing and where they are having problems. It becomes really difficult to know whether your product has a problem retaining the right users or whether you have simply attracted the wrong users, users whom your product was never going to retain.
  • Long tail

    The next is the long tail. The long tail is where you get consistent installations. The sum of future downloads far outweighs the initial impact. Examples of methods here include being featured consistently or getting repeat recommendations.
  • Chain reaction

    The final category, chain reaction, is where getting one installation leads to getting one more. Most social techniques fall into this bracket.

The category we will focus on in this article is the long tail. We are looking for a consistent source of relevant users. The method we used is Google Play store visibility, and our technique is app store optimization (ASO).

App Store Optimization Link

Our long-tail method focuses on Google Play visibility. Apple and Google are the gatekeepers. Your app’s survival hinges on how well your app places in their stores. Just like in the supermarket, if your product is not on shelves, it is not going to sell.

There are three methods in Google Play by which your app can be found by potential users. We targeted the third: direct search.

  • charts
  • features
  • direct search

Charts have huge power in influencing users to download. Unfortunately, to target charts is to put the cart before the horse. Get everything else right and you will end up at the top of a chart. Not much we can do here to help with your launch.

The second is to get featured. This is the equivalent of a shop placing your product beside its tills. Expect a lot more impulsive buys, but also expect a higher level of churn. These users are not very targeted and probably only downloaded your product to nose around. Again, targeting this method from launch is difficult. Hopefully, if you have stayed close to the Android guidelines and your build quality is high, Google might give you a nice surprise and feature you prominently in the store.

The third method is direct search. This is where we found our gold. Users who search for something using a term that is relevant to what you are offering are the ones you are after. Who better to find your product than people who are actually looking for it. Imagine if you built an app that taught users how to draw, and when any user searches for “learn how to draw,” your app is the first they see. That is a good place to be. The challenge here is all of those other pesky apps that want to get in front of those users. So, let’s see what happens when you search for “learn how to draw” in the Play store.

Boom! There it is.

4
Learn How to Draw appears first for the search term “learn how to draw.”

“learn how to draw” “learn to draw” “draw”
position 1 position 6 position 12
Learn How to Draw app store5
Learn How to Draw app store6
Learn How to Draw app store7

The images above give a good view of the app’s position in Play at one point in time. Seeing your own progress, good or bad, is critical to understand how your ASO is helping.

Learn How to Draw app store8
Learn How to Draw’s position in Play over time for the search query “learn how to draw.” The green lines shows its position (first every week). (Source: Sensor Tower15129) (View large version10)

Learn How to Draw app store11
Learn How to Draw’s position in Play over time for the search query “learn to draw.” (Source: Sensor Tower15129) (View large version13)

Learn How to Draw app store14
Learn How to Draw’s position in Play over time for the search query “draw.” (Source: Sensor Tower15129) (View large version16)

Our ASO Techniques Link

ASO is a little like throwing mud at the wall in the dark. This is simply the way it has to be. Google’s methods for ranking search results are a close-kept secret. I’d like to think that everything in the list below helped, but to what degree we will never know. It is clear that content is key when it comes to ASO, but this is a luxury I do not have because the content in my app is rarely updated. Below is a list of methods I did use.

App Name Link

This is the one I am most proud of. The name Learn How to Draw covers so many good search phases. It covers “learn how to draw,” “learn to draw,” “how to draw” and “draw” all in one name. The only time I would ever consider using a name like “Drawful” is if I had such a strong brand and marketing team that people would actually look for that specific product. Not likely for most of us.

Build Name Link

The thing to remember about the build name is that Google uses it to create your unique URL, among other things. Google is a big fan of using URLs in its search rankings. This was a technique used in the early days of the web and was fazed out by Google because people started to take advantage of it. This will probably happen on mobile, so use it while you can. Here, you can see that I use all of the keywords of interest:

Using our build name com.learn.howtodraw.draw for ASO17
Using our build name com.learn.howtodraw.draw for ASO (View large version18)

19
The app’s resulting URL, taken from our build name (View large version20)

Store Listing Link

This one is obvious, but people still tend not to consider ASO when writing it. The “Title,” “Short description” and “Full description” all play a part.

Store Listing21
Store listing (View large version22)

Updates Link

Updating the app is a good opportunity to get creative. The primary purpose of the text accompanying an app update is to let users know what is in the latest update. That shouldn’t stop you from being creative.

App update information23
App update information

High Ratings Link

A high rating is critical to strong ASO. We look after every review, trying to move three stars to four and four stars to five. We now have a really solid 4.488 out of 5 rating, which puts us in a far better light than the competition. A second tip here is always to use your response to feedback as another opportunity to get creative with wording.

Play store rating24
4.488 out of 5 rating from 618 reviews (View large version25)

Play store rating26
Consistent average rating per day (View large version27)

Play store rating28
Play store reviews

Links to Your Store Page Link

If you have read anything about traditional web search optimization, then you will know that getting links to your content from high-quality sources plays a key part in Google’s magical algorithms. The same goes for ASO. Anytime someone writes about our app Learn How to Draw, I always contact them and ask them to link to our page in the app store, using as many of our keywords in their anchor text as possible.

Strong Visual Content Link

Getting users to your Play store page is half the battle. Now you need to get them to download your app. Our goal here was to give users a clear understanding of why they should download our app by using strong app screenshots and a video montage demonstrating the value of the app. Even with all of this work, we still seem to be failing in this step. Only 17% of users who we get to our Play store page go on to install the app. Definitely room for improvement here.

Learn How to Draw store page bounce rate29
Learn How to Draw’s bounce rate (View large version30)

Our Results Link

The first graph below shows installations. Here, you can see a nice consistent installation rate. Our rate is currently at 1000 new installations per day — again, with zero marketing.

Learn How to Draw installation rate31
Learn How to Draw’s installation rate (View large version32)

Learn How to Draw daily installation rate33
Learn How to Draw’s daily installation rate (View large version34)

Next, and probably most important, is usage. Having a nice flow of users installing your app, only to abandon it the same day, is not very helpful.

Learn How to Draw daily usage rate35
Learn How to Draw’s daily usage rate (View large version36)

From these three graphs, it is clear that Learn How to Draw372 has a nice rate of installations, and we are retaining more users than we are losing.

Ready For Launch Link

There you have it. 100,000 installations in eight weeks by following the techniques above. Start throwing mud, and let us know if you get any to stick.

(da, vf, yk, al, il)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/2017/02/current-trends-future-prospects-mobile-app-market/
  2. 2 https://play.google.com/store/apps/details?id=com.learn.howtodraw.draw
  3. 3 https://twitter.com/WillSliney
  4. 4 https://www.smashingmagazine.com/wp-content/uploads/2017/08/4-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  5. 5 https://www.smashingmagazine.com/wp-content/uploads/2017/08/5-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2017/08/6-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2017/08/7-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2017/08/8-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  9. 9 http://www.sensortower.com
  10. 10
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2017/08/9-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  12. 12 http://www.sensortower.com
  13. 13
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2017/08/10-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  15. 15 http://www.sensortower.com
  16. 16
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2017/08/11-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  18. 18
  19. 19 https://www.smashingmagazine.com/wp-content/uploads/2017/08/12-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  20. 20
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2017/08/13-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  22. 22
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2017/08/14-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2017/08/15-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  25. 25
  26. 26 https://www.smashingmagazine.com/wp-content/uploads/2017/08/16-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  27. 27
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2017/08/17-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2017/08/18-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  30. 30
  31. 31 https://www.smashingmagazine.com/wp-content/uploads/2017/08/1-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  32. 32
  33. 33 https://www.smashingmagazine.com/wp-content/uploads/2017/08/2-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  34. 34
  35. 35 https://www.smashingmagazine.com/wp-content/uploads/2017/08/3-Make-App-Store-Optimization-Your-Foundation-For-Growth-large-opt.png
  36. 36
  37. 37 https://play.google.com/store/apps/details?id=com.learn.howtodraw.draw

↑ Back to topTweet itShare on Facebook

Removing Friction In UX: Last-Minute Travel Planning And Activity Booking (A Case Study)

Removing Friction In UX: Last-Minute Travel Planning And Activity Booking (A Case Study)

Most travellers make last-minute decisions, even though they spend significant time researching things to do before embarking on their trip. Finding a hotel and flight is relatively easy, but when it comes to tours and activities, the problem is that late or last-minute bookings are not always available, and if they are, the process of making a purchase online is often hard. The mobile experience can also be limited because many websites are slow or their booking process is long and complex.

In this article, we’ll present a case study and share observations on the project we designed and built, GetLocal1, an online travel-agency and booking platform in Iceland. We will share how we created a booking platform that tackles multiple challenges faced by mobile users, by building a responsive website with super-fast search and a mobile-optimized booking experience. Although this article focuses on travel, designers and developers can apply what we’ve learned to any type of e-commerce and mobile search.

Building A Mobile eCommerce Site Right Link

If you happen to be planing your next mobile e-commerce website, keep in mind that there are many things to consider before getting started, and questions that you need to ask yourself. Read more →2

Finding The Hardest Problem To Solve Link

We started by writing a business plan outlining the problems we wanted to solve. A study by Google3 shows that 85% of travellers make a purchasing decision after arriving at their destination, and 50% use their mobile phone to book. With this in mind, we built multiple use cases catering to different personas. The hardest problem we needed to solve was for the people on the road who were using a mobile device with a slow connection and who needed to find a specific activity with last-minute availability and who needed to be able to finalize their booking online.

4
Our own vision of the customer journey, where excitement and mobile usage increase upon arrival at the destination.

Imagine a group of friends travelling down the south coast of Iceland, famous for its waterfalls and black-sand beaches. It’s 10:00 am, and the group wants to use the opportunity to book a glacial hike on a nearby glacier named Sólheimajökull; they need to find a tour with a certified glacial guide who is able to fit them in an afternoon tour on the same day. They have a mobile phone connected to a wireless router that came with the rental car, but in the countryside they’ll be lucky if they find a solid 3G connection. They want to book online and secure their spot.

The GetLocal search engine in action5
Searching for a glacier tour with multiple attributes on GetLocal.is. (View large version6)

Going Beyond Mobile Design Link

To us, designing for mobile goes beyond visual design. We look at everything from rendering speed to every single piece of content. From the beginning, GetLocal was designed mobile-first. From the first wireframe drawing to the high-definition designs in Sketch, we kept the mobile experience at the forefront.

Having this in mind helped us to simplify the navigation, as well as the information architecture; it also meant that all elements were designed for touch and that we use mobile design patterns such as horizontal sliding. We also had to overwrite many native form elements and replace them with simpler menus that are easier to use.

First version of the booking UI7
The first version of the booking UI where you would need to click, scroll and click to change the number of adults. (View large version8)
Latest version of the booking UI9
The current version requires only a single click and doesn’t need native browser elements, making it easier to use on mobile. (View large version10)

If you compare our desktop version to the mobile version, you can see that we simply copied the mobile booking form to the desktop version. That wasn’t the plan, but once the mobile version was made, we didn’t see a need to create a different experience for the desktop.

Tour detail page in desktop11
Tour detail page on desktop using the same booking UI as the mobile version. (View large version12)
The main call to action is always prominent and accessible13
The main call to action is always prominent and accessible. (View large version14)
The mobile booking form highlights the availability on individual days15
The mobile booking form highlights the availability on individual days. (View large version16)

The booking form queries real-time availability APIs and immediately informs you of the availability on each day. If a departure has fewer than 10 seats left, we tell you exactly how many can be booked. We do this by connecting to various inventory solutions. Once a product is loaded, we call the API and get the available days, along with the number of seats that are left. This allows us to disable days that have no inventory and show the customer how many seats are left.

Having this direct access in real time saves the user the frustration of not having to start a booking process only to find out that what they want is sold out or not available on their preferred date.

Need For Speed Link

We wanted our customers to get the feeling that our website is super-fast, and we wanted to crack the 1-second start rendering time. It’s not an easy task, especially when you have a very visual website loaded with beautiful images.

We challenged our lead front-end developer, Alpesh Prajapati17 from Gateway Technolabs, to cut requests by 40% and increase the rendering speed by 60%. We wanted to be four times faster than our main competitors. To begin with, he thought it was crazy to set such an ambitious goal, but once we started scrutinizing everything we had made so far, we kept finding ways to improve and move closer to our goals.

After pushing ourselves as far as we could, we hired Harry Roberts18 to audit performance for us. Harry provided a very deep analysis and pointed out a few places where we could do better. As a result, we modified our caching strategy and refactored some of our CSS, leading to even further improvements.

Make Fewer Requests Link

We switched over to HTTP/2 in order to load requests in parallel. However, because each request from the server to the client still takes time, we reduced the number of requests by merging and compressing CSS and JavaScript files, using sprites for icons, etc. The merging and compression bring some overhead to development during updates and releases, but they’re still worth it.

We also broke up the JavaScript and CSS files to load only what is necessary on pages; for example, the CSS and JavaScript required for a calendar isn’t needed on our blog. We also removed some libraries that we were using in the beginning because we found a way around them; for example, we dropped Font Awesome, as awesome as it is.

Compress Images and Serve the Optimum Sizes Link

We use a lot of images and we found that Photoshop and Sketch didn’t compress them highly enough. We started passing all images through ImageOptim19 (Mac only), and then we integrated our CMS with the ImageOptim web service20, so all images that are uploaded go through proper compression before being stored and published on our CDN.

Results after compressing high-resolution images in this article through ImageOptim21
Results after compressing high-resolution images in this article through ImageOptim. (View large version22)

Although compression of the images reduced the sizes a lot, we knew that serving images in different sizes based on the screen size of the device would help further. This also enables us to adjust the cropping point and even to serve different images to different devices to make the best use of the space.

We use the picture element to serve the right-sized image at different breakpoints.

<picture> <source media="(max-width: 480px)" srcset="https://d1xcc5iosvch6m.cloudfront.net/pages/gullfoss-480.jpg" /> <source media="(max-width: 780px)" srcset="https://d1xcc5iosvch6m.cloudfront.net/pages/gullfoss-780.jpg" /> <source media="(max-width: 1200px)" srcset="https://d1xcc5iosvch6m.cloudfront.net/pages/gullfoss-1200.jpg" /> <source srcset="https://d1xcc5iosvch6m.cloudfront.net/pages/gullfoss-2400.jpg" /> <img alt="The magnificent Gullfoss waterfall seen from above" src="https://d1xcc5iosvch6m.cloudfront.net/pages/gullfoss-1200.jpg" /> </picture> 

For each image, we create versions 480, 780, 1200 and 2560 pixels wide. We use a Slack template to position and crop hero banners in the best way for common screen sizes, sometimes using different images if they fit better.

Screenshot of the Slack template we use for banner positioning23
The Slack template we use for banner positioning (View large version24)

We preload the hero banner and serve the best-fitting size inline in the header, for optimum size and design (although preload is not supported25 by all browsers).

<link rel="preload" href="https://d1xcc5iosvch6m.cloudfront.net/images/gullfoss-2560-20170718155205jpg" as="image" media="(min-width:1200px)" /> <link rel="preload" href="https://d1xcc5iosvch6m.cloudfront.net/images/gullfoss-1200-20170718155209jpg" as="image" media="(max-width:1199px)" /> <link rel="preload" href="https://d1xcc5iosvch6m.cloudfront.net/images/gullfoss-780-20170718155212jpg" as="image" media="(max-width:767px)" /> <link rel="preload" href="https://d1xcc5iosvch6m.cloudfront.net/images/gullfoss-480-20170718155215jpg" as="image" media="(max-width:480px)" /> <style>@media screen and (min-width:1200px) {.trip-banner {background-image: url("https://d1xcc5iosvch6m.cloudfront.net/images/gullfoss-2560-20170718155205jpg");}}</style> <style>@media screen and (max-width:1199px) {.trip-banner {background-image: url("https://d1xcc5iosvch6m.cloudfront.net/images/gullfoss-1200-20170718155209jpg");}}</style> <style>@media screen and (max-width:767px) {.trip-banner {background-image: url("https://d1xcc5iosvch6m.cloudfront.net/images/gullfoss-780-20170718155212jpg");}}</style> <style>@media screen and (max-width:480px) {.trip-banner {background-image: url("https://d1xcc5iosvch6m.cloudfront.net/images/gullfoss-480-20170718155215jpg");}}</style> 

Use a CDN, and Cache Properly Link

We have customers from all over the world, and we want customers from Brazil, Australia and China to experience the same speed as customers from Europe. All common files except critical CSS and JavaScript files are stored on Amazon’s S3, served through the CloudFront content delivery network (CDN). For most files, we set the browser cache to be immutable, which basically means that the browser will never try to fetch that file again. In order to break that cache, we change the version numbers of the files. As a backup for browsers that don’t support immutable caching, we set an expiry date very far into the future.

<link href="http://www.smashingmagazine.com//d1xcc5iosvch6m.cloudfront.net/assets/css/v1.17/boostrap.css" rel="stylesheet" type="text/css"> <link href="http://www.smashingmagazine.com//d1xcc5iosvch6m.cloudfront.net/assets/css/v1.17/style.css" rel="stylesheet" type="text/css"> <link href="http://www.smashingmagazine.com//d1xcc5iosvch6m.cloudfront.net/assets/css/v1.17/merge.css" rel="stylesheet" type="text/css"> 

We use Redis26 for server-side caching for the majority of our pages, but we don’t cache everything because the inventory checks need to be live and are populated via AJAX.

When a page loads, we:

  1. get the product details,
  2. load the reviews,
  3. call the real-time availability APIs and populate the calendar,
  4. and, finally, load similar tours.
The sequence of AJAX loading on our tour-detail page27
The sequence of AJAX loading on our tour-detail pages (View large version28)

Move Above-the-Fold Styles Inline Link

Speed has a lot to do with perception. Being able to start rendering a page within a second is important because it gives the impression that it is fast, even if the full rendering time is slower.

Results from a performance test29
Results from a performance test on WebPagetest.org. The B grade is due to third-party scripts. (View large version30)

We do this by taking parts of our main CSS file, just what is needed to render the first part of the page, and include it in the head of our template, which allows the browser to start rendering the page, even though it hasn’t downloaded all of the CSS. Loading CSS files causes render-blocking, so we load the full style sheets asynchronously using loadCSS31.

Keep Optimizing — It’s Never Over! Link

Optimizing is a bit like going on a diet: Once you reach your goal, you tend to start slacking off and forgetting to optimize. Speed is one of our main features, so we often check to make sure we are still in good health. We use Pingdom’s speed tester32 to automatically test various pages and send us weekly results; this alerts us if something goes wrong or we become forgetful.

Use the Tools and Get Outside Help Link

We’ve used Lighthouse33, WebPagetest34 and Google’s PageSpeed Insights35 to better understand what we can do to improve our website. We recommend finding a benchmark, setting a goal and optimizing until you reach that point.

Check out some of the performance articles on Smashing Magazine36. There are also a lot of great videos37 and books38 out there on the subject. Don’t be shy to hire experts to perform an audit or give you advice. This subject is really tricky and requires a lot of specialization.

Can Too Fast Be A Problem? Link

Shortly after going live, we realized that one of our biggest challenges was to find tours with availability. In a relatively small market like Iceland’s, where tourism has been growing more than 20% per year, it’s become increasingly difficult to find available seats close to departure, especially on the more popular tours. We are not a meta search engine, and we integrate directly on top of inventory solutions. We handle the full lifecycle, from search to booking. So, rather than handing off the customer to another sales platform with an affiliation key, we are able to follow the customer through the purchasing funnel, making sure that every step is optimized.

We needed to find a way to map the activities available in our market, so we built a search engine using relative data points, such as location, activity type, price, duration, departure time, vehicle type and sights. Once you start looking into the challenge and throwing booking cutoff times and availability into the mix, the size of the data set starts to grow quite fast.

A tour with three departures a day, 365 days a year, and that contains multiple facets will require over a thousand rows of complex data. Multiply that by a thousand tours and you have over a million rows of data.

With such a large inventory of products on offer but with so many search facets in place (we use over a hundred data points for categorization purposes), we needed to find a solution that not only fulfills our need for speed but also is flexible and scalable enough to handle the load of processing up to a million records in just a few milliseconds.

We thought about building our own search engine and made a few prototypes, but then we came across Algolia and magic started to happen. However, integration with Algolia39 was quite tricky because we needed to design a data set that holds all of the information and facets but with a limitation of 10 KB per record (a limit set by Algolia). We also needed to build custom widgets on top of Algolia’s API because we wanted to use our own designs.

In our database, we store all of the product information that we aggregate from the inventory solutions we integrate with. This includes meta data and descriptions, photos, categorization for the search facets, as well as pricing and availability. This required us to build cron jobs that at certain intervals throughout the day send a request to the APIs of the inventory solutions; these requests check the updated availability for the next few weeks and take in the latest prices. Once an update has been made, we push the changes into Algolia via its API so that the search data set is in sync and shows real-time availability and prices.

The integration of multiple inventory solutions and Algolia was no easy task, but the end result makes us really proud. The search engine delivers a response within 25 milliseconds — it’s almost too fast!

Average response time from our Algolia dashboard40
Average response time from our Algolia dashboard (View large version41)

The 25-Millisecond Problem Link

With the result set updating instantly in 25 milliseconds we realized that we need to somehow let the user know that changes have taken place, because the results might appear below the fold.

To work around this problem, we tested using a “Submit” button to mimic a form’s submission, but the button doesn’t really do anything because once any filter is changed, the result set is updated. All the button does is act like an anchor that navigates you down to the result set, thus giving you a feeling that a change has been made in the result set below.

We also tested the yellow fade technique to highlight the change in the result set number, just to let people know that changes have taken place and that the number of results has changed.

Recently, we’ve been experimenting with a sliding panel that appears for two seconds if there is a change in the result set. On mobile, we fix the position of this preview so that people can immediately see the impact their changes have made on the results.

When the result set updates, we subtly notify the user.42
Subtle notification of changes in the result set

Content Is Still King Link

For us, content is a critical part of design — not only the labels and headings, but also the descriptions of the products we sell. We operate a marketplace, so our suppliers provide us with their own marketing material, including text and images. Because we work with 200 suppliers and have over 1000 tours to sell, you can imagine the vast difference from item to item.

This resulted in our need to rewrite the descriptions for the majority of products we offer. We used the opportunity to enhance the descriptions, making them shorter and more direct. We put ourselves in the shoes of a traveller, reading and trying to understand every product that we sell. What information is necessary, and what is just wasteful fluff? Are key elements missing that we can try to answer, and can we highlight key details that we find important.

This process is slow yet important; it is still in progress, but it enables us to add our personal tone and brand to all of the products we sell. We wanted our tone to be that of a friend or of a friendly local who gives you honest and direct answers, rather than glorifying tourist traps (as magnificent as they might be). This enabled us also to use slightly simpler language, because many of our customers are non-native English speakers. The Hemingway app43 has been a great tool to help us rephrase and form our sentences to make them easier to read and understand.

Before and after editing content using the Hemingway app to measure legibility44
Before and after editing content using the Hemingway app to measure legibility. (View large version45)

Removing Friction Link

E-commerce is full of hurdles, feelings of insecurity, and complex forms and labels. Users often have to to sign up or give away personal information that is not necessarily needed in order to complete their purchase. One small mistake and you’ve lost a customer forever. Our situation is even more difficult because most of our customers only shop once during their stay, so we don’t get much of an opportunity to build a relationship with them.

For this reason, we don’t require anyone to sign up in order to check out or to add a product to their list of favorites. We store their choices in a cookie but allow them to share a link that reveals the contents of their saved list.

Users can share their collection of favorite tours without signing up or providing their email address.46
Users can share their collection of favorite tours without signing up or providing their email address. (View large version47)

We apply the same philosophy to the checkout, having no hidden fees and not asking for any information we don’t need. We explain why we need the information we collect; we auto-suggest country calling codes; and we make sure that the input fields offer the right keyboard format.

Make it easier to input a credit-card number using a mobile phone48
Make it easier to input a credit-card number using a mobile phone. (View large version49)

For us, there are two major hurdles in e-commerce. The first is getting visitors to give up their email address, and the second is getting their credit card information. We experimented with asking for their credit card first, before asking for their name, phone number and email address. The idea behind that was that if they are willing to cross the biggest hurdle of providing their credit card, then providing the rest wouldn’t be a problem. The experiment was successful, although we didn’t see a significant change in conversions. So, we reverted to the classic approach because it felt more natural.

Conclusion Link

Building a great mobile experience is really hard and time-consuming, but with enough attention to detail, you can succeed. For us, it’s been only eight months since going live, so we are nowhere near our goal, although we have made good progress.

We’ve managed to prove our case, and currently the majority of our sales (over 70%) take place on mobile and tablet.

Over 70% of our conversions take place on mobile and tablet50
Over 70% of our conversions take place on mobile and tablet. (View large version51)

Our goal was to go live with a minimum viable product (MVP) in six weeks, including design and development of the first version. In the first version, we had to take a few shortcuts, but we wanted to prove that we were able to convert. We made our first sale, a $2500 snowmobile trip, within two days of going live. Since then, thousands of travellers have used us our service to book their dream vacation. Now we have started to focus on the next phase of our product, so stay tuned.

Summary Link

  • Ship fast and keep testing for usability and market fit.
  • Get everybody on the team on board with recognizing the importance of speed and user experience.
  • Continually question what has been created, and find ways to improve.
  • Set a performance budget, stick to it, and keep measuring.
  • Use the great selection of tools and resources available.
  • Don’t be shy to hire outside help.

(da, vf, yk, al, il)

Footnotes Link

  1. 1 https://www.getlocal.is
  2. 2 https://www.smashingmagazine.com/2014/03/how-to-plan-your-next-mobile-e-commerce-website/
  3. 3 https://www.thinkwithgoogle.com/articles/travel-trends-2016-data-consumer-insights.html
  4. 4 https://www.smashingmagazine.com/wp-content/uploads/2017/08/customer-journey-800w-opt.png
  5. 5 https://www.smashingmagazine.com/wp-content/uploads/2017/08/mobile-search-large-opt.png
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2017/08/mobile-search-large-opt.png
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2017/08/old-widget-large-opt.jpg
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2017/08/old-widget-large-opt.jpg
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2017/08/new-widget-large-opt.png
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2017/08/new-widget-large-opt.png
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2017/08/desktop-tour-detail-large-opt.jpg
  12. 12 https://www.smashingmagazine.com/wp-content/uploads/2017/08/desktop-tour-detail-large-opt.jpg
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2017/08/mobile-tour-detail-large-opt.png
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2017/08/mobile-tour-detail-large-opt.png
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2017/08/mobile-tour-booking-large-opt.png
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2017/08/mobile-tour-booking-large-opt.png
  17. 17 https://twitter.com/alpeshprajapati
  18. 18 https://csswizardry.com/
  19. 19 https://imageoptim.com/mac
  20. 20 https://imageoptim.com/api
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2017/08/imageoptim-large-opt.png
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2017/08/imageoptim-large-opt.png
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2017/08/slack-template-large-opt.jpg
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2017/08/slack-template-large-opt.jpg
  25. 25 http://caniuse.com/#feat=link-rel-preload
  26. 26 https://redis.io/
  27. 27 https://www.smashingmagazine.com/wp-content/uploads/2017/08/load-order-large-opt.jpg
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2017/08/load-order-large-opt.jpg
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2017/08/speed-perf-test-large-opt.png
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2017/08/speed-perf-test-large-opt.png
  31. 31 https://github.com/filamentgroup/loadCSS
  32. 32 https://tools.pingdom.com/
  33. 33 https://developers.google.com/web/tools/lighthouse/
  34. 34 http://www.webpagetest.org/
  35. 35 https://developers.google.com/speed/pagespeed/insights
  36. 36 https://www.smashingmagazine.com/tag/performance/
  37. 37 https://www.google.is/search?biw=1405&bih=799&tbm=vid&q=web+speed+performance+talk&oq=web+speed+performance+talk&gs_l=psy-ab.3..33i160k1l2.5068.8182.0.8423.11.11.0.0.0.0.155.1184.5j6.11.0….0…1.1.64.psy-ab..1.6.695…0i13k1.o7gGwC2YXH4
  38. 38 https://www.amazon.com/s/ref=sr_nr_n_4?fst=as%3Aoff&rh=n%3A3600%2Ck%3Aweb+performance&keywords=web+performance&ie=UTF8&qid=1502260824&rnid=2941120011
  39. 39 https://www.algolia.com/
  40. 40 https://www.smashingmagazine.com/wp-content/uploads/2017/08/search-response-time-large-opt.png
  41. 41 https://www.smashingmagazine.com/wp-content/uploads/2017/08/search-response-time-large-opt.png
  42. 42 https://www.smashingmagazine.com/wp-content/uploads/2017/08/result-notification-800w-opt.png
  43. 43 http://www.hemingwayapp.com/
  44. 44 https://www.smashingmagazine.com/wp-content/uploads/2017/08/hemingway-large-opt.png
  45. 45 https://www.smashingmagazine.com/wp-content/uploads/2017/08/hemingway-large-opt.png
  46. 46 https://www.smashingmagazine.com/wp-content/uploads/2017/08/sharing-favourites-large-opt.png
  47. 47 https://www.smashingmagazine.com/wp-content/uploads/2017/08/sharing-favourites-large-opt.png
  48. 48 https://www.smashingmagazine.com/wp-content/uploads/2017/08/credit-card-input-large-opt.jpg
  49. 49 https://www.smashingmagazine.com/wp-content/uploads/2017/08/credit-card-input-large-opt.jpg
  50. 50 https://www.smashingmagazine.com/wp-content/uploads/2017/08/mobile-conversions-large-opt.png
  51. 51 https://www.smashingmagazine.com/wp-content/uploads/2017/08/mobile-conversions-large-opt.png

↑ Back to topTweet itShare on Facebook

An Introduction To Gravit Designer: Designing A Weather App (Part 1)

An Introduction To Gravit Designer: Designing A Weather App (Part 1)

Being a designer at the moment is great because a wealth of modern design applications are available that let you easily bring your ideas to the screen: Sketch1, Affinity Designer, Adobe XD (beta) and Figma, to name just a few (not to mention the classics, Photoshop and Illustrator). One app that is quite new, though — and perhaps a bit overlooked — is the free Gravit Designer2 app. Gravit gives you all of the tools needed to create functional and elegant screen designs. It can also be used to make icons, designs for print, presentations and much more.

With the recent release of version 3.1, it’s gotten even better: Now you can import your Sketch files into Gravit (similarly to Figma, which also supports3 the new Sketch file4 format), save designs locally or sync them to Gravit Cloud, and get started quickly with design templates. Gravit is free, works on all major OS platforms and is available as both a web and desktop (standalone) app.

5
Figure 1: The completed weather app. (Go to Part 26)

Every new tool can feel daunting at the beginning. So, in this tutorial I will walk you through the creation of a neat weather app (designed by Claudia Driemeyer7). You can download the design file8 to inspect it or use it as the base of your own work. (Please remember that you need to select “View” → “View Mode” → “Output View,” so that the overflowing parts of the design are clipped when you initially open the design in Gravit.)

Moving From Photoshop And Illustrator To Sketch Link

If you’re a UI designer and you still haven’t made the transition, it’s worth trying out. In Sketch, you can work with various plugins that automate parts of your workflow and help you work much more efficiently. Read more →9

Start Me Up Link

The first thing you will see when you open Gravit Designer is the start screen, with a broad selection of presets (see figure 2). For the purpose of this tutorial, let’s start with the “Nexus 5” template, which has the common size of 360 × 640 pixels. (Click and select the template from the dropdown.) If you don’t want to limit your imagination, you can also leave the “width” and “height” fields at the top empty, which will create an infinite canvas; going for a fixed-dimension canvas later will be easy: Just enter width and height values.

This initial screen also lets you open files (either from Gravit Cloud or from your computer) and start from a selection of templates.

10
Figure 2: Bottom-left: Start from the “Nexus 5” preset. Top: Leaving “width” and “height” empty will create a design file with an infinite canvas. (View large version11)

After having selected the “Nexus 5” preset, you will be presented with a new “page” (known as an artboard in other design applications) at the center. The page will hold all of the elements of the proposed app. Because it’s an app about weather and a potential user should see the current conditions at a glance, let’s start with a full-sized background image. I’ve prepared a rainy image12, which you can either save to your computer and drag it to the canvas from there, or copy and paste directly from the browser.

This image will create the first entry in the Layers panel (on the left), and it will also be placed in the center area of Gravit Designer, on the canvas (figure 3). In case the image hasn’t been centered to the page, right-click and select “Align” → “Align Center,” followed by “Align Middle.” Alternatively, you can drag the image until the pink smart guides show you this centered position.

Now, switch to the Pointer tool (press V), hold Shift and Alt both to constrain the ratio of the image and to resize it from the center, and drag out the bottom-right handle. It should have a width of about 415 pixels, visible from “Size” → “W” in the Inspector, the right-hand panel of Gravit Designer (figure 3). The image will overflow the page now — to clip it, select “View” → “View Mode” → “Output view.” Another handy option here is “Outline View,” which shows the outlines of the layers only.

Note: Usually, enlarging bitmap images is not a good idea, but as we will be blurring the image later on, this is not so important.

13
Figure 3: Overview of the interface of Gravit Designer. (Please note that all screenshots in this article show the Dark theme. To switch the interface theme in Gravit, select “Edit” → “Settings” from the menu bar. (View large version14)

Now is a good time to save our file. The best way is to save it to Gravit Cloud with the related option in “File” in the menu bar, which makes it available everywhere and on all devices. Want to start the design in the Mac app and keep working in the browser or on Windows? No problem. You just need to create an account, which is only a matter of seconds (you can read more about Gravit Cloud in my overview on Medium15). For the file name, use something like weather-app.

The other option, of course, is to save the file to your computer with “Save to file…” (from the desktop app version) or “Download File…” (from the web app version of Gravit).

What’s Your Status? Link

Let’s continue with the status bar of the app, whose basic shape is a rectangle. Press R to switch to the Rectangle tool, start to draw in the top-left corner, go all the way to the right, and make it 24 pixels high.

Note: All of these tools (such as the Pointer tool mentioned a little earlier) can also be accessed from the toolbar at the top of Gravit Designer (figure 3)

In case you didn’t get the right dimensions for the rectangle, you can also enter them in the Inspector (the width should be “360.”) The reason we chose exactly 24 pixels is that we will be using an 8-point grid, which prevents an arbitrary placement and sizing of elements. You can display the grid from “View” → “Show Grid” or by pressing Alt + Command + G (or, on Windows and Linux, Alt + Control + G). The actual grid size can be set in the Inspector (“Grid” → “Width and Height”) once you click anywhere outside the page — use “8” for both fields.

16
Figure 4: The background of the status bar (a rectangle shape) placed on the 8-pixel grid. Change the color to white with the color dialog (1); either drag the color picker (2) or select a swatch (3). (View large version17)

Select the rectangle again with a click, and change the color to white. You can do so by clicking on the color field in “Fills” in the Inspector (figure 4, callout 1), which will bring up the color dialog, with many different options. For now, either drag the color picker to the top-left (figure 4, callout 2) or select white from the swatches in the bottom-right (figure 4, callout 3). To let the background image shine through, set the “Opacity” to 50%. Instead of doing that in the color dialog, close it, and enter this value just above the “Fills” area in the Inspector.

Note: The opacity affects the global transparency of the layer, while the “A” field (alpha) in the color dialog sets the opacity of only the current fill. This is especially important because you can add multiple fills with the “+” icon on the right. To delete a fill again, select it with a click and press the trash bin (delete) icon.

Back to the status bar: The next element will be the time, a white text layer with a size of 12 pixels. To add it, switch to the Text tool with T, click in the center of the rectangle, and write “14:00” for example (figure 5). When done, press Esc, set the “Size” to “12” and the font face to “Open Sans” with a “Bold” weight in the Inspector.

Note: Gravit Designer comes with a wide selection of fonts, but you can also bring in your own fonts with “File” → “Import” → “Add fonts…” in the web version; in the desktop app, all fonts on your system can be used out of the box.

18
Figure 5: The text layer for the time; check the Inspector for the correct properties. (Note: I’ve set the color to black for the screenshot, so that the text is properly visible. Use the alignment icons in the top-right to align it to the background.) (View large version19)

Select the time along with the rectangle (hold Shift and click on both), and center them to each other. You can either right-click and select “Align” → “Align Center” and “Align Middle” or use the alignment icons in the top-right — in particular, the fourth and seventh icons from the left. Another option would be to drag the time until the pink smart guides show you this centered position. At the moment, the text layer is barely visible, so we will treat the background image before continuing with the rest of the status bar’s elements.

Wonderful Imagery Link

First, create another full-width rectangle, starting from the top-left, with a height of 376 pixels. Enter the color dialog and, instead of a solid fill, select the second option at the top, a linear gradient (figure 6). It will be created horizontally by default, going from the left to the right. What we want, however, is a vertical gradient, so click on the round arrow pointing to the right twice to rotate it clockwise. The starting color stop of the gradient should still be selected — change its color to #070031 in the “Hex” field. For the other gradient stop, you can use the same color but with 0% alpha.

To blend it in with the image, click anywhere on the rectangle to close the color dialog, and select “Soft Light” from “Blending” right above the “Fills” area in the Inspector.

Note: As with the opacity of a layer, there is a “general” blending, which affects the entire element and how it blends with objects behind it, and a “separate” blending for each fill, which just affects how the various fills interact with each other.

For an even stronger effect, clone this layer with Shift + Command + D (on Windows and Linux, Shift + Control + D). Rename the first rectangle to “Overlay 1” with a double-click in the Layers panel, and the second to “Overlay 2,” select both after holding Shift, and drag them below the other white layer (the background of the status bar). Finally, lock them with a click on the lock symbol so that you don’t interfere with them by accident later on.

20
Figure 6: Create a new rectangle, and change the solid fill to a gradient (click to play video21).

Now to the background image itself. Gravit Designer enables you to directly tweak the colors of a bitmap without needing to fall back on another application. Select the image, click on “Color Adjust” in the Inspector, and change the “Brightness” to “-17%,” the “Contrast” to “27%” and the “Saturation” to “10%” (figure 7). Looks way better, and the time already comes to the fore. Besides this color correction, you have many other filters with which to modify bitmaps. Click on “More” at the bottom of the Inspector, which will show you a comprehensive list of effects to choose from. Be sure also to click on the dropdown at the top.

Back to the background image, where we need to fix one last detail: applying a “Blur” with a “Radius” of “17” (figure 7). To make the white layer of the status bar better blend in with the background image, you can also set its “Blending” to “Soft Light” in the Inspector.

Important: Keep in mind that effects such as blur can slow down Gravit Designer considerably. If you experience this, switch off the effects temporarily with “View → Show Effects” (on a Mac, Command + E, and on Windows and Linux, Control + E).

22
Figure 7: Adapt the image with “Color Adjust,” and apply a Blur effect. More effects are available from the “More” button. (View large version23)

Before we continue with the other elements of the status bar, select its existing parts (the time text layer and background rectangle), and press Command + G (on Windows and Linux, Control + G) to group them, and name this group “Status bar” by double-clicking. This lets you select the entire group, but you can still pick individual elements by holding Command (on Windows and Linux, Control) and clicking on a layer. The same behavior will be enabled with “Click-through this element” in the Inspector.

A handy alternative to using a group is to use a so-called “layer.” (Do not confuse this with a general layer, which is an individual element on the canvas and in the Layers panel.) Add such a layer with a click on the “New Layer” icon (figure 8, callout 1) in the Layers panel. Just like with a group, such a layer (group) also allows you to combine elements but has the following advantages:

  • You can define a color that is shown for all related elements on the canvas (click on the colored bar on the right side of a layer — see figure 8, callout 2),
  • You don’t need to hold Command or Control to select an individual layer within the layer (group) on the canvas.
  • Elements are automatically added to the layer (group) after their creation.
  • You have a separate “Layer” tool (press M, also available from the “Select” tools in the toolbar) that will let you select the entire Layer group.

If you like, you can add a layer and drag the elements from the group in there (and delete the now empty “Status bar” group with Backspace (or, Windows and Linux, Delete).

24
Figure 8: “Layer” is a special kind of group. Add one with a click on the “New Layer” icon (1). Amongst other advantages, a “layer” lets you define the outline color of its elements (2). (View large version25)

Signal Lost Link

The next element for the status bar is the icon for the receive signal (see figure 9 for the process). We’ve drawn some inspiration from iOS’ icon here with its circles — and although that’s quite a contrast from the typical Android design, it’s the perfect opportunity to show the smart duplicate feature of Gravit Designer (more on that in a minute).

Press E to switch to the Ellipse tool, hold Shift to make it a perfect circle, and add a first circle with a diameter of 6 on the left. Switch off the grid with Alt + Command + G (on Windows and Linux, Alt + Control + G). Give it a white fill.

If you’re having trouble creating such a small element, you can also add it at a bigger size and then bring it down to 6 × 6 using the Inspector. Just be sure that “Keep Ratio” (the small icon between the width and height fields) is enabled. Alternatively, press Z to switch to the Zoom tool and drag a selection in the top-left of the page to enlarge this area.

Getting to the other four circles is easy. First, press Command + D (on Windows and Linux, Control + D) to duplicate the element. Then drag it up, so that it is at the same height as the other circle and has a distance of 1 pixel (the pink smart guides help here). After that, press Command + D again to create three more instances at the same distance. This “smart duplicate” feature works for all kinds of transformations, such as rotations, and always repeats all of the steps between the first and second duplication.

The difference between duplicate (Mac: Command + D, Windows and Linux: Control + D) and clone (Mac: Shift + Command + D, Windows and Linux: Shift + Control + D) is that the former offsets the new layer by 10 pixels in each direction (X, Y) and allows for smart duplication. The latter doesn’t.

Let’s suppose the signal isn’t the best over here. So, select the last two circles and apply a border instead of a fill. Click on the eye icon on the right side of the fill to disable it, and instead add a border with the “+” icon in the “Borders” section below. Also, give it a white color.

This default centered border isn’t suitable, however, so change it to an inside type by clicking on the “Advanced stroke settings” on the right. There, change the “Position” to the first icon. For the border width, pick “0.5.”

There are several ways to change a value in an input field in Gravit:

  • Click inside an input field, type the desired value, and press Enter.
  • Use the up or down arrow key on the keyboard to increase or decrease the value by 1;
  • Hold Alt and use the arrow keys to go in increments of 0.1;
  • Hold Shift and use the arrow keys to go in increments of 10.

For our border, the easiest way is to hold Alt and press the down arrow key five times on the keyboard. (With the rise of high-resolution mobile devices, it’s probably OK to use a half-pixel value here, because it will still appear sharp when exported.)

26
Figure 9: Create the circles, duplicate them, and change from a fill to a border (click to play video27).

Finally, select all circles and perform the following steps:

  • Create a group with Command + G (on Windows and Linux, Control + G).
  • Name it “Receive signal” (double-click in the Layers panel to rename).
  • Drag it into the “Status bar” group.
  • Move it so that it is 2 grid units (16 pixels) away from the left edge of the page. (You can show the grid again with Alt + Command + G, or on Windows and Linux, Alt + Control + G.) Pressing Alt to display the smart guides will assist you here.
  • In the vertical direction, center it to the white background (and rename this one to “BG”).

The next element we will tackle is the carrier name (figure 10). Pan a bit to the right (hold the space bar and drag), select the time text layer, hold Alt and drag it to the left to create a duplicate. Make sure that it’s 6 pixels away from the receive signal, change the text to “Gravit,” and the weight to Regular. Do the same for the battery level indicator, but drag it to the right, with “75%” as the content (figure 10). Remember that you can press Esc to leave text-editing mode. Of course, we could take a premade icon for the battery symbol, but where is the fun in that? Let’s give it a try (figure 11).

28
Figure 10: Add the text layers for the carrier name and the battery level indicator. (View large version29)

Recharge Your Batteries Link

The first element is a simple rectangle (24 × 10) with a white inside border of 0.5 and rounded corners of “1.” (You can add the rounded corners in “Corners” in the “Appearance” section of the Inspector.)

Clone this rectangle with Shift + Command + D (on Windows and Linux, Shift + Control + D), move it to the left and down by 1 pixel with the arrow keys, and change the size so that it’s 2 pixels smaller in each dimension.

Please note that Gravit Designer supports mathematical operations in input fields, so you can use “+5,” for example, to add 5 to the current value, or “*3” to multiply by 3. In our case, enter “24-2” for the “Width” in the Inspector, and “10-2” for the “Height,” and press “Enter” to get to the desired dimensions.

This second shape should have a white fill, without a border. Also clone it, move it to the right so that its left edge touches the right edge of the bordered shape, and change the size to 1.5 × 4. Center it vertically to the other shapes.

The third shape has rounded corners on all sides now, but we only want them on the right side, so we need to enter the “Advanced Settings” on the right. Uncheck “Uniform Corners” so that you can enter “0” for the top-left and bottom-left corner, and 0.5 for the top-right and bottom-right pendants. Select all three rectangles, combine them into a “Battery” group and drag it into the “Status bar.” Make sure that it is 2 grid units (16 pixels) away from the right edge of the page, vertically centered to the status bar, and that the battery level has a gap of 6 pixels to it.

30
Figure 11: The creation of the battery symbol (click to play video31). Note: I’ve disabled the blur effect with Command + E (on Windows and Linux, Control + E) for performance reasons.

Good Vibrations Link

There’s one last thing to manage for the status bar: the Wi-Fi signal indicator (figure 12). We can approach it in two ways. First, a white rectangle. Create one next to the “Gravit” text layer, with a size of 9 × 9 (hold Shift to create a square). Turn it by 45 degrees, either in the Inspector (“Angle” → “R”) or by grabbing the top-most handle on the canvas and holding Shift to constrain the movement to 15-degree steps.

Now we need to convert it to a path (Mac: Shift + Command + P, Windows and Linux: Shift + Control + P, or right-click → “Convert to Path”), so that we are able to manipulate its individual points. Change to the Subselect tool (press D), select the top-most point and click on the second icon at “Joint” in the Inspector. This will convert the former “Straight” point, with no curve, to an evenly rounded “Mirror” point. Increase the curve a bit by dragging out either of the handles to the sides of the point while holding Shift (to keep the movement horizontal), and move it 3 pixels down with the keyboard. Goal accomplished!

Note: The difference between the Pointer tool (V) and the Subselect tool (D) is that the former selects entire shapes or layers, while the latter is mainly used to manipulate an individual point or to show more manipulation options.

The second approach for the Wi-Fi icon would be with the Bezigon tool (figure 12). Keep the icon we just created as a reference, but tone it down to an opacity of 40% in the Inspector. Now, enable the Bezigon tool from the “Path” area in the toolbar (or press B) and make a first click at the bottom-most point of the other Wi-Fi symbol. Make another click at the left-most point, then continue to the top-most point, but hold Alt before you click.

This move is especially vital with the Bezigon tool because it creates a curve that automatically adapts to the surrounding points. Continue at the right-most point, but release Alt again, and finish the shape with a click on the first point at the bottom. You can see how a point that was created with an Alt click of the Bezigon tool adapts automatically if you select the top-most point with the Subselect tool (D) and drag it around.

Keep the version of the icon you like, center it vertically to the status bar, and move it away 6 pixels from the “Gravit” text layer. Finally, rename it to “WiFi” before you drag it into the “Status bar” group. With this last step, we’ve finished the status bar and can turn to the contents of the app.

32
Figure 12: The creation of the icon for the Wi-Fi signal — first, with a rectangle as the base, then with the help of the Bezigon tool. Note: I’ve created a dark shape in the back to increase visibility. (Click to play video33.)

The first element here is the current date (“Friday, Jun 15”), a white text layer with a size of 18 pixels and a “Regular” weight (figure 13). Zoom out to 100% again with Command + 0 (on Windows and Linux, Control + 0), so that the placement becomes easier. Center the text layer to the page and place it on a grid line, about 36 pixels away from the status bar. Hold Alt and drag it to the bottom to create another text layer for the location. Double-click so that you can change it to “Berlin”; for the text size, choose “38.” It should also sit on a grid line right below the date and be centered to the page.

The final text layer we need now is for the temperature (“21 °C”). Proceed as before, but for the font size, you can simply add “*2” to the current value of the input field and press Enter, which will double the size. It should be about 28 pixels away from the other layer.

34
Figure 13: Add three text layers for the date, location and temperature. They should be centered and aligned to the grid. (View large version35)

Conclusion Link

With this ends the first part of the tutorial. I hope you have enjoyed it so far and that it has given you valuable insight into Gravit Designer, its features and what it can do.

In the second part36, we will look at some more sophisticated techniques, see how we can make the weather icons to create a version of the app with sunny weather, and learn how to export the final design.

If you have questions regarding this tutorial, please leave a comment below and I will gladly help you. And if you have ideas on how Gravit Designer could be further improved, don’t hesitate to reach out to the Gravit team on Twitter37 or on Facebook38, or post your questions and ideas in the Gravit discussion board39. Your feedback would be more than welcome!

(mb, al, il)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/sketch-handbook/
  2. 2 https://www.designer.io/
  3. 3 https://www.smashingmagazine.com/2017/03/sketch-figma-showdown/#supported-file-types
  4. 4 http://sketchplugins.com/d/87-new-file-format-in-sketch-43
  5. 5 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig1-Gravit-Design-Tutorial-large-opt.png
  6. 6 https://www.smashingmagazine.com/2017/08/introduction-gravit-designer-designing-weather-app-part-2/
  7. 7 https://gravit.io/team/
  8. 8 http://provide.smashingmagazine.com/weather-app.gvdesign
  9. 9 https://www.smashingmagazine.com/2017/04/photoshop-illustrator-sketch-ui/
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2017/08/p1-fig2-Gravit-Design-Tutorial-large-opt.png
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2017/08/p1-fig2-Gravit-Design-Tutorial-large-opt.png
  12. 12 https://www.dropbox.com/s/yshkffl0vshwe9b/weather-app.gvdesign?dl=0
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig3-Gravit-Design-Tutorial-large-opt.png
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig3-Gravit-Design-Tutorial-large-opt.png
  15. 15 https://medium.com/@christian.krammer/welcome-to-the-gravit-cloud-c30f84a7eb1f
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig4-Gravit-Design-Tutorial-large-opt.png
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig4-Gravit-Design-Tutorial-large-opt.png
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig5-Gravit-Design-Tutorial-large-opt.png
  19. 19 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig5-Gravit-Design-Tutorial-large-opt.png
  20. 20 https://vimeo.com/230680778
  21. 21 https://vimeo.com/230680778
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig7-Gravit-Design-Tutorial-large-opt.png
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig7-Gravit-Design-Tutorial-large-opt.png
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig8-Gravit-Design-Tutorial-large-opt.png
  25. 25 https://www.smashingmagazine.com/wp-content/uploads/2017/08/fig8-Gravit-Design-Tutorial-large-opt.png
  26. 26 https://vimeo.com/230680788
  27. 27 https://vimeo.com/230680788
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2017/08/p1-fig10-Gravit-Design-Tutorial-large-opt.png
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2017/08/p1-fig10-Gravit-Design-Tutorial-large-opt.png
  30. 30 https://vimeo.com/230680819
  31. 31 https://vimeo.com/230680819
  32. 32 https://vimeo.com/230680836
  33. 33 https://vimeo.com/230680836
  34. 34 https://www.smashingmagazine.com/wp-content/uploads/2017/08/p1-fig13-Gravit-Design-Tutorial-large-opt.png
  35. 35 https://www.smashingmagazine.com/wp-content/uploads/2017/08/p1-fig13-Gravit-Design-Tutorial-large-opt.png
  36. 36 https://www.smashingmagazine.com/2017/08/introduction-gravit-designer-designing-weather-app-part-2/
  37. 37 https://twitter.com/gravitdesigner
  38. 38 https://www.facebook.com/GravitDesigner/
  39. 39 https://discuss.gravit.io/

↑ Back to topTweet itShare on Facebook

UX Meets MBA: What Happens When A Designer Goes To Business School

UX Meets MBA: What Happens When A Designer Goes To Business School

If great design can imbue customers with trust, why are designers so removed from product management and the larger business strategy? As a VP of UX with an MBA, I strive to bring both worlds together to create a new model in which user experience and design align with overall business strategy and company vision to drive increased revenue and customer engagement.

1
I formulated a hypothesis: If I were educated in core business skills, I could shift myself (and design teams) from a service to a highly strategic functional asset, driving larger organizational direction. (View large version2)

A Seat At The Table Link

As the Internet became commercially viable, “first to market” generally prevailed as a dominant corporate strategy. However, as technology has become more open and reusable, product differentiation is now a proven strategic blueprint. This tectonic shift has been a boon for the design discipline. Consequently, design has gotten the proverbial “seat at the table” and is now expected to be a driving, strategic function.

For designers, this is a celebrated, exciting advancement, yet it has also exposed a severe skills gap. Specifically, design leaders are being thrust into overarching, cross-functional executive positions, with little to no formal training in business or strategy skills.

Consider the context: Most BFA and MFA programs don’t cover traditional business skills, and companies certainly aren’t investing in cross-functional training for creative professionals. The resulting condition is tragic: Design teams and leaders are not set up for success and, subsequently, are unable to deliver, thus relegating the collective back to a service function.

I’ve experienced this first-hand. I unexpectedly found myself in boardrooms and strategy sessions armed with nothing more than Photoshop and front-end programming competencies. I knew the value of design work but simply couldn’t articulate it in a convincing and relatable form to a corporate audience.

Communicating Design Decisions To Clients Link

Designers like to pride themselves on an extensive portfolio, while business folks like to see numbers. With no doubt, speaking in a language the client understands is key to good communication in any business. Read more →3

Designer Goes To Business School Link

Out of frustration, I formulated a hypothesis: If I were educated in core business skills, I could shift myself (and design teams) from a service to a highly strategic functional asset, driving larger organizational direction.

Very soon, I found a workable solution: a part-time MBA program where I would study and learn actionable skills of business frameworks and best practices of management. So, for just over three years, I was a senior user experience designer by day and an MBA student by night.

Though I studied many illuminating topics (economics, financial accounting, business law, supply-chain management, corporate ethics) as they relate to design, three particular areas of study were highly impactful: statistical analysis, competitive strategy and organizational management. These subjects were most impactful because, to be candid, I had never studied or considered them at depth professionally. Yet, the more I learned, the greater the impact these courses had on my professional development and approach to design.

Description of the image.4
For just over three years, I was a senior user experience designer by day and an MBA student by night. Armed with this new statistical skill set, I was able to incorporate business thinking as an early step in my design process. (View large version5)

A Bit Of Math Goes A Long Way Link

When it came to statistical analysis, as a creative professional, I had an adverse physical reaction to the very idea of spending four months pouring over Excel spreadsheets. In fact, I had done just about everything possible to avoid “math” during my academic and professional career. I was guilty, like so many, of being stuck in the construct of a left-brain and right-brain duality.

It was surprising to me that my first weeks in statistics had very little to do with mathematical calculations, but rather, with theory6. I learned that statistics actually rest upon a singular premise: ratios. If you boil down ratios to their core, it’s basic: X &div; Y = Z. Simply, you take two forces, stack them against each other, and you achieve an output that is influenced against both forces.

Surprisingly, as a designer, the concepts and application of ratios were very familiar to me. I had comfortably worked with ratios in everyday design tasks (grids, padding, aspect ratios) throughout my career.

As I progressed through the course, week after week, I waded through increasingly complex financial models that leverage statistics. Over time, this repetition built up a muscle, and without even thinking about it, I found myself toying with basic statistical models to help guide my design decisions.

Normally, as a designer, I’d go through my design process (competitive auditing, high-level concepts, interactive wireframes, visual design, usability testing), and leave it to the business unit to figure out the impact on our company and users. Armed with this new statistical skill set, I was able to incorporate business thinking in my design process as an early step.

A Quick Example Link

Let’s consider a simple redesign of a home page. For many designers, this can be very challenging because there are so many competing priorities: search functionality, email registration, illustration of the brand’s value, testimonials, etc.

Prior to using statistical analysis, I’d just try to find a design that represented a compromise for all use cases and moved on. Now, I’ve been able to step back and use statistics to help prioritize my layout. Rather than “just” designing a variant or two, I’m able to provide a thoughtful overview of the revenue impact correlated to my design decisions.

Let’s take a hypothetical example. In a first pass of a design, the layout would prioritize email registration as the primary action for a user. Consequently, this would have the immediate impact of fewer orders. Using standard Google Analytics, I was able to show the potential revenue ripple effects of that approach.

Conversely, for a second pass at the design, my layout would feature a search bar. Of course, this would lead to a decrease in email registrations but would also lift the number of immediate orders, as well as conversions (users would convert better because they found more relevant results).

Description of the image.7
Once I was able to build this sort of analysis into my design practice, more and more of my initiatives got investment. (View large version8)

This is a basic application of a statistical model, but as it scales, it becomes even more powerful for larger design initiatives (launch of an app, new product offering, new checkout page, e-commerce feature, brand campaign). What’s more, the model becomes more specific and predictive the more it’s used.

As I progressed, I was able to genuinely factor in cost reduction9 as a critical variable into my models. Consider a chatbot that can easily answer questions for a customer; that feature cuts down on call-center operations, thus reducing a cost driver to the business. Or consider an engaging feed, constantly being populated by fresh content; this boosts organic repeat visits, reducing pricey SEO spend. Of course, raw revenue generation will always be a key driver for business, but as designers, our work actually has a profound impact on cost reduction for the company. This type of analysis gave financial credibility to design-led projects that would have previously been considered “non-revenue generating.”

In all, once I was able to build this sort of analysis into my design practice, more and more of my initiatives got investment. It became formulaic. I would not only present a jaw-dropping, visually striking design prototype that solved actual customer problems, but would also offer precise measurement and financial gains (or savings) to the company.

Build Your Moat Link

Even armed with statistical analysis, I still struggled with the ask to be more “strategic.” But, to be honest, I had no idea what that really meant. How does one actually be strategic? Is it planning? Is it innovation?

In my study of competitive strategies, I read extensively about strategic frameworks to help guide decision-making. In particular, we spent a great deal of time understanding the work of Michael Porter, who is basically the Jony Ive of business thinking.

Porter constructed a simple yet far-reaching structure to guide corporate decision-making (The Economist has a good summary10). It all rests on the premise of achieving an enduring advantage over your competitors (Warren Buffett calls it the moat).11

To summarize, Porter defines the two ways in which an organization can achieve competitive advantage over its rivals: cost advantage and differentiation advantage. In short, to stand apart, you can either have a very different offering or win on price. (Mind Tools has more on this12.) If executed correctly, the business will have achieved a competitive advantage over its competitors.

SSTK Editor13
Differentiation is a strong strategic approach, as opposed to cost leadership. We identified a pain point and a product for an emerging customer segment. (View large version14)

Today at Shutterstock, we certainly offer exceptional content at competitive prices, but many in the industry offer similar products. Using Porter’s model, we knew that differentiation would be a strong strategic approach, as opposed to cost leadership. Aligned with traditional user experience and product strategy, we identified a pain point for an emerging customer segment. Customers want to be able to quickly edit and design off our images without leaving the website. From there, our integrated editor15 tool was born. As it moved from beta to production, we have emerged with a highly differentiated experience for a new customer segment.

Porter’s model is powerful for larger-scale strategic initiatives, but is equally important for feature development. How often have we seen decision-makers deploy a strategy to merely copy existing functionality (see Instagram and Snapchat)? To this, Porter would say, “… bad strategy simply ignores competitors; average companies copy; and winning companies lead their competitors.”

From a design standpoint, articulating the flawed logic of replication becomes simple and powerful. A series of designs showing our product changes to be benchmarked to company B’s advantage showed the futility of the effort and how differentiation would never be achieved. In contrast, a differentiated product (alongside a statistical modeling) can clearly illustrate that the optimal path allows for both differentiation and long-term revenue gain.

Management Is Highly Underrated Link

Designers are natural optimists. Where others see disorganization, designers see the prospect of beauty. Where others wish to cut corners, designers take pride in completeness and quality. Moreover, designers are problem solvers, collaborators and, yes, a bit eccentric, too! We are the people who are wanted — who are needed — to be constant, positive creative, cultural and strategic forces within companies.

However, I would argue that while we can be epicenters of culture and innovation, our discipline hasn’t devoted much attention to successful management of our organizations. Far too often, we manage work, not the individual or the collective.

A bad system will beat a good person everytime.16
Design hasn’t devoted much attention to successful management of our organizations. Far too often, we manage work, not the individual or the collective. (View large version17)

For me, a breakthrough in thinking about how to structure design departments was found in the work of Edward Deming18, often referred to as the father of quality.

Deming, an academic who was brought to Japan in the 1950s following World War II, is credited with being a leading figure in post-war Japan’s economic rise. Deming based his entire business philosophy on an ideal of cooperation and complete employee fulfillment. Much of his experience and life work were codified in his brilliant 14 points19.

To me, these 14 points are an exact blueprint for how to build and scale a thriving design organization. I encourage every reader to share these with their teams and to ask for a grade on each point. I promise that you’ll find immediate areas of opportunity. If you commit to the changes, you will have all the guidance needed to build a connected, high-morale and thriving organization.

I would like to leave you with Deming’s final point, point 14: “Put everybody in the company to work to accomplish the transformation. The transformation is everybody’s job.”

To me, this point — and my entire MBA experience — reaffirmed that the foundation of design thinking, customer empathy and long-term vision is, in fact, the foundation of an enduring corporate strategy. Far too often in today’s economy, strategy is subject to the whims of short-term gains, which, over time, comes back to haunt company and consumer alike. Or, inversely, as the adage goes, if you solve your customer’s problems, they’ll solve your business problems.

I’ll end with this: Invest in yourself. Invest in learning new skills. Invest in your design team. When you do, you’ll see great returns for yourself, the team, the customer and the business.

Suggested Resources Link

(cc, al, il)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/wp-content/uploads/2017/07/UX-meets-MBA-image_1-large-opt.jpg
  2. 2 https://www.smashingmagazine.com/wp-content/uploads/2017/07/UX-meets-MBA-image_1-large-opt.jpg
  3. 3 https://www.smashingmagazine.com/2008/07/how-to-communicate-design-decisions-to-clients/
  4. 4 https://www.smashingmagazine.com/wp-content/uploads/2017/07/UX-meets-MBA-mba-schedule-large-opt.png
  5. 5 https://www.smashingmagazine.com/wp-content/uploads/2017/07/UX-meets-MBA-mba-schedule-large-opt.png
  6. 6 https://www.khanacademy.org/math/statistics-probability
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2017/07/UX-meets-MBA-ux-roi-large-opt.png
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2017/07/UX-meets-MBA-ux-roi-large-opt.png
  9. 9 https://hbr.org/2011/09/achieving-sustained-cost-reduc
  10. 10 http://www.economist.com/node/11869910
  11. 11 http://www.investopedia.com/ask/answers/05/economicmoat.asp
  12. 12 https://www.mindtools.com/pages/article/newTMC_08.htm
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2017/07/UX-meets-MBA-sstk_editor-large-opt.png
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2017/07/UX-meets-MBA-sstk_editor-large-opt.png
  15. 15 https://www.shutterstock.com/editor
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2017/07/UX-meets-MBA-demming-large-opt.png
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2017/07/UX-meets-MBA-demming-large-opt.png
  18. 18 https://www.youtube.com/watch?v=GHvnIm9UEoQ
  19. 19 https://deming.org/explore/fourteen-points
  20. 20 https://www.youtube.com/watch?v=oTugjssqOT0&t=2244s
  21. 21 https://www.khanacademy.org/math/statistics-probability
  22. 22 https://www.amazon.com/Why-Women-Should-Rule-World/dp/0061140414
  23. 23 https://www.youtube.com/watch?v=ehMAwIHGN0Y
  24. 24 https://www.amazon.com/Competitive-Strategy-Techniques-Industries-Competitors-ebook/dp/B001CB34J0/ref=mt_kindle?_encoding=UTF8&me=
  25. 25 https://www.amazon.com/Good-Great-Companies-Collins-Hardcover/dp/B00MXCC72W/ref=sr_1_2?ie=UTF8&qid=1496667154&sr=8-2&keywords=good+to+great
  26. 26 https://www.amazon.com/Go-Giver-Expanded-Little-Powerful-Business/dp/1591848288
  27. 27 https://www.amazon.com/Effective-Executive-Definitive-Harperbusiness-Essentials/dp/0060833459

↑ Back to topTweet itShare on Facebook

How To Create A Sketch Plugin With Front-End Technologies

How To Create A Sketch Plugin With Front-End Technologies

UX design hasn’t been the same since Sketch arrived on the scene. The app has delivered a robust design platform with a refreshing, simple user interface. A good product on its own, it achieved critical success by being extended with community plugins.

The open nature of the Sketch plugin system means that anyone can identify a need, write a plugin and share it with the community. A major barrier is stopping those eager to take part: Designers and front-end developers must learn how to write a plugin. Unfortunately, Objective-C is difficult to learn!

What if users could write plugins using technologies they are already familiar with? This tutorial covers the usage of WebView technology to create a plugin using HTML, CSS and JavaScript.

Making Use Of Symbols In Sketch Link

It’s a fact: Sketch can help you keep your files organized and even helps you save a lot of time in the long run. Read more →1

What You Will Learn Link

This introduction to Sketch development teaches you by creating a sample plugin. This plugin is dubbed “Symbol Export.” It’s a simple tool to export document symbols to image files. A mockup of what you’ll create is below.

42
A mockup of the Sketch plugin you will create

For the purpose of learning, the end product won’t be aesthetically pleasing. The demo will be simplistic, but you are encouraged to spice it up with your own HTML, CSS and JavaScript.

Be warned: While the tutorial leans heavily on front-end technologies to reduce the learning barrier, some Objective-C and Cocoa concepts must still be learned.

Let’s get started!

Architecting With WebViews Link

Sketch plugins are typically created using Objective-C and CocoaScript. These technologies can be confusing, and often downright frustrating, to learn for beginners. So, although developers must still know the basics to create a plugin, the difficulty will be mitigated by using WebViews.

What’s A WebView? Link

Simply put, a WebView is a web browser. With WebView, instead of learning how to create layouts in Objective-C, you can use JavaScript, HTML and CSS. Much like a real browser, developers also get access to the powerful developer console to troubleshoot and prototype with.

You might already be familiar with WebViews in hybrid app development! The concept is the same: Barriers are removed through the use of technologies that developers are already familiar with. We will lean heavily on the WebView to meet all interface requirements.

Plugin Architecture Link

Think of Sketch and the WebView as two separate entities. Sketch provides data to the interface, monitoring for events, and any system-level logic such as reading and writing to files. The WebView is responsible for rendering the interface and communicating events back to Sketch.

Infographic: webview and sketch architecture3
Sketch and WebView architecture

Sketch Plugin Setup Link

For this tutorial, we will create a Sketch plugin that lets designers export all document symbols as images. When a user presses a shortcut, they will see an interface showing all symbols to export. Clicking on an “Export” button will perform the export and close the plugin’s interface.

42
A mockup of the Sketch plugin you will create

For the purpose of education, the result won’t be as stylish as the screenshot above. The functionality will be the same, however.

Create Plugin’s Basic Structure Link

Sketch plugins are bundles of files set up as macOS bundles. Similar to a ZIP archive, a bundle appears as a single file but is actually made up of many. Let’s create our Sketch bundle now.

// Go to your Sketch plugins folder. // Replace {{User}} below with your Mac user name cd /Users/{{User}}/Library/Application Support/com.bohemiancoding.sketch3/Plugins/ // Create the folder with the .sketchplugin suffix mkdir SymbolExport.sketchplugin 

You may now open the folder you just created with your favorite text editor. You may also consider adding a shortcut to this folder on your desktop for quick access.

Recreate the following file tree:

The file structure of a basic Sketch plugin5
The file structure of a basic Sketch plugin
  • Contents

    Contains all plugin files.

    • Resources

      May contain images, fonts and other assets.
    • Sketch

      Contains the plugin’s code.

      • Manifest.json

        Meta data for the plugin, similar to package.json for npm.
      • app.cocoascript

        The file to run when the plugin is activated.

At a bare minimum, every Sketch plugin requires a manifest.json file and a file to call when the plugin is initiated. Beyond these requirements, any directory or file structure may be used.

A Simple Plugin Demonstration Link

First, let’s tell Sketch about our SymbolExporter plugin.

{ "name" : "Symbol Exporter", "identifier" : "yourname.symbolexporter", "version" : "1.0.0", "description" : "An interface for exporting all document Symbols as images.", "authorEmail" : "youremail@example.com", "author" : "Your Name", "commands" : [ { "script" : "app.cocoascript", "handler" : "onRun", "shortcut" : "ctrl alt q", "name" : "Export All Symbols", "identifier" : "show-symbol-exporter-ui" } ], 

Fill out meta data above to reflect your name and email address. Pay special attention to the commands array: This is where we tell Sketch the file and function to run and which shortcut to respond to.

Next, create app.cocoascript with the contents below:

/** * onRun * * Bootstraps the Sketch plugin when the user calls the plugin. * This method runs every time the plugin shortcut or menu item is fired. * * @param {object} context A generic object Sketch provides with information on the currently running Sketch instance. */ function onRun(context) { context.document.displayMessage('Hello there!'); } 

Time for testing! Create a new Sketch project to see our hard work in action. You can initiate your plugin with the shortcut or by looking under the “Plugins” menu option. If all went well, you should see the message “Hello there!” at the bottom of your Sketch window each time the plugin is called.

A working Sketch plugin demo8
A simple functioning Sketch plugin (View large version9)

A Primer On Sketch, Objective-C And CocoaScript Link

To be effective in creating a Sketch plugin, a developer must know the system APIs available for accessing user data. First, a short history lesson.

Objective-C was released in the 1980s as a general-purpose programming language. It’s since been used to create full-fledged applications for Apple products. Being an older language, Objective-C isn’t as intuitive as more modern ones.

Cocoa is a framework created to make working with Objective-C easier. Think of it as a library of APIs that streamline actions in Objective-C. You can often recognize Cocoa code by the NS naming convention: NSString, NSObject, NSWindow and others. This comes from its original name, NextStep.

CocoaScript is a bridge between JavaScript and Cocoa. It allows for scripting in Cocoa without needing to know as much of the language. CocoaScript simplifies the process of Objective-C development but is not a complete abstraction: Developers must still be aware of Cocoa APIs to create a Sketch plugin.

You can see an example of CocoaScript below. Don’t worry: If this is slightly confusing, that’s all right. Picking up small bits of Cocoa and CocoaScript will happen naturally as we create the Sketch plugin.

/** * Example of Objective-C/Cocoa and CocoaScript in action * * Saves a JavaScript object as a json file */ // A JavaScript object turned into a JSON string var userConfigToSave = JSON.stringify({ name: 'John Doe' }); // Convert the JavaScript string to a Cocoa string (note NS prefix) var userConfigNSString = [NSString stringWithFormat: "%@", userConfigToSave]; // The path to save the file to var savePath = '/path/to/userConfig.json'; // A Cocoa system call to save the file [userConfigNSString writeToFile:savePath atomically:true encoding:NSUTF8StringEncoding error:nil]; 

A More Organized Plugin Structure Link

Before going further, let’s make our plugin’s structure easier to understand.

Organized File Dependencies With Imports Link

Our main plugin class will eventually have many JavaScript methods. Understanding the flow of the application will be easier if the logic is moved to a separate file. Change the contents of app.cocoascript to the contents below:

@import 'app/SketchPlugin.cocoascript'; /** * @type {SketchPlugin} The Sketch plugin app class. */ var plugin = new SketchPlugin(); /** * onRun * * Bootstraps the Sketch plugin when the user calls the plugin. * This method runs every time the plugin shortcut or menu item is fired. * * @param {object} context A generic object Sketch provides with information on the currently running Sketch instance. */ function onRun(context) { plugin.init(context); } 

For the rest of development, our app.cocoascript file will stay the same. Its only responsibility is to load the SketchPlugin class, initialize it and then run it when the user calls the plugin.

Note the context parameter. This is a plain JavaScript object containing information on the currently running Sketch instance. It’s used to get file path information, user settings and other meta data.

On line 1, an import call is made to an uncreated file. Now, create the app folder and the SketchPlugin.cocoascript file inside it. Your directory structure should match what is below.

Add the app folder12
The new directory structure

Add the code below to the SketchPlugin class created. The code represents a skeleton class; it doesn’t do anything useful quite yet.

/** * SketchPlugin Class * * Manages CocoaScript code for our plugin. * * @constructor */ function SketchPlugin() { // The Sketch context this.context = {}; } /** * Init * * Sets the current app and plugin context, then renders the plugin. * * @param {object} sketchContext An object provided by Sketch with information on the currently running app and plugin. * @returns {SketchPlugin} */ SketchPlugin.prototype.init = function(context) { this.context = context; return this; } 

Great! We now have a tidy class to handle our plugin’s code. On to the interface!

Create The Interface Link

Rendering the WebView is a simple three-step process. Create a containing window, create a frame for the WebView and, finally, have the WebView load an HTML file.

The WebView rendering process15
The WebView rendering process

Create The Window Link

A window in Cocoa is an NSWindow object. The window will be used as a container for the WebView and its frame. See the annotated code below for a new method to add to the SketchPlugin class.

SketchPlugin.prototype.init = function(context) { this.context = context; // Create a window this.createWindow(); // Blastoff! Run the plugin. [NSApp run]; return this; } /** * Create Window * * Creates an [NSWindow] object to hold a WebView in. */ SketchPlugin.prototype.createWindow = function() { this.window = [[[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 800, 800) styleMask:NSTitledWindowMask | NSClosableWindowMask backing:NSBackingStoreBuffered defer:false ] autorelease]; this.window.center(); this.window.makeKeyAndOrderFront_(this.window); return this; }; 

The new createWindow method introduces the NSWindow Cocoa object. With it, we are able to create a window with many different options. Some of those are worth explaining because the methods aren’t entirely obvious.

[[[NSWindow alloc] creates an NSWindow object. An important property here is alloc, which allocates memory to the window. Without it, we couldn’t interact with the window.

JavaScript developers might be unfamiliar with memory management. In JavaScript, a “garbage collector” automatically releases objects in memory that are not in use. Unfortunately, a little extra leg work is required for Objective-C.

Think of alloc as telling the system, “Please keep this object around. I’m not done using it.” And after, it follows up with, “I’m done with this object. Please free the memory space it was using.”

So, when do you explicitly allocate memory to an object? For most actions in CocoaScript, this will only be required for window objects that you want to keep around. For now, you only need to be familiar with the concept.

initWithContentRect:NSMakeRect(0, 0, 800, 800) creates the window with the specified position and height. NSMakeRect‘s parameters are set as x, y, width, height.

X and Y values are ignored here because we’re calling this.window.center() below it, which automatically sets these values for us.

styleMask:NSTitledWindowMask | NSClosableWindowMask sets the style of the window. It’s possible to set whether or not a user can close the window, to set a window title and to set other style options.

For this project, we will use a title bar and allow the user to close the window. Note that we have not declared support for resizing the window or minimizing it.

See Apple’s NSWindow documentation5118 for the plethora of styling options available for windows.

backing:NSBackingStoreBuffered defer:false are two options that specify how the window is rendered. defer:false says we want to create the window object now, not later. And the backing type specifies how the window contents are drawn in memory. Always use NSBackingStoreBuffered, which specifies that a memory buffer should be used. That’s what the system is optimized for, and it is the most performant.

] autorelease]; states that the window object should be cleared from memory when it’s closed (remember when we used alloc?). Recall that memory management is important in Cocoa and Objective-C. If objects are not released after being used, the app might crash from a lack of memory. This unfortunate scenario is referred to as a memory leak.

this.window.center(); this.window.makeKeyAndOrderFront_(this.window);

centers the window and also makes it the key window.

A “key window” is the window that responds to key events. Think of it as the active window.

In addition to adding this method, review the init method: We’ve called createWindow and also added a call to [NSApp run], which launches our window.

Now, review the changes made to the init method. A createWindow call was added, as well as the [NSApp run] line. The call to NSApp runs our plugin and starts listening to events. The plugin does not stop until NSApp receives a message to terminate. In this case, the run command shows the window; clicking the close button on the window sends the “terminate!” message and releases our plugin from memory.

Create The WebView Link

We’ve created a window. Now let’s create a WebView frame and specify the HTML file to load.

Similar to the previous step, a new method is added createWebView, as well as a call to it in the init method.

/** * Create WebView * * Creates a [WebView] object and loads it with content. */ SketchPlugin.prototype.createWebView = function() { // create frame for loading content in var webviewFrame = NSMakeRect(0, 0, 800, 800); // Request index.html var webviewFolder = this.context.scriptPath.stringByDeletingLastPathComponent() + '/app/webview/'; var webviewHtmlFile = webviewFolder + 'index.html'; var requestUrl = [NSURL fileURLWithPath:webviewHtmlFile]; var urlRequest = [NSMutableURLRequest requestWithURL:requestUrl]; // Create the WebView, frame, and set content this.webView = WebView.new(); this.webView.initWithFrame(webviewFrame); this.webView.mainFrame().loadRequest(urlRequest); this.window.contentView().addSubview(this.webView); return this; }; 

It’s worth pointing out line 17 as an alternative CocoaScript syntax — it certainly feels more like JavaScript! The style is often a matter personal preference, but being familiar with both forms will help you read the code of others.

We could just as easily have written the following code instead:

[[webView webviewFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:webviewhtmlFile]]] 

Don’t feel you need to know the names of objects, the methods or the syntax. For now, we only need to know that the WebView is working. Resources to learn more are listed at the end of this article.

Remember to add the call to createWebView in the init method. It should get called after the window is created:

// Create a window this.createWindow(); // Create a WebView this.createWebView(); 

Create the HTML Layout

If you peeked at the previous code closely, then you saw reference to an HTML file that doesn’t yet exist. Create a webview folder and an index file now.

Directory structure for the WebView21
Current directory structure for the WebView layout
<!doctype html> <html> <head> <style> html { width: 100%; height: 100%; background: cornflowerblue; } </style> </head> <body> Hello there! </body> </html> 

Now, calling the plugin from Sketch produces a field of welcoming cornflowers:

A basic WebView template24
The basic WebView template

Communication Between Sketch And WebViews Link

So far, we have a working WebView to use as an interface but no data to fill it with. Next, let’s see how to communicate data between Sketch and the WebView.

Sending Sketch Symbol Data to the WebView Link

This plugin will render a list of symbol data for previewing before exporting. To do that, we need to get the data from Sketch and then communicate it to the WebView.

Several options exist to communicate a large amount of data to a WebView. Keep in mind that it’s a requirement that the end user thinks the WebView is a native application, which is to say that all data should load instantaneously. The easiest means of meeting this requirement is by precompiling symbol data to a file before loading the request, then including the data as a JavaScript script.

Sketch and WebView Communication Diagram25
Communication of data between Sketch and WebView

Other options for communicating data do exist. One way is to set JavaScript variables through CocoaScript once the WebView loads. Unfortunately, this does add a slight lag, thus failing our requirement for a native-like experience.

How to Fetch Sketch Symbol Data

The first step is to grab all symbol data from Sketch. Add the following method to your file:

/** * Get All Document Symbols * * Gets every symbol in the document (in all pages, artboards, etc) * * @returns {Array} An array of MSSymbolMaster objects. */ SketchPlugin.prototype.getAllDocumentSymbols = function() { var pages = this.context.document.pages(); var symbols = []; // Loop through all pages for (var i = 0; i < pages.count(); i++) { var page = pages.objectAtIndex(i); // Loop through all artboard layers for (var k = 0; k < page.layers().count(); k++) { var layer = page.layers().objectAtIndex(k); if ('MSSymbolMaster' == layer.class()) { symbols.push(layer); } } } return symbols; } 

Sketch has many helper methods to access data in the current document. Sometimes, developers will need to do some heavy lifting, as is the case here. No helper method exists to grab all master symbols data in all pages. As a result, we must loop through data that Sketch does provide in order to find what we need.

It’s worth noting the check for MSSymbolMaster on line 20. This differs from a symbol instance in that the master is what each instance references as the original copy. If, instead, we checked for any symbol type, we would have duplicates!

Methods such as context.document.pages() and type definitions such as MSSymbolMaster are detailed in Sketch’s documentation28. Often you may find Sketch’s documentation lacking. More resources for finding what you need are included at the end of this tutorial.

Create the JavaScript File for Storing Symbols Data

Following the illustration, this step requires that we create a JavaScript file and fill it with symbol data. Add the following method to your plugin file:

/** * Create Symbols JavaScript File * * Creates a JavaScript file representing all document master symbols. * This data is consumed by the WebView for rendering symbol information. * * Generated file path: * Contents/Sketch/app/webview/symbolData.js * * @returns {SketchPlugin} * @method */ SketchPlugin.prototype.createSymbolsJavaScriptFile = function() { /** * Build the content for the JavaScript file */ var webviewSymbols = []; this.documentSymbols = this.getAllDocumentSymbols(); // Push all document symbols to an array of symbol objects for (var i = 0; i < this.documentSymbols.length; i++) { var symbol = this.documentSymbols[i]; webviewSymbols.push({ name: '' + symbol.name(), symbolId: '' + symbol.symbolID(), symbolIndex: i }); } /** * Create The JavaScript File, then fill it with symbol data */ var jsContent = 'var symbolData = ' + JSON.stringify(webviewSymbols) + ';'; var jsContentNSSString = [NSString stringWithFormat:"%@", jsContent]; var jsContentFilePath = this.context.scriptPath.stringByDeletingLastPathComponent() + '/app/webview/symbolData.js'; [jsContentNSSString writeToFile:jsContentFilePath atomically:true encoding:NSUTF8StringEncoding error:nil]; return this; }; 

The method loops through all document symbols, creates a new array of objects and then saves to the file path specified. Let’s review two items that could use more explanation.

webviewSymbols.push({ name: '' + symbol.name(), 

This code sample is an example of where JavaScript and Cocoa sometimes clash types. The return value of symbol.name() is a Cocoa object. Without casting to a JavaScript string, nothing at all would be assigned to name!

The '' + [Object] line is shorthand for casting the value to a JavaScript string.

You will not get an exception when an unexpected type conversion doesn’t occur. Avoid bugs by being aware of each object type and documenting them in your code.

[jsContentNSSString writeToFile:jsContentFilePath atomically:true encoding:NSUTF8StringEncoding error:nil]; 

This code shows a common means of saving contents to a file. Developers do not always need to understand the underlying methods. Instead, think of some Cocoa code as a code recipe: Use this code as a template and switch out the file path and content value.

Indeed, much of CocoaScript code can be abstracted into a library for large projects.

function saveFile(string, path) { // Cocoa code goes here } 

For larger Sketch plugins, consider adding abstractions like saveFile above into a utility class.

As usual, call the new createSymbolsJavaScriptFile code in the init method. Add it before the WebView is created:

SketchPlugin.prototype.init = function(context) { this.context = context; // Generate symbol data for the webview this.createSymbolsJavaScriptFile(); // Create a window this.createWindow(); // Create a WebView this.createWebView(); 

Running Sketch and calling the plugin now creates the JavaScript data file for us. Give it a shot! If you don’t see any generated, ensure that you have created at least one master symbol object in Sketch.

Communicating Events From the WebView Link

Communicating data to the WebView from Sketch was easy enough. Communicating events from the WebView to Sketch, such as a click event, requires slightly more work.

WebView Design Update

The fun in working with WebViews is that developers have full access to all CSS and JavaScript libraries desired. You should feel right at home in creating the interface. For simplicity’s sake, we won’t include any additional front-end frameworks. Instead, let’s go relive 1995.

A basic exporting interface33
A basic exporting interface
<!doctype html> <html> <head> <script src="symbolData.js"></script> </head> <body> <!-- Header --> <h1>Export All Symbols as Assets</h1> <button>Export Now</button> <hr/> <!-- Symbols List --> <div></div> <script> var symbolListDiv = document.getElementById('symbol-list'); /** * Add all symbol data to the interface */ // Ensure symbols exist if (typeof symbolData !== 'undefined' && true === Array.isArray(symbolData) && symbolData.length) { // Append each symbol as a new div for (var i = 0; i < symbolData.length; i++) { var newDiv = document.createElement('div'); var newDivHdg = document.createElement('h3'); var symbolNameNode = document.createTextNode(symbolData[i].name); newDivHdg.appendChild(symbolNameNode); newDiv.appendChild(newDivHdg); symbolListDiv.appendChild(newDiv); } } else { symbolListDiv.innerText = 'No symbols found!'; } </script> </body> </html> 

Should any design issues arise, recall that you have full access to the “Developer Console.”

Intercepting WebView Events in CocoaScript

With the stunning WebView design in place, it’s time to communicate back to Sketch when the export button is clicked.

The most reliable way to communicate a WebView event is slightly convoluted. The solution is to redirect the URL when a desired event is fired, intercept the request and then run CocoaScript code instead.

Why so confusing? You’d expect better event management in communication to a WebView. However, in CocoaScript, we have limited access to event handlers. No listener for “the user clicked something on the WebView” exists. The solution adopted is possible due to a CocoaScript event that is called any time the WebView changes its URL.

WebView HTTP intercept36
Diagram for intercepting events in the WebView

The WebView event is a simple onclick event on the export button. Add the following to your index.html script section:

/** * Export assets when button is clicked */ var exportBtn = document.getElementById('export'); exportBtn.onclick = function() { window.location.href = 'https://localhost:8080/symbolexport'; } 

Handling Event Listeners in CocoaScript

So far, the word “event” has been used to describe listeners in Objective-C. It’s time to learn about proper terminology: delegates. A “delegate” is an object that acts on another object’s behalf. It can receive messages and specify a callback when a certain message is sent. Put very simply, think of delegates as event listeners and handlers in JavaScript. From here on out, we will use the term “delegate” to refer to events on the Objective-C side.

To intercept the WebView redirect, create a delegate and assign it to the WebView. Add the createWebViewRedirectDelegate method below to your class file.

/** * Create Webview Redirect Delegate * * Creates a Cocoa delegate class, then registers a callback for the redirection event. */ SketchPlugin.prototype.createWebViewRedirectDelegate = function() { /** * Create a Delegate class and register it */ var className = 'MochaJSDelegate_DynamicClass_SymbolUI_WebviewRedirectDelegate' + NSUUID.UUID().UUIDString(); var delegateClassDesc = MOClassDescription.allocateDescriptionForClassWithName_superclass_(className, NSObject); delegateClassDesc.registerClass(); /** * Register the "event" to respond to and specify the callback function */ var redirectEventSelector = NSSelectorFromString('webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:'); delegateClassDesc.addInstanceMethodWithSelector_function_( // The "event" - the WebView is about to redirect soon NSSelectorFromString('webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:'), // The "listener" - a callback function to fire function(sender, URL) { // Ensure its the URL we want to respond to. // You can also fire different methods based on the URL if you have multiple events. if ('https://localhost:8080/symbolexport' != URL) { return; } // A special method to export symbols - we haven't created it yet this.exportAllSymbolsToImages(); }.bind(this) ); // Associate the new delegate to the WebView we already created this.webView.setFrameLoadDelegate_( NSClassFromString(className).new() ); return this; }; 

This is the most complex part of the tutorial for anyone without Objective-C and Cocoa experience. Let’s look at some of the lines and explain further.

 /** * Create a Delegate class and register it */ var className = 'MochaJSDelegate_DynamicClass_SymbolUI_WebviewRedirectDelegate' + NSUUID.UUID().UUIDString(); var delegateClassDesc = MOClassDescription.allocateDescriptionForClassWithName_superclass_(className, NSObject); delegateClassDesc.registerClass(); 

Because we don’t have a simple abstraction to work with delegates, any delegate code will require some basic knowledge of Cocoa.

This code creates a new Cocoa delegate class. It’s important to note that some CocoaScript development involves quirks. On line 48, we see an example of this: Any class name registered through CocoaScript that isn’t unique will crash the application. This appears to be an issue with memory allocation at runtime. The simple solution is to append a unique string at the end of the class name we choose.

As you learn CocoaScript, you might come across some odd workarounds like this:

/** * Register the "event" to respond to and specify the callback function */ var redirectEventSelector = NSSelectorFromString('webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:'); delegateClassDesc.addInstanceMethodWithSelector_function_( // The "event" - the WebView is about to redirect soon NSSelectorFromString('webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:'), // The "listener" - a callback function to fire function(sender, URL) { // Ensure its the URL we want to respond to. // You can also fire different methods based on the URL if you have multiple events. if ('https://localhost:8080/symbolexport' != URL) { return; } // A special method to export symbols - we haven't created it yet this.exportAllSymbolsToImages(); }.bind(this)); // Associate the new delegate to the WebView we already created this.webView.setFrameLoadDelegate_( NSClassFromString(className).new()); 

Think of this code portion as a simple JavaScript event callback — the NSSelectorFromString being the event, and the anonymous function being the callback to run.

In the callback, notice the reference to another method, exportAllSymbols, that is not created just yet — we will create it in the next step.

 // Associate the a new delegate instance to the WebView this.webView.setFrameLoadDelegate_(NSClassFromString(className).new()); 

The setFrameLoadDelegate_ method on our WebView allows us to associate a delegate.

This line creates a new instance of the delegate class, and it tells the WebView we want to use it to intercept events.

Take a deep breath and exhale: The most difficult part is over. Finally, add a call to the method that we just created inside the createWebView function.

 SketchPlugin.prototype.createWebView = function() { ....

// Create the WebView, frame, and set content this.webView = WebView.new(); this.webView.initWithFrame(webviewFrame); this.webView.mainFrame().loadRequest(urlRequest); this.window.contentView().addSubview(this.webView); // Assign a redirect delegate to the WebView this.createWebViewRedirectDelegate(); return this; }

Export All Sketch Symbols as Images

The last step in this tutorial is to export all document symbols as images. Create the final method below.

SketchPlugin.prototype.exportAllSymbolsToImages = function() { /** * Loop through symbols; export each one as a PNG */ for (var i = 0; i < this.documentSymbols.length; i++) { var symbol = this.documentSymbols[i]; // Specify the path and filename to create var filePath = this.context.scriptPath.stringByDeletingLastPathComponent() + '/export/' + symbol.symbolID() + '.png'; // Create preview PNG var slice = [[MSExportRequest exportRequestsFromExportableLayer:symbol] firstObject]; [slice setShouldTrim:1]; [slice setScale:1]; [(this.context.document) saveArtboardOrSlice:slice toFile:filePath]; } // Close the plugin and display a success message this.window.close(); this.context.document.displayMessage('All symbols exported!'); }; 

If all goes well, calling the plugin in Sketch will create the export folder and images for you. You should see the “All symbols exported!” message flash once the operation completes. The file system will look similar to the screenshot below.

Asset export success45
A working asset export!

Go ahead and look at the generated PNG files and bask in the fruits of your hard labor.

Conclusion Link

Congratulations! You’ve created your first Sketch plugin! This foundation should give you the information needed to start making larger, more complex Sketch plugins.

Below are resources to aid you in future Sketch development. Go forth and create the next best Sketch plugin!

Troubleshooting Your Plugin Link

The most effective debugging tool is still careful thought, coupled with judiciously placed print statements.

– Brian Kernighan (Unix for Beginners, 1979)

This tutorial should have guided you well enough that troubleshooting tools were not necessary.

Take time to appreciate Kernighan’s quote. Engineers are spoiled today with great debugging tools. Unfortunately, for Sketch developers, the tool set for debugging a plugin isn’t quite there yet. Debugging often involves placing log calls throughout the plugin to see where the plugin is failing.

One utility class that helps greatly with step debugging is SketchPluginLog46. Using this utility, you are able to print information to the system log or to custom log files. Go through the setup guide and become familiar with logging before starting your next big Sketch plugin.

Sketch Resources Link

Sketch’s “Resources47” page lists resources for each technology involved — even JavaScript! It will provide ongoing education after you’ve reviewed the “Introduction48” for developers. The reference APIs and subsequent pages will help you find more information, but developers will quickly find that the documentation is incomplete.

Given the lack of documentation and books, the Sketch team recommends pouring over open-source plugins. The quality of code varies wildly, as do the solutions to different problems. Learning from the code of established Sketch plugins is recommended. The Plugin Directory49 on GitHub is a good reference of plugins to learn from.

The Sketch team doesn’t appear to respond directly to requests for support with plugin development, and StackOverflow isn’t very active for Sketch topics. Much of the work in plugin development will come from reviewing the code of others.

Objective-C and CocoaScript Resources Link

Both Objective-C and CocoaScript are difficult to use without learning the basics. For intense complex applications, consider purchasing a book on building straight Cocoa applications. Most use cases in plugin development should be solved by GitHub’s code search and by looking at code samples.

Apple has an API reference50 that will frequently come in handy. You can match up some of the calls made in this demo to the NSWindow documentation5118 for reference.

CocoaScript syntax, and how it relates to Cocoa, can sometimes be confusing as well. MagicSketch has an excellent guide on CocoaScript syntax52 to assist with translation.

Looking to the Future Link

What does the landscape look like for creating a Sketch plugin in the future?

Historically, the Sketch team has created some API-breaking changes with major releases. For the most part, the major updates have done well in not breaking plugins, but do keep in mind that you’ll need to test new major versions for each release.

This tutorial should remain effective through new Sketch updates, because it doesn’t touch on internal Sketch APIs to a large degree. This article will be updated for all major updates after version 42.

(rb, vf, yk, al, il)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/2017/04/symbols-sketch/
  2. 2 https://www.smashingmagazine.com/wp-content/uploads/2017/07/img01-mockup-preview-opt.png
  3. 3 https://www.smashingmagazine.com/wp-content/uploads/2017/07/img02-whats-a-webview-preview-opt.png
  4. 4 https://www.smashingmagazine.com/wp-content/uploads/2017/07/img01-mockup-preview-opt.png
  5. 5 https://www.smashingmagazine.com/wp-content/uploads/2017/07/img03-starting-file-tree-preview-opt.png
  6. 6 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/blob/df8ca423e3113a03ac1509c600ae1120457e6677/SymbolExport.sketchplugin/Contents/Sketch/manifest.json
  7. 7 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/blob/df8ca423e3113a03ac1509c600ae1120457e6677/SymbolExport.sketchplugin/Contents/Sketch/app.cocoascript
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2017/07/img04-sketch-plugin-demo-large-opt.png
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2017/07/img04-sketch-plugin-demo-large-opt.png
  10. 10 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/blob/9649aac938bf92095b3ab51c540917d22336a558/SymbolExport.sketchplugin/Contents/Sketch/app.cocoascript
  11. 11 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/commit/9649aac938bf92095b3ab51c540917d22336a558#diff-80aaa979da56224161376ee954a6ebae
  12. 12 https://www.smashingmagazine.com/wp-content/uploads/2017/07/img05-app-file-tree-preview-opt.png
  13. 13 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/blob/9649aac938bf92095b3ab51c540917d22336a558/SymbolExport.sketchplugin/Contents/Sketch/app/SketchPlugin.cocoascript
  14. 14 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/commit/9649aac938bf92095b3ab51c540917d22336a558#diff-8cef7ab71a0b0be12cdca631b5117a69
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2017/07/img06-webview-ui-illustr-preview-opt.png
  16. 16 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/blob/9891d371bf03bd44032f72f8861b8755aec1c936/SymbolExport.sketchplugin/Contents/Sketch/app/SketchPlugin.cocoascript
  17. 17 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/commit/9891d371bf03bd44032f72f8861b8755aec1c936#diff-8cef7ab71a0b0be12cdca631b5117a69
  18. 18 https://developer.apple.com/reference/appkit/nswindow
  19. 19 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/blob/809eeea0fb6a6e2beca2b5316273f7dc969513e1/SymbolExport.sketchplugin/Contents/Sketch/app/SketchPlugin.cocoascript
  20. 20 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/commit/809eeea0fb6a6e2beca2b5316273f7dc969513e1#diff-8cef7ab71a0b0be12cdca631b5117a69
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2017/07/img07-webview-dir-structure-preview-opt.png
  22. 22 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/blob/6885235c5d9b7f013bb8bfaca5b6eceb13611f3e/SymbolExport.sketchplugin/Contents/Sketch/app/webview/index.html
  23. 23 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/commit/6885235c5d9b7f013bb8bfaca5b6eceb13611f3e#diff-3510c28073a509aee8af2fddee057920
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2017/07/img08-cornflower-demo-preview-opt.png
  25. 25 https://www.smashingmagazine.com/wp-content/uploads/2017/07/img09-sketch-webview-data-sync-preview-opt.png
  26. 26 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/blob/8977e5811f005a784d9acfc1ccea4ac40b5dcd13/SymbolExport.sketchplugin/Contents/Sketch/app/SketchPlugin.cocoascript
  27. 27 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/commit/8977e5811f005a784d9acfc1ccea4ac40b5dcd13#diff-8cef7ab71a0b0be12cdca631b5117a69
  28. 28 http://developer.sketchapp.com/
  29. 29 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/blob/8977e5811f005a784d9acfc1ccea4ac40b5dcd13/SymbolExport.sketchplugin/Contents/Sketch/app/SketchPlugin.cocoascript
  30. 30 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/commit/8977e5811f005a784d9acfc1ccea4ac40b5dcd13#diff-8cef7ab71a0b0be12cdca631b5117a69R111
  31. 31 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/blob/8977e5811f005a784d9acfc1ccea4ac40b5dcd13/SymbolExport.sketchplugin/Contents/Sketch/app/SketchPlugin.cocoascript
  32. 32 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/commit/8977e5811f005a784d9acfc1ccea4ac40b5dcd13#diff-8cef7ab71a0b0be12cdca631b5117a69
  33. 33 https://www.smashingmagazine.com/wp-content/uploads/2017/07/img10-basic-export-ui-preview-opt.png
  34. 34 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/blob/3dd89abac992ed105c53174a2032101fd4373b25/SymbolExport.sketchplugin/Contents/Sketch/app/webview/index.html
  35. 35 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/commit/3dd89abac992ed105c53174a2032101fd4373b25#diff-3510c28073a509aee8af2fddee057920
  36. 36 https://www.smashingmagazine.com/wp-content/uploads/2017/07/img11-webview-http-intercept-preview-opt.png
  37. 37 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/blob/525ac3847edb0ea5f9e150958269d6b81732a73d/SymbolExport.sketchplugin/Contents/Sketch/app/webview/index.html
  38. 38 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/commit/525ac3847edb0ea5f9e150958269d6b81732a73d#diff-3510c28073a509aee8af2fddee057920
  39. 39 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/blob/525ac3847edb0ea5f9e150958269d6b81732a73d/SymbolExport.sketchplugin/Contents/Sketch/app/SketchPlugin.cocoascript
  40. 40 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/commit/525ac3847edb0ea5f9e150958269d6b81732a73d#diff-8cef7ab71a0b0be12cdca631b5117a69R156
  41. 41 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/blob/525ac3847edb0ea5f9e150958269d6b81732a73d/SymbolExport.sketchplugin/Contents/Sketch/app/SketchPlugin.cocoascript
  42. 42 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/commit/525ac3847edb0ea5f9e150958269d6b81732a73d#diff-8cef7ab71a0b0be12cdca631b5117a69R79
  43. 43 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/blob/525ac3847edb0ea5f9e150958269d6b81732a73d/SymbolExport.sketchplugin/Contents/Sketch/app/SketchPlugin.cocoascript
  44. 44 https://github.com/sketch-plugin-development/smashing-magazine-sourcecode/commit/525ac3847edb0ea5f9e150958269d6b81732a73d#diff-8cef7ab71a0b0be12cdca631b5117a69R200
  45. 45 https://www.smashingmagazine.com/wp-content/uploads/2017/07/img12-export-success-preview-opt.png
  46. 46 https://github.com/sketch-plugin-development/sketch-plugin-log
  47. 47 http://developer.sketchapp.com/resources/
  48. 48 http://developer.sketchapp.com/introduction/
  49. 49 https://github.com/sketchplugins/plugin-directory
  50. 50 https://developer.apple.com/library/content/navigation/#section=Frameworks&topic=AppKit
  51. 51 https://developer.apple.com/reference/appkit/nswindow
  52. 52 https://blog.magicsketch.io/interacting-with-objective-c-classes-in-cocoascript-68be7f39616f

↑ Back to topTweet itShare on Facebook

Web Development Reading List: Announcing Changes, A Design Kit, DNA Malware, And Why Meaning Is An Advantage

Web Development Reading List: Announcing Changes, A Design Kit, DNA Malware, And Why Meaning Is An Advantage

You might have noticed it already: in the past few weeks you might have missed Anselm’s Web Development Reading List1 issues here on SmashingMag. No worries, from now on, we’ll switch to collecting the most important news of each month in one handy, monthly summary for you. If you’d like to continue reading Anselm’s weekly reading list (and we encourage you to!), you can still do so via email2, on wdrl.info3 or via RSS4. — Editorial Team

Hello again! I’ll continue publishing this resource and am grateful for everyone who supports my ongoing work. And to celebrate the last weekly edition, I found a lot of great articles for you: Biohacking news that sound like science fiction, advances in deep learning with JavaScript, and a lot more. Happy reading!

News Link

  • The upcoming Chrome 615 (in beta channel now) brings support for JavaScript modules, the Payment Request API on desktop, smooth-scrolling in CSS, 8-digit hex colors (with alpha transparency), and the new Expect-CT HTTP header.
  • Edward Thomson shares why you should upgrade your git installation6 to 2.14.1 to fix vulnerabilities.
  • Microsoft will change their Edge rendering engine7, making it independent of and asynchronous to the main thread.
  • This week, Opera announced the end of Opera Max8, their data-saving browser product. The service will still stay active for a while but probably not for too long.

UI/UX Link

11
The macOS Desktop Kit12 includes desktop application and web UI elements a designer could need when building a user flow through a web app or constructing a Mac interface. (Image credit13)

Tooling Link

  • Puppeteer14 is a Node.js library that provides an API to control headless Chrome. It can also be configured to use full (non-headless) Chrome.

Security Link

Web Performance Link

  • Andreya Grzegorzewski explains how we can use the Cache API for offline POST requests17 in Progressive Web Apps. This super cool trick allows us to queue POST requests, such as a form submission/data upload, cache it, and send it to the server once the user is back online.

HTML & SVG Link

  • If you want to use <details>/<summary> elements together with rem font-size values on your site, be aware that there’s a bug in Safari that renders parts of a website with that CSS combination useless. After tracking it down and debugging it, I finally summarized the case18.

Accessibility Link

10 guidelines to improve your web accessibility20
Eva Ferreira shares ten web accessibility guidelines21 to guarantee access to your site to any person, in spite of disabilities. (Image credit22)

JavaScript Link

  • deeplearn.js23 is a hardware-accelerated machine intelligence library for the web. You can use it to build and train neural networks in your browser, to play color sequences or detect objects in images, for example.
  • flatpickr24 is a dependency-free, lightweight and powerful datetime picker.
  • Peter Kröner shares how he achieved immutable arrays and objects in JavaScript in only 33 lines25 (German article, automatically translated) without any library with ECMAScript Proxies.

CSS Link

CodePen Directionally-Aware Hover Only With CSS27
Giana uses :hover and the sibling selector to apply different styles to elements based on their position and, thus, create a CSS-only, directionally-aware hover effect28.

Work & Life Link

Going Beyond… Link

—Anselm

Footnotes Link

  1. 1 https://www.smashingmagazine.com/tag/web-development-reading-list/
  2. 2 https://wdrl.info/
  3. 3 https://wdrl.info/
  4. 4 https://wdrl.info/feed
  5. 5 https://blog.chromium.org/2017/08/chrome-61-beta-javascript-modules.html
  6. 6 https://www.edwardthomson.com/blog/upgrading_git_for_cve2017_1000117.html
  7. 7 https://blogs.windows.com/msedgedev/2017/08/17/making-web-smoother-independent-rendering/
  8. 8 http://blogs.opera.com/mobile/2017/08/upcoming-changes-opera-max/
  9. 9 http://facebook.design/desktopkit
  10. 10 http://facebook.design/ios10
  11. 11 http://facebook.design/desktopkit
  12. 12 http://facebook.design/desktopkit
  13. 13 http://facebook.design/desktopkit
  14. 14 https://github.com/GoogleChrome/puppeteer
  15. 15 https://www.wired.com/story/malware-dna-hack
  16. 16 http://telegra.ph/Why-Isnt-Telegram-End-to-End-Encrypted-by-Default-08-14
  17. 17 https://medium.com/web-on-the-edge/offline-posts-with-progressive-web-apps-fc2dc4ad895
  18. 18 https://colloq.io/blog/safaris-detailssummary-rem-font-size-issue
  19. 19 https://aerolab.co/blog/web-accessibility/
  20. 20 https://aerolab.co/blog/web-accessibility/
  21. 21 https://aerolab.co/blog/web-accessibility/
  22. 22 https://aerolab.co/blog/web-accessibility/
  23. 23 https://pair-code.github.io/deeplearnjs/
  24. 24 https://chmln.github.io/flatpickr/
  25. 25 http://www.microsofttranslator.com/bv.aspx?from=&to=en&a=http%3A%2F%2Fwww.peterkroener.de%2Fimmutable-arrays-und-objekte-fuer-javascript-mit-proxies%2F
  26. 26 https://codepen.io/giana/pen/YZWjQy
  27. 27 https://codepen.io/giana/pen/YZWjQy
  28. 28 https://codepen.io/giana/pen/YZWjQy
  29. 29 https://christianheilmann.com/2017/08/16/taking-a-break-and-so-should-you/
  30. 30 https://shift.newco.co/is-social-media-the-new-tobacco-936d28a2bfe2
  31. 31 https://getpocket.com/explore/item/stop-spending-so-much-time-in-your-head-1381441550
  32. 32 http://thestoryoftelling.com/meaning-advantage/

↑ Back to topTweet itShare on Facebook

User Authentication For Web And iOS Apps With AWS Cognito (Part 1)

User Authentication For Web And iOS Apps With AWS Cognito (Part 1)

Developers and organizations alike are looking for a way to have more agility with mobile solutions. There is a desire to decrease the time from idea to test. As a developer, I often run up against one hurdle that can slow down the initial build of a mobile hypothesis: user management.

Over the years, I have built at least three user management systems from scratch. Much of the approach can be based on a boilerplate, but there are always a few key items that need to be customized for a particular client. This is enough of a concern that an entire category of user management, authentication and authorization services have sprung up to meet this need. Services like Auth01 have entire solutions based on user and identity management that developers can integrate with.

One service that provides this functionality is Amazon Web Services’ (AWS’) Cognito. Cognito is a tool for enabling users to sign up for and sign into web and mobile applications that you create. In addition to this functionality, it also allows for storage of user data offline, and it provides synchronization of this data. As Amazon states, “With Amazon Cognito, you can focus on creating great app experiences instead of worrying about building, securing, and scaling a solution to handle user management, authentication, and sync across devices.”

Underestimating Carousels Link

Carousels don’t really deserve the bad reputation they’ve gained throughout the years. They can prove to be very effective and come in many shapes and sizes. Read more →2

Last year, Amazon introduced an addition to its Cognito service, custom user pools. This functionality now provides what I and other developers need in order to have a complete, customizable, cross-platform user management system, with the flexibility needed to fit most use cases. To understand why, we need to take a quick look at what user management is and what problems it solves.

3
Cognito custom user pool diagram (View large version4)

In this article, we will spend a majority of our time walking through the process of configuring a user pool for our needs. Then, we will integrate this user pool with an iOS application and allow a user to log in and fetch the attributes associated with their user account. By the end, we’ll have a limited demo application, but one that handles the core of user management. In addition, after this is in place, there will be a follow-up article that takes this quite a bit deeper.

What Do We Need From User Management? Link

If you have a mobile or web app, what exactly do you need in terms of user management? While user log-in is probably the first thing you would think of, we cannot stop there. If we want a flexible user management system that would work for most web and mobile app use cases, it would need to have the following functionality:

  • username and password log-in;
  • secure password hashing and storage;
  • password changes;
  • password policy and validation;
  • user lifecycle triggers (welcome email, goodbye email, etc.);
  • user attributes (first name, last name, etc.);
  • required configuration and optional attributes per user;
  • handling of forgotten passwords;
  • phone number validation through SMS;
  • email verification;
  • API access to endpoints based on permissions;
  • secure storage of access token(s) on mobile devices;
  • offline storage of user attributes for mobile devices;
  • synchronization of user attributes for online and offline states;
  • multi-factor authentication.

While user management might at first seem like a log-in system, the functionality must go far beyond that in order for the system to be truly flexible enough to handle most use cases. This clearly goes far beyond just a username and password.

One additional item needs to be called out here: security. One of the requirements of any user management system is that it needs to be continually evaluated for the security of the system as a whole. Many custom user management systems have vulnerabilities that simply haven’t been corrected. Within the last year, there have been security breaches of user management systems of companies such as Dropbox, Dailymotion, Twitter and Yahoo. If you choose to build a custom solution, you are on the hook for securing your system.

Enter Amazon Cognito Link

Amazon Cognito is a managed service that enables you to integrate a flexible and scalable user management system into your web and mobile applications. Cognito provides two distinct ways to utilize the service: federated identities, which allow for log-in via social networks such as Facebook, and user pools, which give you completely custom user management capabilities for a specific app or suite of applications.

Federated identities are great if you want users to be able to log in with Facebook (or Google, Amazon, etc.), but this means that a portion of the user management process will have been outsourced to Facebook. While this might be acceptable in some cases, users might not want to connect their Facebook account to your application. In addition, you might want to manage more of the user’s lifecycle directly, and for this, federated identities aren’t as flexible. For the purpose of today’s article, we will focus on user pools because they provide the flexibility needed for a robust user management platform that would fit most any use case. In this manner, you will have an approach that can be used in most any project.

Because this is an AWS service, there are other benefits of using Cognito. Cognito can integrate with API Gateway to provide a painless way to authorize API access based on the tokens that are returned from a Cognito log-in. In addition, if you are already leveraging other AWS services for your mobile application, you can use your user pool as an identity provider for your AWS credentials.

As with any other AWS service, there is a cost involved. Pricing for Cognito is based on monthly active users (MAUs). The great news for most developers is that there is an indefinite free tier that is capped at 50,000 MAUs when using a custom user pool. If you have a large application, this will give you a large number of users to pilot a new approach to user management. However, I suspect that many of you have experiences that will never go beyond 50,000 users. In this case, core user management will be pretty much free. The only exception to this is other AWS services that you will be leveraging as part of the user management process, such as Lambda, SNS and S3.

Creating A User Pool Link

The first step in integrating a user pool into your mobile application is to create a Cognito user pool. This will give us the configuration values needed to plug into our example application. To create a new user pool, walk through the wizard provided in Amazon’s Cognito console5.

Let’s walk through the process of creating a user pool. I must warn you that this is a lengthy process. In many ways, this is a good thing because it shows areas of flexibility. However, you’ll want to grab a cup of coffee and buckle in for this one.

1. Name Link

The initial step in creating a user pool involves setting a name for your user pool and selecting the approach you will be taking to create the user pool. You can either review the defaults or “step through” the settings. Because we want to have a good working knowledge of how the user pool is being configured, choose the option “Step through settings.”

Step 1 in User Pool Creation6
The initial step in creating a user pool (View large version7)

2. Attributes Link

Configuring attributes will require a bit of thought. For each user pool, you will need to determine which attributes will be stored in the system and which ones are required. Because the system will enforce required values, you cannot change this down the road. The best approach here is to mark only truly essential values here as required. In addition, if you want users to be able to log in with their email address, be sure to mark that one as an alias.

If you want to include custom values, you will need to do that here as well. Each custom value will have a type, optional validation rules, and an option to be mutable (changeable) or non-mutable (unchangeable). There is a hard limit of 25 custom attributes.

Finally, a point needs to be made here about usernames. The username value for each user is immutable (unchangeable). This means that, in most cases, making this value automatically generated would make sense. This is why the “preferred username” value exists. If you want to users to have a username value that they can edit, just mark the “preferred username” attribute as an alias. If you want users simply to log in with their email address, be sure to mark the “email” attribute as both required and an alias.

For our demo application, I chose to make “email,” “given name” and “family name” required.

Step 2 in User Pool Creation8
Configuring user attributes for the user pool (View large version9)

3. Policies Link

After configuring the attributes, you will be able to configure the policies for the account. The first policy to configure is the password policy. The policy allows you to configure both the length and whether you require numbers, special characters, uppercase letters or lowercase letters. This policy will be enforced on both passwords that users enter as well as passwords that administrators assign to users.

The next policies relate to user sign-up. For a public application, you will likely want to allow users to sign up themselves. However, depending on the type of application, you might want to restrict sign-up and have the system be invitation-only. In addition, you will have to configure how quickly these invitations will expire if they are not used.

For our demo application, I chose to use just the default values, with the exception that I don’t want users to be able to sign up on their own. With these values in place, we can proceed to verifications.

Step 3 in User Pool Creation10
Configuring policies for the user pool (View large version11)

4. Verifications Link

The verifications step allows you to set up multi-factor authentication, as well as email and phone verification. While this functionality is relatively easy to set up in the console, note that you will need to request a spending increase12 for AWS SNS if you want to either verify phone numbers or use multi-factor authentication.

For our demo application, I chose to use just the default values.

Step 4 in User Pool Creation13
Configuring verifications for the user pool (View large version14)

5. Message Customizations Link

This step allows you to customize the email and SMS messages that your user pool will send, as well as the “from” and “reply to” email addresses. For the purpose of our demo application, I will leave the default values here and proceed.

Step 5 in User Pool Creation15
Configuring the lifecycle messages for the user pool (View large version16)

6. Tags Link

If you are new to AWS, you might not need to specify any tags. However, in case your organization uses AWS regularly, tags provide a way to analyze spending and assign permissions with IAM. For example, some organizations specify tags per environment (development, staging, production) and by project.

No matter what you enter in this step, it won’t affect our demo application.

Step 6 in User Pool Creation17
Adding tags for the user pool (View large version18)

7. Devices Link

The next step allows you to define whether the user pool will remember your user’s devices. This is an additional security step that allows you to see what devices a specific account has been logged into with. This has an extra value when you are leveraging multi-factor authentication (MFA). If the device is remembered, you can elect not to require an MFA token upon each log-in.

For the purpose of the demo application, I have chosen to set the value to “Always.”

Step 7 in User Pool Creation19
Configuring device handling for the user pool (View large version20)

8. App Clients Link

For each application for which you want to use the user pool (such as an iOS application, web application, Android application, etc.), you should create an app. However, you can come back and create these after the user pool has been created, so there is no pressing need to add all of these just yet.

Each application has several values that you can configure. For this demo application, we will give the app a name and then leave the default values. Next, you can configure which user attributes each app can read and write.

Step 8 in User Pool Creation21
Configuring client applications for the user pool (View large version22)

You can set whichever values you like in this step, as long as the email address, family name and given name are all readable and writable by the application. Be sure to click the option to “Create App Client” before proceeding.

9. Triggers Link

With triggers, you can use Lambda functions to completely customize the user lifecycle process. For example, if you only want users with an email address from your company’s domain to be able to sign up, you could add a Lambda function for the “Pre sign-up” trigger to perform this validation and reject any sign-up request that doesn’t pass.

For our demo application, I will not add any triggers.

Step 9 in User Pool Creation23
Configuring triggers for the user pool (View large version24)

10. Review Link

I realize that this might have seemed like a lengthy and arduous process. But bear in mind that each step in creating a user pool has flexibility that allows for the solution to fit more use cases. And now for the news you’ve been waiting to hear: This is the last step.

Just review the settings to make sure you have configured them correctly for the demo application. From this screen, you can go back and edit any of the previous settings. Once the user pool is created, some configuration values (such as required attributes) cannot be changed.

With your new user pool created, you can now proceed to integrate them in a sample iOS application using the AWS SDK for iOS.

Step 10 in User Pool Creation25
Final review of the user pool before creation (View large version26)

Setting Up Your iOS Application For Your User Pool Link

I have created a sample iOS application that integrates with Cognito to allow the user to log in, log out, enter their first and last name, and set a password. For this initial demo, user sign-up is not included, so I’ve used Cognito’s console to add a new user for testing.

The code for this application can be found in my GitHub repository27.

Configuring Dependencies Link

This application uses CocoaPods28 for managing dependencies. At this point, the only dependencies are the specific pieces of the AWS iOS SDK that relate to Cognito user pools.

(A full description of CocoaPods is beyond the scope of this article, however, a resource29 on CocoaPods’ website will help you get up and running, in case this concept is new to you.)

The contents of the Podfile for this application can be seen below:

source 'https://github.com/CocoaPods/Specs.git' platform :ios, '10.0' use_frameworks! target 'CognitoApplication' do pod 'AWSCore', '~> 2.5.5' pod 'AWSCognitoIdentityProvider', '~> 2.5.5' end 

Assuming that CocoaPods is installed on your machine, you can just run pod install, and the necessary dependencies will be installed for you.

User Pool Configuration Link

The next step is to include the values for your user pool and client application. The demo application is configured to use a file, CognitoApplication/CognitoConfig.plist, from which to pull this information. Four values need to be defined:

  • region (string)

    This is the region in which you created your user pool. This needs to be the standard region identifier, such as us-east-1 or ap-southeast-1.
  • poolId (string)

    This is the ID of the user pool that you created.
  • clientId (string)

    This is the clientId configured as a part of the app that you attached to the user pool.
  • clientSecret (string)

    This is the clientSecret that is configured as a part of the app that you attached to the user pool.

With that file and the proper values in place, the demo application can be launched. If any exceptions occur during launch, be sure that you have included each of the four values shown below and that the file is placed in the correct directory.

plist Configuration in Xcode30
User pool configuration in Xcode with the plist file (View large version31)

App Delegate Integration Link

The core of the integration with Amazon Cognito happens within the application’s AppDelegate. Our first step is to ensure that we have set up logging and have connected to our user pool. As a part of that process, we will assign our AppDelegate as the delegate of the user pool. For this basic example, we can keep this logic within the AppDelegate. For larger projects, it might make sense to handle this elsewhere.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // set up logging for AWS and Cognito AWSDDLog.sharedInstance.logLevel = .verbose AWSDDLog.add(AWSDDTTYLogger.sharedInstance) // set up Cognito config self.cognitoConfig = CognitoConfig() // set up Cognito setupCognitoUserPool() return true } func setupCognitoUserPool() { // we pull the needed values from the CognitoConfig object // this just pulls the values in from the plist let clientId:String = self.cognitoConfig!.getClientId() let poolId:String = self.cognitoConfig!.getPoolId() let clientSecret:String = self.cognitoConfig!.getClientSecret() let region:AWSRegionType = self.cognitoConfig!.getRegion() // we need to let Cognito know which region we plan to connect to let serviceConfiguration:AWSServiceConfiguration = AWSServiceConfiguration(region: region, credentialsProvider: nil) // we need to pass it the clientId and clientSecret from the app and the poolId for the user pool let cognitoConfiguration:AWSCognitoIdentityUserPoolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId: clientId, clientSecret: clientSecret, poolId: poolId) AWSCognitoIdentityUserPool.register(with: serviceConfiguration, userPoolConfiguration: cognitoConfiguration, forKey: userPoolID) let pool:AWSCognitoIdentityUserPool = AppDelegate.defaultUserPool() // we need to set the AppDelegate as the user pool's delegate, which will get called when events occur pool.delegate = self } 

After this configuration is in place, we need to configure the delegate methods for the user pool. The protocol that we are implementing is AWSCognitoIdentityInteractiveAuthenticationDelegate. This delegate will get called any time the user needs to log in, reset their password or provide a multi-factor authentication code or if we need to query the user about whether they would like their device to be remembered. For our example, we only need to implement the startPasswordAuthentication and the startNewPasswordRequired methods:

extension AppDelegate: AWSCognitoIdentityInteractiveAuthenticationDelegate { // This method is called when we need to log into the application. // It will grab the view controller from the storyboard and present it. func startPasswordAuthentication() -> AWSCognitoIdentityPasswordAuthentication { if(self.navigationController == nil) { self.navigationController = self.window?.rootViewController as? UINavigationController } if(self.loginViewController == nil) { self.loginViewController = self.storyboard?.instantiateViewController(withIdentifier: "LoginViewController") as? LoginViewController } DispatchQueue.main.async { if(self.loginViewController!.isViewLoaded || self.loginViewController!.view.window == nil) { self.navigationController?.present(self.loginViewController!, animated: true, completion: nil) } } return self.loginViewController! } // This method is called when we need to reset a password. // It will grab the view controller from the storyboard and present it. func startNewPasswordRequired() -> AWSCognitoIdentityNewPasswordRequired { if (self.resetPasswordViewController == nil) { self.resetPasswordViewController = self.storyboard?.instantiateViewController(withIdentifier: "ResetPasswordController") as? ResetPasswordViewController } DispatchQueue.main.async { if(self.resetPasswordViewController!.isViewLoaded || self.resetPasswordViewController!.view.window == nil) { self.navigationController?.present(self.resetPasswordViewController!, animated: true, completion: nil) } } return self.resetPasswordViewController! } } 

One key thing to note is that both of these methods return a view controller that implements a specific protocol. For example, the LoginViewController implements AWSCognitoIdentityPasswordAuthentication, which has a single method that gets called with the parameters needed to enable the user to complete the log-in process.

Authentication Flow Link

With all of these pieces in place in the demo application, you can now see the log-in process work from beginning to end. The main view of the application shows the username and the first name and last name of the user. To make this happen, the following steps occur:

  1. In the AppViewController, we call the fetchUserAttributes method in the viewDidLoad method. If the user isn’t logged in, this will trigger the log-in process.
  2. The startPasswordAuthentication method in the AppDelegate will be triggered. This method loads the LoginViewController and presents it.
  3. The getDetails method of LoginViewController is called by the AWS SDK. This includes an object that is an instance of AWSTaskCompletionSource, which we can use to allow the user to attempt to log in.
  4. When the user presses the “Log in” button, we pass the log-in credentials to that object. This will then call the didCompleteStepWithError method, and we can handle the result accordingly. If there is no error, we can dismiss the view controller.
  5. If we created the user in the console, we will have another step to handle here. Because we gave the user a temporary password, they will need to set a more permanent one. In addition, because we set the given name and family name as required parameters, we need to allow the user to enter those, too. The AWS SDK will detect this and call the startNewPasswordRequired method in the AppDelegate. This will present the ResetPasswordViewController and set its instance of AWSTaskCompletionSource.
  6. The ResetPasswordViewController works almost identically to the LoginViewController. We simply need to ask the user for the correct values and then submit those values. Once this process is completed successfully, we dismiss the view controller.
  7. Once the entire log-in process has completed, the SDK will securely store the tokens returned by Cognito. Then, we will finally retrieve the user details, and we can use those to populate the AppViewController with the user’s username, given name and family name.
The working application with authentication working32
The working sample application, showing username and meta data

Conclusion Link

While the user pool set-up process might have several steps, those steps are easy to navigate. In addition, the amount of configuration possible should give you confidence that it can support a majority of use cases. In my day job at Universal Mind, I’ve worked with several clients who are moving their existing applications over to leverage the capabilities that Cognito provides for user management.

Regardless of whether you need to implement a user management system regularly, this is a tool that every mobile and web developer should have in their toolbox. In the next article in this series, we will begin to explore the capabilities of Cognito a bit more by implementing a more full-featured demo application that implements more of the common user management use cases.

With a bit of practice, you can go and impress all of your friends by setting up a new application that satisfies all of these user management use cases within a day. That’s pretty good for a day’s work.

Links and Resources Link

(da, vf, yk, al, il)

Footnotes Link

  1. 1 https://auth0.com/
  2. 2 https://www.smashingmagazine.com/2015/02/carousel-usage-exploration-on-mobile-e-commerce-websites/
  3. 3 https://www.smashingmagazine.com/wp-content/uploads/2017/07/cognito-diagram-large-opt.jpg
  4. 4 https://www.smashingmagazine.com/wp-content/uploads/2017/07/cognito-diagram-large-opt.jpg
  5. 5 https://console.aws.amazon.com/cognito/home
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step1-large-opt.jpg
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step1-large-opt.jpg
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step2-large-opt.jpg
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step2-large-opt.jpg
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step3-large-opt.jpg
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step3-large-opt.jpg
  12. 12 http://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-email-phone-verification.html
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step4-large-opt.jpg
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step4-large-opt.jpg
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step5-large-opt.jpg
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step5-large-opt.jpg
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step6-large-opt.jpg
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step6-large-opt.jpg
  19. 19 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step7-large-opt.jpg
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step7-large-opt.jpg
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step8-large-opt.jpg
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step8-large-opt.jpg
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step9-large-opt.jpg
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step9-large-opt.jpg
  25. 25 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step10-large-opt.jpg
  26. 26 https://www.smashingmagazine.com/wp-content/uploads/2017/07/userpool-step10-large-opt.jpg
  27. 27 https://github.com/davidtucker/CognitoSampleApplication/tree/article1
  28. 28 https://cocoapods.org/
  29. 29 https://cocoapods.org
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2017/07/xcode-plist-large-opt.jpg
  31. 31 https://www.smashingmagazine.com/wp-content/uploads/2017/07/xcode-plist-large-opt.jpg
  32. 32 https://www.smashingmagazine.com/wp-content/uploads/2017/07/app-working-preview-opt.jpg
  33. 33 https://aws.amazon.com/cognito/
  34. 34 https://aws.amazon.com/cognito/dev-resources/
  35. 35 https://aws.amazon.com/mobile/sdk/
  36. 36 https://www.raywenderlich.com/156971/cocoapods-tutorial-swift-getting-started

↑ Back to topTweet itShare on Facebook