<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Piervincenzo Madeo on Medium]]></title>
        <description><![CDATA[Stories by Piervincenzo Madeo on Medium]]></description>
        <link>https://medium.com/@piervix?source=rss-7811ae9ca550------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*oHG5r4Z73_xWrMICLecPyg.jpeg</url>
            <title>Stories by Piervincenzo Madeo on Medium</title>
            <link>https://medium.com/@piervix?source=rss-7811ae9ca550------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 06 Jun 2026 21:28:01 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@piervix/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Automate your UX Design workflow with Framer.js, Gulp and Sketch]]></title>
            <link>https://blog.prototypr.io/automate-your-ux-design-workflow-with-framer-js-gulp-and-sketch-cc2e8484e4b7?source=rss-7811ae9ca550------2</link>
            <guid isPermaLink="false">https://medium.com/p/cc2e8484e4b7</guid>
            <category><![CDATA[gulp]]></category>
            <category><![CDATA[framerjs]]></category>
            <category><![CDATA[prototyping]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[ux]]></category>
            <dc:creator><![CDATA[Piervincenzo Madeo]]></dc:creator>
            <pubDate>Sat, 09 Apr 2016 12:13:09 GMT</pubDate>
            <atom:updated>2017-08-26T10:48:26.528Z</atom:updated>
            <cc:license>http://creativecommons.org/licenses/by/4.0/</cc:license>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*y1zbJuxBevJIaOPRhv93JQ.jpeg" /></figure><p><em>[ Update 04.01.2017: recently the awesome guys at Framer added a powerful component that helps you transition and navigate between multiple screens: </em><a href="https://blog.framerjs.com/posts/introducing-framer-flows.html?ref=piervix-ux-framer-prototyping"><em>Flow</em></a><em>. I’ve just tried this useful component and it just works fine. <br>Update FramerJS in your node_module and enjoy the FlowComponent. ]</em></p><p>First things first, after years, I’m back to blogging. Nice feeling, it’s always a good thing when you want to share experiences and thoughts with the community. Be nice with me, it’s my first post after a while.</p><p>After a couple of years of pure coding and project management activities, I’m back to UX design too… and design is about thinking <strong>products that work for people</strong>. To reach your goal, as designer, you should present in a clever way your design concepts, you should test the user flow and you should provide clear explanations about your design choices.</p><p>If you were in 2006, JPGs and a long meetings would be fine. But, wait. We’re in 2016 and today you can prove your ideas are working and your assumptions are correct creating a prototype with testable interactions and real animations.</p><p>Today the final result of our efforts will be the following.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/1*5jglUcjv7s_xhh70rK-D1Q.gif" /><figcaption>Final prototype</figcaption></figure><p>If you want just run and play, go to the <a href="https://github.com/piervix/ux-framer-prototyping"><strong><em>GitHub repository</em></strong></a> and enjoy it.</p><p>Here you can test the final result: <a href="http://framer-ux.herokuapp.com/">http://framer-ux.herokuapp.com/</a></p><h3>Seriously, create prototypes</h3><p>I have to be honest, I needed some proof. I didn’t see prototyping as a necessary step in my design process, it seemed to be a waste of time; but, in a random fashion, I’ve spent a lot of time:</p><ol><li>arguing my design choices with managers</li><li>explaining to <a href="https://medium.com/@piervix/i-perfectly-know-that-351da9bde504#.6v9w3qynu"><em>lazy developers</em></a> why we need to implement that particular user flow or animation</li><li>failing at user tests</li><li>making wrong assumptions</li><li>proving that clients (often, but not always) are completely wrong</li></ol><p>I needed to find a way to optimise my time, and I tried to prototype portions of user flow and some <em>hard-to-explain</em> interactions. Guess what? People understand me better and <strong>they provide more valuable feedbacks </strong>after testing a real prototype. The final product gains a lot of benefits (and our clients too… of course), it will be more close to user expectations and mental model.</p><blockquote>To be clear, discussing with managers, clients and colleagues is not so evil. You can always improve and generate good ideas from a positive discussion, I’m just saying that with prototypes you can create smart and more engaging user tests and design discussions.</blockquote><p>An non-exhaustive list of advantages deriving from the creation of working prototypes is:</p><ul><li>performing more precise user tests</li><li>receiving more valuable feedbacks</li><li>anticipating possibile technical constraints with developers</li><li>defining client’s expectations</li></ul><h3>Why Framer.js?</h3><p>There are a lot of <em>almost-free </em>tools out there: <a href="https://www.invisionapp.com/">InVision</a>, <a href="https://marvelapp.com/">Marvel</a>, <a href="https://proto.io/">Proto.io</a> and so on. They are all <em>ready-to-go </em>and good solutions to create your prototype.</p><p>So, why my choice is Framer.js?</p><p>The Readme file of the <a href="https://github.com/koenbok/Framer">GitHub repository</a> says:</p><blockquote><strong>Framer.js </strong>is an open source JavaScript framework for rapid prototyping. It allows you to define animations and interactions, complete with filters, spring physics, 3D effects and more. It’s bundled with Framer Generator, an application that allows you to import layers directly out of Photoshop and Sketch.</blockquote><p>Below some key points that convinced me Framer is good in order to improve my design process and workflow.</p><p><em>[Yes, it’s a JS library. Ball is in your court, </em><strong><em>you have to code!</em></strong><em>]</em></p><h4>Open source</h4><p>It’s an open source project (<a href="https://github.com/koenbok/Framer">https://github.com/koenbok/Framer</a>) that basically means free to use and cost optimization. You will also earn in terms of freedom, flexibility and customization.</p><h4>Active and large community</h4><p>Open source means community: a bunch of contributors who constantly fix bugs and improve the framework (<a href="https://github.com/koenbok/Framer/graphs/contributors">https://github.com/koenbok/Framer/graphs/contributors</a>) and a lot of people that share knowledge, case histories, tutorials and examples. You can join the <a href="https://www.facebook.com/groups/framerjs">Facebook Group</a> to be updated.</p><h4>Learning curve</h4><p>Framer.js has four main concepts: <strong>Layers</strong>,<strong> Animation</strong>,<strong> States </strong>and<strong> Events</strong>. They are basic concepts, easy to understand, that will allow you to create great prototypes. You will write code in a very natural way even if you are not a developer.</p><h4><strong>JavaScript</strong></h4><p>It is one of the most used programming language. With Framer, actually, you use <a href="http://coffeescript.org/">CoffeeScript</a> but you will be able to extend your prototypes in a JavaScript world, that means you can perform XHR requests, import other libraries, implement logic and algorithms in order to make your prototype smarter, and so on.</p><p><em>[Personally, I don’t like so much the use of CoffeeScript but we can survive]</em></p><h4>Modularization</h4><p>With JS you can create reusable components and create a repository of modules that you can share in different projects.</p><h4>Versioning</h4><p>We can use the power of Git to track the prototype history and collaborate with other team members. Trust me, it’s really cool.</p><h4>Adoption</h4><p>Top-notch designers and teams at <strong>Dropbox</strong>, <strong>Twitter</strong>,<strong> Google </strong>and<strong> Facebook </strong>are using Framer as a fundamental piece of their workflow. Take a look at Dribbble tag page for <a href="https://dribbble.com/tags/framer?s=popular">#<em>framer</em></a><em> </em>to discover new members of the Framer family.</p><h3>Introduction to Framer.js</h3><p>As you already know we are talking about a JavaScript framework for rapid prototyping. Here a quick introduction.</p><h4>Language: CoffeeScript</h4><p>CoffeeScript is a language compiled to JavaScript (<em>.coffee</em> files are not interpreted at run time). It has a clever syntax, some performance and code style optimizations; and below there are some examples to get started with CoffeeScript.</p><p>First, rembember that Indentation counts, it is used to define the structure of the language.</p><p><strong>Variables<br></strong>Variables don’t require <em>var</em>.</p><pre><strong>name</strong> = &quot;Pier&quot;<br><strong>year</strong> = 1986<br><strong>fullName</strong> = name + &quot;Doe&quot; # Pier Doe</pre><p><strong>Functions<br></strong>Declared by naming the function, equals sign, parameters and then a the symbol -&gt;.</p><pre><strong>sum</strong> = (a, b = 2) -&gt; <br>  a + b</pre><pre><strong>a</strong> = 4<br><strong>sum</strong>(a) # <em>-&gt; 6</em></pre><p><strong>Arrays<br></strong>You can use array as usual with Coffee with some extra features</p><pre>alphabet = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;] <br>firstFive = [1..5] # <em>range = [1, 2, 3, 4, 5];</em></pre><p><strong>Object literals</strong><br>You can declare objects in Coffee avoiding braces:</p><pre><strong>people</strong> =<br>  dev:<br>    name: &quot;Pier Nad&quot;<br>    skills: [&quot;JavaScript&quot;, &quot;Ruby&quot;]<br>  designer:<br>    name: &quot;Carl B&quot;<br>    skills: [&quot;Framer.js&quot;, &quot;Sketch&quot;]</pre><p><strong>Classes<br></strong>They are declared in CoffeeScript with the keyword <em>class </em>followed by the name.<br>Methods and construcotr are written with the name of the method followed by a colon.</p><pre><strong>class</strong> Person<br>  constructor: -&gt;</pre><p><strong>Instance Variables<br></strong>An instance variable starts with an @ symbol</p><pre><strong>class</strong> Person<br>  constructor: (name) -&gt;<br>    @name = name</pre><p><strong>Class Inheritance<br></strong>To write a subclass you can use <em>extends </em>keyword</p><pre><strong>class</strong> Employee <strong>extends</strong> Person<br>  constructor: (name, jobTitle) -&gt;<br>    super name<br>    @jobTitle = jobTitle</pre><p><strong>Loops and flow control<br></strong>A simple for loop:</p><pre><strong>for</strong> name, i <strong>in</strong> [&quot;Pier&quot;, &quot;Carl&quot;]<br>  alert &quot;#{i} - Employee: #{name}&quot;</pre><p>The convention of optional parentheses continues with CoffeeScript’s if and else keywords.</p><pre><strong>if</strong> true == true<br>  &quot;Passed!&quot;</pre><pre><strong>if</strong> true != true then &quot;Something wrong here!&quot;</pre><pre>alert &quot;Yeah!&quot; <strong>if</strong> season == &quot;Summer&quot;</pre><p>This was just an introduction, if you need to learn more about CoffeeScript, below some useful resources.</p><ul><li><strong>CoffeeScript doc</strong>: <a href="http://coffeescript.org/">http://coffeescript.org/</a></li><li><strong>The Absolute Beginner’s Guide to CoffeeScript</strong>: <a href="http://blog.teamtreehouse.com/the-absolute-beginners-guide-to-coffeescript">http://blog.teamtreehouse.com/the-absolute-beginners-guide-to-coffeescript</a></li><li><strong>The Little Book on CoffeeScript</strong>: <a href="https://arcturo.github.io/library/coffeescript/index.html">https://arcturo.github.io/library/coffeescript/index.html</a></li></ul><h4>Layers</h4><p>They are the basic block of Framer, you can think of layers as shapes with attributes that you can move and animate within a sort of canvas.</p><pre>mySquare = new Layer<br>  x: 0<br>  y: 0<br>  width: 100<br>  height: 100<br>  opacity: 0.8<br>  backgroundColor: &quot;black&quot;</pre><p>Yes, it’s exactly what you are thinking, a 100x100 top-left black square with 80% opacity.</p><p>Cool, but you don’t want to manually create all layers of your app prototype. You can set your properties directly in Sketch, and I suggest to do that. A good rule, in my opinion, is: you should focus on interactions in Framer and do the graphical things in Sketch.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/619/1*2UtGwV7bVeULyQ_7onCcoA.png" /></figure><p>If you draw a 228x228 square in position top-left (x=0 and y=0) in Sketch, using <a href="http://framerjs.com/assets/static/downloads/Framer.zip">Framer Generator</a>, you will import the same layer attributes. Your square will be the same inside the Framer canvas.</p><p>To be consistent, remember to <a href="http://framerjs.com/learn/import/">group your layers</a> in a clever and mnemonic way and avoid name repetitions.</p><p>You can just import layers from Sketch (we use <a href="http://framerjs.com/assets/static/downloads/Framer.zip">Framer Generator</a>).</p><pre>app = Framer.Importer.load(&quot;app.framer/imported/app@1x&quot;)</pre><p>Now you can access all the layers through the variable <em>app, </em>play with them and change attributes</p><pre>app.overlay.opacity = 0.6 <em># </em>app.layerName.attribute = value</pre><p>If you want to change the initial properties of your layers, you can either import again after you edit in Sketch or directly edit in Framer.</p><p><em>[Learn more: </em><a href="http://framerjs.com/docs/#layer.layer"><em>http://framerjs.com/docs/#layer.layer</em></a><em>]</em></p><h4>Events</h4><p>Events are things that you can listen for. Framer supports event listeners such as <em>Click</em>, <em>TouchStart</em>, <em>TouchEnd</em>, <em>Scroll</em>, <em>Drag</em> etc. It’s easy to understand what they mean by their name.</p><p>A <em>click</em> example we’ll be useful: print <em>“clicked!” </em>when user click on a specific button layer.</p><pre>app.button.on Events.Click, -&gt;<br>   print &quot;clicked!&quot;</pre><p>When an event is called we can handle two arguments: the first one has event information (containing mouse positions etc…); the second argument is always the layer responding to the event.</p><pre>app.button.on Events.Click, (event, layer) -&gt;<br>  print &quot;Clicked&quot;, layer.name<br># &quot;Clicked&quot;, &quot;button&quot;</pre><p><em>[Learn more: </em><a href="http://framerjs.com/docs/#events.events"><em>http://framerjs.com/docs/#events.events</em></a><em>]</em></p><h4>States</h4><p>You can simply think of state as <em>a number of attributes between state A and B</em>, indeed they are sets of layer properties and values. You have an initial state (State A) and then you can <a href="http://framerjs.com/docs/#layer.states.add">add</a>, <a href="http://framerjs.com/docs/#layer.states.remove">remove</a> or <a href="http://framerjs.com/docs/#layer.states.switch">switch</a> states.</p><pre># Add two states to button layer<br>app.overlay.states.add<br>  stateA:<br>    x: 500<br>    opacity: 0.5<br>  stateB:<br>    x: 200<br>    opacity: 1</pre><pre>app.button.on Events.Click, -&gt;<br>   app.overlay.states.switch(&quot;stateB&quot;)</pre><p><em>[Learn more: </em><a href="http://framerjs.com/docs/#layer.states"><em>http://framerjs.com/docs/#layer.states</em></a><em>]</em></p><h4>Animation</h4><p>Animation objects manage animations that target a layer and. You can think at animations like this: if you trigger an event, something moves (<em>layer) </em>following some specified rules (<em>state</em> changes).</p><p>You can customize animation options in states like this:</p><pre>app.overlay.states.animationOptions = curve: &quot;spring(300, 30, 0)&quot;</pre><p>You can also create animation objects and attach a layer that will move, like this:</p><pre># Repeat an animation 3 times, delay for 1 seconds, target the layerX<br>animationD = new Animation<br>  layer: layerX<br>  properties:<br>    x: 100<br>  repeat: 3<br>  delay: 1</pre><p><em>[Learn more: </em><a href="http://framerjs.com/docs/#animation.animation"><em>http://framerjs.com/docs/#animation.animation</em></a><em>]</em></p><p>To learn more about Framer.js, below some helpful links:</p><ul><li><strong>Framer.js doc</strong>: <a href="http://framerjs.com/docs/">http://framerjs.com/docs/</a></li><li><strong>New to Framer? Just 3 Things to Get You Started</strong>: <a href="https://medium.com/framer-prototyping/new-to-framer-just-3-things-to-get-you-started-47397f27c71e">https://medium.com/framer-prototyping/new-to-framer-just-3-things-to-get-you-started-47397f27c71e</a></li><li><strong>Framer for beginners</strong>: <a href="https://medium.com/framer-prototyping/framer-js-for-people-who-think-things-like-framer-js-are-weird-and-hard-add2068c8114">https://medium.com/framer-prototyping/framer-js-for-people-who-think-things-like-framer-js-are-weird-and-hard-add2068c8114</a></li><li><strong>Working with Framer: </strong><a href="http://humaan.com/prototyping-with-framer/">http://humaan.com/prototyping-with-framer/</a></li><li><strong>Framer.js group</strong>: <a href="http://framergroup.com/">http://framergroup.com/</a></li></ul><h3>Project goal</h3><p>When I prototype with other prototyping tools I find a bit annoying the import phase. When I change a design component or an animation I don’t have an automated reload and I can’t frequently check the prototype flow and the interactions.</p><p>Our goal is to create an automated workflow to simplify our life by eliminating waste of time importing assets, maximizing the time we spend solving UX problems, testing in real time flows and interactions and easily sharing the prototype.</p><p>So, we want to:</p><ol><li>use Sketch to create our design and look and feel (or just a wireframe, it’s up to you)</li><li>slice and import new assets to be used in Framer</li><li>edit our CoffeeScript main file with our text editor in order to add interactions and animations</li><li>save our progress and immediately test the latest version of the prototype</li></ol><p>Below you can take a look at my preferred set-up on my Mac. <br><strong>Desktop 1</strong>: my favourite text editor (<a href="https://atom.io/">https://atom.io/</a>) to modify source code and the terminal to run automated tasks and do nerdy stuff.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EcjNcT25yBrpiNCF23nAGw.png" /><figcaption>Desktop 1</figcaption></figure><p><strong>Desktop 2</strong>: Sketch to design, Framer Generator to import assets and the Finder.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HppBzC0AahTx0ZfoU6pJ4A.png" /><figcaption>Desktop 2</figcaption></figure><p><strong>Desktop 3</strong>: browser to test our progress in real time</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vaDGO8x7BDkbx3LO_N-Yxw.png" /><figcaption>Desktop 3</figcaption></figure><p>With Framer we are in a JavaScript world so we are going to create our prototype framework with the help of libraries such as:</p><ul><li><a href="http://gulpjs.com/">Gulp</a>, a toolkit that helps you <strong>automate</strong> painful or time-consuming tasks in your development workflow</li><li><a href="https://webpack.github.io/">Webpack</a>, a <strong>module bundler </strong>that takes modules with dependencies and generates static assets representing those modules</li><li><a href="https://www.browsersync.io/">BrowserSync</a>, to keep multiple browsers &amp; devices in sync building our prototype</li></ul><h3>Let’s start: project set-up and structure</h3><p>We need <a href="https://nodejs.org/en/">Node.js</a> and <a href="https://www.npmjs.com/">npm</a> installed. The best way to install them is <a href="http://brew.sh/">Brew</a>, open your terminal and type:</p><pre>$ /usr/bin/ruby -e &quot;$(curl -fsSL <a href="https://raw.githubusercontent.com/Homebrew/install/master/install%29">https://raw.githubusercontent.com/Homebrew/install/master/install)</a>&quot;<br>$ brew update<br>$ brew doctor</pre><p>Install Node and npm</p><pre>$ brew install node</pre><p>Create project folder and init <em>package.json</em>, where we are going to specify libraries and tools we want to use.</p><pre>$ mkdir ux-framer-prototyping<br>$ cd ux-framer-prototyping<br>$ npm init</pre><p>Follow the wizard and then you can customize your <em>package.json.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/633/1*RP-biUin7BeEV4NEnZFDxw.png" /><figcaption>What you see after ‘<em>npm init’. Feel free to fill all fields, but you can always modify them later</em></figcaption></figure><p>This file allows us to keep track of our project dependencies. Here’s a <strong><em>package.json</em></strong> I made.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2ccc94fc372d1fdd59954e48b56df832/href">https://medium.com/media/2ccc94fc372d1fdd59954e48b56df832/href</a></iframe><p>Easy to read, we have all our project <em>dependencies</em> listed. One thing to specify: I’m using GitHub as source for Framer.js code, I had some problems with the npm source and I’ve added a <em>postinstall</em> script to build Framer after download and modules setup. So don’t forget to add the <em>postinstall.sh </em>file in your project root with the following commands.</p><pre>cd ./node_modules/framerjs<br>npm install --only=dev<br>mkdir -p build<br>gulp build:release<br>cd ../..<br>gulp build</pre><p>Now we can run <em>npm install </em>to download and build all necessary libraries.</p><p>Now we create a src folder in the root of the project with all our necessary files (go to the GitHub repository for reference: <a href="https://github.com/piervix/ux-framer-prototyping/tree/develop/src">https://github.com/piervix/ux-framer-prototyping/tree/develop/src</a>)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/257/1*Z6SeNK_FPUo4h-BlnAKlaw.png" /></figure><ul><li><em>images </em>contains project images</li><li><em>modules </em>will contain our helper and Framer modules</li><li><em>app.coffe </em>is the main app file of our prototype. Here will go the main code</li><li><em>app.sketch </em>is our whole design, our Sketch file</li><li><em>index.html </em>is our main presentation file that will be compiled and served</li><li><em>style.css</em> is our main CSS file</li></ul><p>Next, we can add the necessary <em>index.html</em></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6923c202204b56db6b456e4b86708a8f/href">https://medium.com/media/6923c202204b56db6b456e4b86708a8f/href</a></iframe><p>and our stylesheet.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d5adfb9cc472a5749a4af57c026e52dd/href">https://medium.com/media/d5adfb9cc472a5749a4af57c026e52dd/href</a></iframe><p>Don’t forget to install <a href="http://framerjs.com/assets/static/downloads/Framer.zip">Framer Generator</a> app.</p><h3>An automated workflow with Gulp and Webpack</h3><p>We have the skeleton of our project and now we are going to add some Gulp tasks to automate our workflow.</p><p>Remember the goal: we want to work in our Sketch file, add interactions in our CoffeeScript main app file, save and <em>automagically</em> update the animated prototype with the new code and images inside the <em>build </em>folder.</p><p>We do the magic with <a href="http://gulpjs.com/">Gulp</a>. <br>Create a <em>Gulpfile.js </em>in your project root and start by requiring necessary libraries and defining your paths object.</p><pre>&#39;use strict&#39;;</pre><pre>var gulp = require(&#39;gulp&#39;);<br>var coffee = require(&#39;gulp-coffee&#39;);<br>var gutil = require(&#39;gulp-util&#39;);<br>var sketch = require(&#39;gulp-sketch&#39;);<br>var del = require(&#39;del&#39;);<br>var webpack = require(&#39;webpack&#39;);<br>var mergeStream = require(&#39;merge-stream&#39;);<br>var browserSync = require(&#39;browser-sync&#39;).create();<br>var path = require(&#39;path&#39;);<br>var argv = require(&#39;yargs&#39;).argv;</pre><pre>var webpackCfg = require(‘./webpack.config.js’);var paths = {<br>  framerModuleBuild: path.join(__dirname, &#39;node_modules/framerjs/build/*&#39;),<br>  src: path.join(__dirname, &#39;src&#39;),<br>  build: path.join(__dirname, &#39;build&#39;),<br>  buildFramer: path.join(__dirname, &#39;build/framer&#39;),<br>  buildFolders: path.join(__dirname, &#39;build/**/**/*.*&#39;),<br>  buildImages: path.join(__dirname, &#39;build/framer/images&#39;),<br>  appIndex: path.join(__dirname, &#39;src/app.coffee&#39;),<br>  appHTML: path.join(__dirname, &#39;src/index.html&#39;),<br>  appImages: path.join(__dirname, &#39;src/images/**/*.{png, jpg, svg}&#39;),<br>  appModules: path.join(__dirname, &#39;src/modules/*.coffee&#39;),<br>  appCSS: path.join(__dirname, &#39;src/style.css&#39;),<br>  importedFromSketchFold: path.join(__dirname, &#39;src/**/imported/**/**&#39;),<br>  importedFromSketchJson: path.join(__dirname, &#39;src/**/imported/**/**/*.json&#39;),<br>  sketchSlices: path.join(__dirname, &#39;src/*.slices.sketch&#39;),<br>};</pre><p>Note the <em>importedFromSketchFold </em>and <em>importedFromSketchJson </em>paths. They are generated by using <strong>FramerGenerator.app</strong> to import our design.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/452/1*RVYXWh445Ox9Aw4kIUkLow.png" /><figcaption>Framer Generator</figcaption></figure><p>By clicking on import we will make available all our layers form Sketch in the <em>app.framer</em> folder.</p><p>Let’s create some tasks: we will need a <em>clean task </em>to clean up our build folder.</p><pre>gulp.task(‘clean’, del.bind(null, paths.build));</pre><p>We need tasks that help us to copy our static files (<em>framer.js</em> build, <em>index.html</em>, <em>style.css</em> and <em>images</em>) into our <em>build</em> folder. We create the <em>copy:generator </em>that depends on <em>copy:framerjs </em>and<em> copy:static </em>tasks.</p><pre>gulp.task(&#39;copy:framerjs&#39;, function () {<br>  var stream = gulp.src(paths.framerModuleBuild)<br>    .pipe(gulp.dest(paths.buildFramer));</pre><pre>  return stream;<br>});</pre><pre>gulp.task(&#39;copy:static&#39;, function () {<br>  var htmlStream = gulp.src(paths.appHTML)<br>    .pipe(gulp.dest(paths.build));</pre><pre>  var imagesStream = gulp.src(paths.appImages)<br>    .pipe(gulp.dest(paths.buildImages));</pre><pre>  var cssStream = gulp.src(paths.appCSS)<br>    .pipe(gulp.dest(paths.build));</pre><pre>  return mergeStream(htmlStream, imagesStream, cssStream);<br>});</pre><pre>gulp.task(&#39;copy:generator&#39;, function () {<br>  var stream = gulp.src(paths.importedFromSketchFold)<br>    .pipe(gulp.dest(paths.build));</pre><pre>  return stream;<br>});</pre><p>We create our <em>watch:serve</em> task that will check our main <em>app.coffee</em>, app modules files and imported-by-FramerGenerator folder and when they change it will run <em>copy:generator </em>and<em> webpack </em>tasks (we will soon configure Webpack). Finally our BrowserSync server will start, serving the <em>build</em> folder on default port 3000.</p><pre>gulp.task(&#39;watch:serve&#39;, function() {<br>  browserSync.init({<br>    server: &#39;./build&#39;,<br>    files: [paths.buildFolders],<br>    notify: true,<br>  });</pre><pre>  gulp.watch([paths.appIndex, paths.appModules], [&#39;webpack&#39;]);<br>  gulp.watch(paths.importedFromSketchFold, [&#39;copy:generator&#39;]);<br>});</pre><p>Our main tasks will be <em>build</em> and the <em>default</em> task. <br>The <em>build</em> task will setup our build folder to be served, the default task will run <em>build</em> and <em>watch:serve </em>after cleaning the build folder.</p><pre>gulp.task(&#39;build&#39;, [copyTask, &#39;webpack&#39;]);<br>gulp.task(&#39;default&#39;, [&#39;build&#39;], function () {<br>  gulp.start(&#39;watch:serve&#39;);<br>});</pre><h4>Webpack</h4><p>We use <a href="https://webpack.github.io/">Webpack</a> basically to compile our <em>.coffee</em> files. Here I’m not going to explain how it works, just know that it compiles your <em>app.coffee</em>.</p><p>Add a <em>webpack.config.js </em>inside your project root, like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3c46ee1b982e817f12275c13903a2ba1/href">https://medium.com/media/3c46ee1b982e817f12275c13903a2ba1/href</a></iframe><p>We now have our automated system for rapid prototyping. Just run</p><pre>$ gulp</pre><p>If you want to test with a working sample, copy and paste the following code (from Framer <a href="http://framerjs.com/examples/">examples page</a>) in your <em>app.coffee </em>and save.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8da6ba19ec52865fe463123e82421677/href">https://medium.com/media/8da6ba19ec52865fe463123e82421677/href</a></iframe><p>With default Gulp task running, by visiting <a href="http://locahost:3000">http://locahost:3000</a> you should see your prototype example (from <a href="http://framerjs.com/examples/">Framer Examples</a>).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TO9SZ69t7H5i-a6umW9XJA.png" /></figure><h3>Let’s create the prototype</h3><p>Time to start: we create our design (or just a wireframe) in Sketch, import assets with Framer Generator and add interactions with Framer.</p><p>You can download the sample <a href="https://drive.google.com/file/d/0B8rkaYITo3M0SzM0NHMtYUU4Ykk/view?usp=sharing">app.sketch</a> as your starting point.<br>Run <em>‘gulp’ </em>to watch your projects updates and recompile.</p><h4>Setup presentation device</h4><p>Add the presentation template you like. <a href="https://github.com/koenbok/Framer/tree/master/extras/DeviceResources">Here</a> a list of all available devices. I choose <em>google-nexus-6p </em>with a resolution of 2560x1440<strong><em>.</em></strong></p><pre># setup device for presentation<br>device = new Framer.DeviceView();</pre><pre>device.setupContext()<br>device.deviceType = &quot;google-nexus-6p&quot;<br>device.contentScale = 1</pre><pre>deviceHeight = device.screen.height<br>deviceWidth = device.screen.width</pre><pre>print &quot;Device height: #{deviceHeight}&quot;<br>print &quot;Device width: #{deviceWidth}&quot;</pre><p>Visiting <a href="http://localhost:3000">http://localhost:3000</a> you should see the following situation: device and resolution log.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MTZY_vAT3jelbFaMgZuHEA.png" /></figure><h4>Import design</h4><p>Framer Generator will import your design from Sketch. You can update and re-import it and you can access your entire design in <em>app.coffee</em> by typing:</p><pre>app = Framer.Importer.load(“app.framer/imported/app@1x”)</pre><p>The <em>app </em>object now represents the entire design.</p><h4>Setup layers</h4><p>Keep in mind, you can access different app layers by their group name. With the following situation</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/330/1*qjKuPP_oRS38Ez3yq71BcA.png" /></figure><p>to access the <em>iconWrite </em>element we just need to type <em>app.iconWrite</em>.</p><p>Let’s make some initial setup: we need to hide some layers, set some variables and create an array of Layers in order to perform animations and interactions later.</p><pre># variables to hold a scale value we’ll use later<br>initialScale = 0.2</pre><pre># array of our actions<br>actionButtons = []</pre><pre># hide some layers for the initial state<br>app.actions.opacity = 0<br>app.overlay.opacity = 0<br>app.iconWrite.opacity = 0</pre><pre># hide and set initial y position of the keyboard<br>app.keyboard.opacity = 0<br>app.keyboard.y = app.keyboard.height + deviceHeight</pre><pre>app.iconWrite.rotation = -180</pre><pre># Create an array of action layers (Add, Reminder, Task)<br>for i in [0…3]<br> actionButtons.push app[“action#{i+1}”]</pre><pre># Add initial scale value to action buttons<br>for action in actionButtons<br> action.scale = initialScale</pre><p>You should see the following situation at <a href="http://localhost:3000">http://localhost:3000</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JC_QSaLywv9IcVL-jMGAng.png" /><figcaption>Initial State</figcaption></figure><h4>Define states</h4><p>We define how the different components will change on specific states. We have basically two states at the moment:</p><ol><li>the<em> default</em> state with our elements at their initial state</li><li>the<em> openActions</em> state in which we show all our action buttons (add reminder and add task)</li></ol><p>So we define the state <em>openActions </em>and the related animation for each layer involved. The code is really self-explaining.</p><pre># define states<br>app.overlay.states.add<br> openActions: { opacity: 1 }<br>app.overlay.states.animationOptions = curve: “spring(400, 20, 0)”</pre><pre>app.actions.states.add<br> openActions: { opacity: 1 }<br>app.actions.states.animationOptions = curve: “spring(400, 20, 0)”</pre><pre>for action in actionButtons<br> action.states.add<br>  openActions: { scale: 1 }<br> action.states.animationOptions = curve: “spring(500, 30, 0)”</pre><pre>app.iconPlus.states.add<br> openActions: { opacity: 0, rotation: 90 }<br>app.iconPlus.states.animationOptions = curve: “spring(500, 30, 0)”</pre><pre>app.iconWrite.states.add<br> openActions: { opacity: 1, rotation: 0 }<br>app.iconWrite.states.animationOptions = curve: “spring(500, 30, 0)”</pre><h4>Add events</h4><p>We add a <em>switchState </em>function that will take the name of the state and will switch layers to that state.</p><pre># functions<br>switchOptions = (state) -&gt;<br> app.overlay.states.switch(state)<br> app.actions.states.switch(state)<br> <br>for action in actionButtons<br>  action.states.switch(state)</pre><pre>app.iconPlus.states.switch(state)<br>app.iconWrite.states.switch(state)</pre><p>Now we can run this function when we tap on the floating action button switching to the <em>openActions </em>state.</p><pre>app.floatingButton.on Events.Click, -&gt;<br> switchState(“openActions”)</pre><p>We call the same function when we tap on the overlay for coming back to the default state.</p><pre>app.overlay.on Events.Click, -&gt;<br> switchState(“default”)</pre><h4>Using modules</h4><p>As said, Framer.js allows us to work with modules. We use a nice module to add our input text element: <a href="http://framerco.de/post/136846506048/module-inputfield-class-update-this-module-has"><em>InputField module</em></a> by <a href="https://medium.com/u/f288cd03ad2a">Jordan Dobson</a>.<br>Download the <a href="http://share.framerjs.com/download/gl5sskhzdxi5/project.zip">sample project</a>, got to the module folder, find the <em>InputField.coffee</em> file and copy it into your <em>modules</em> folder.</p><p>Open your app.coffee main file now and import the module by typing:</p><pre>{ InputField } = require ‘InputField’</pre><p>Create the layer and set the initial state (hide it).</p><pre># the input element from module<br>taskInput = new InputField<br> name: “task”<br> type: “text-area”<br> width: deviceWidth<br> height: deviceHeight — app.keyboard.height<br> color: “DarkCyan”<br> backgroundColor: “#f5f5f5”<br> fontSize: 200<br> indent: 120<br> placeHolder: “Add task”<br> placeHolderFocus: “”<br> autoCapitalize: true</pre><pre># hide the input text element<br>taskInput.opacity = 0</pre><p>Now we need to handle the states. We want to show the <em>inputField</em> and the <em>keyboard</em> when the user tap on task action.<br>We already know how to proceed: create the state for <em>keyboard</em> and <em>inputField</em>, add a switch function and handle events.</p><pre># add the openInput state for keyboard and inputField<br>app.keyboard.states.add<br> openInput: { opacity: 1; y: deviceHeight — app.keyboard.height}<br>app.keyboard.states.animationOptions = { curve: “linear”, time: 0.1 }</pre><pre>taskInput.states.add<br> openInput: { opacity: 1 }<br>taskInput.states.animationOptions = curve: “spring(400, 20, 0)”</pre><pre># handle state switch<br>switchInput = (state) -&gt;<br> taskInput.states.switch(state)<br> app.keyboard.states.switch(state)</pre><pre># by tapping task action we open the inputField and keyboard<br>app.action2.on Events.Click, -&gt;<br> switchInput(“openInput”)</pre><pre># tap on the keyboard, default!<br>app.keyboard.on Events.Click, -&gt;<br> switchInput(“default”)<br> switchOptions(“default”)</pre><p>That’s all folks! Our prototype is ready to be tested, below the complete <em>app.coffee</em> sample code.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/973320d3f2813aa82d68fcc61c5210a0/href">https://medium.com/media/973320d3f2813aa82d68fcc61c5210a0/href</a></iframe><h3>Publishing our demo on Heroku</h3><p>You need an active Heroku account (<a href="https://signup.heroku.com/">https://signup.heroku.com/</a>), it’s free but with some limitations. Create your account and then you can install heroku-toolbelt.</p><pre>$ brew install heroku-toolbelt<br>$ heroku login<br>$ cd ux-framer-prototype</pre><p>Create the app and start a Git repository.</p><pre>$ git init`<br>$ git add .<br>$ git commit -am “starting!”<br>$ heroku create *app-name*</pre><p>We serve static files using <a href="http://harpjs.com/">Harp</a>, we use a super simple configuration but if you want to learn more take a look at the <a href="http://harpjs.com/docs/">documentation</a>. You can modify the sample <em>_harp.json </em>where we just define a BasicAuth access.</p><pre>{<br> “basicAuth”: “user:password”<br>}</pre><p>In order to make things working on Heroku we provide a Procfile that defines how to start our application on Heroku.</p><pre>web: harp server ./build — port $PORT</pre><p>Again, we use Git to add modifications in our repo and then we will push our prototype on Heroku.</p><pre>$ git add .<br>$ git commit -am “configured harp server and added Procfile”<br>$ git push heroku master`</pre><p>Just hit the following command to start the app and test your prototype.</p><pre>$ heroku open --app *app-name*</pre><h3>Conclusions</h3><p>I love Framer ’cause it gives us super-powers to animate our designs. It’s not the definitive tool, of course, but with JavaScript we can extend our projects and play with prototypes in a clever way.</p><p>Comments, ideas and suggestions are very appreciated. I’ve a lot of ideas to improve this <em>“framework” </em>for rapid prototyping, but yours are very welcome and if you want to collaborate just drop me a line.</p><p><strong>Credits and inspiration<br></strong><a href="https://medium.com/framer-prototyping/new-to-framer-just-3-things-to-get-you-started-47397f27c71e#.y1cm3ocqr"><em>New to Framer? Just 3 Things to Get You Started</em></a> by <a href="https://medium.com/u/c668900331c3">David Lee</a><br><a href="https://medium.com/framer-prototyping/framer-js-for-people-who-think-things-like-framer-js-are-weird-and-hard-add2068c8114#.jvg81pqxv"><em>Framer.js for people who think things like Framer.js are weird and hard</em></a> by <a href="https://medium.com/u/c67715e3ddf9">Sean Mateer</a><br><a href="http://www.darrinhenein.com/rapid-prototyping-part-one/"><em>Rapid Prototyping with Gulp, Framer.js and Sketch</em></a> by <a href="http://www.darrinhenein.com/">Darrin Henein</a></p><p>Thank you to <a href="https://github.com/turbometalskater">Walter</a>, <a href="https://it.linkedin.com/in/matteo-poile-89a3a016">Matteo</a> and <a href="https://it.linkedin.com/in/risinglf">Luca</a> for the help.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fupscri.be%2Ff51076%3Fas_embed%3Dtrue&amp;dntp=1&amp;url=https%3A%2F%2Fupscri.be%2Ff51076%2F&amp;image=http%3A%2F%2Fapi.screenshotlayer.com%2Fapi%2Fcapture%3Faccess_key%3Dfe59908dad3baab69ffab249a2224b03%26viewport%3D1024x612%26width%3D1000%26url%3Dhttps%253A%252F%252Fupscri.be%252Ff51076%253Fscreenshot&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=upscri" width="800" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/b85dfbb5286d8a25cf2e754b9462cf45/href">https://medium.com/media/b85dfbb5286d8a25cf2e754b9462cf45/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cc2e8484e4b7" width="1" height="1" alt=""><hr><p><a href="https://blog.prototypr.io/automate-your-ux-design-workflow-with-framer-js-gulp-and-sketch-cc2e8484e4b7">Automate your UX Design workflow with Framer.js, Gulp and Sketch</a> was originally published in <a href="https://blog.prototypr.io">Prototypr</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>