<?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[Unexpected Token - Medium]]></title>
        <description><![CDATA[Bi-monthly stories about code, tech and shared experiences. For developers. UT is brought to your by eFounders.co — startup studio building great SaaS startups. - Medium]]></description>
        <link>https://medium.com/unexpected-token?source=rss----2d2624499d2---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Unexpected Token - Medium</title>
            <link>https://medium.com/unexpected-token?source=rss----2d2624499d2---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 11 May 2026 16:54:16 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/unexpected-token" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[The (perfect) startup story of Wit.ai, acquired by Facebook in 21 months]]></title>
            <link>https://medium.com/unexpected-token/the-perfect-startup-story-of-wit-ai-acquired-by-facebook-in-21-months-1bf35b996808?source=rss----2d2624499d2---4</link>
            <guid isPermaLink="false">https://medium.com/p/1bf35b996808</guid>
            <category><![CDATA[entrepreneurship]]></category>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[facebook]]></category>
            <dc:creator><![CDATA[Rachel Vanier]]></dc:creator>
            <pubDate>Fri, 06 Nov 2015 14:59:50 GMT</pubDate>
            <atom:updated>2015-12-08T11:13:33.205Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/400/1*oiEb0ddcQdNrPkv7wt58Bg.png" /></figure><p>You don’t often get to meet a co-founder of a startup that follows, by all means, the “perfect successful startup” path. And by “perfect startup”, I mean the kind of startup that goes by the book. And by “the book”, I mostly mean Paul Graham’s essays.</p><p>I met <a href="https://twitter.com/lxbrun">Alexandre Lebrun</a>, co-founder of <a href="https://wit.ai/">Wit.ai</a>, an AI platform that makes it easy for developers to create apps that users can talk to. He holds a degree from a top engineering school. He started his startup while he was living in Palo Alto. He had previous experience in the field. He built the app and launched it early on Hacker News. The app got traction. The team got into <a href="http://www.ycombinator.com/">Y Combinator</a>. They raised $3M after the Demo Day, with one of the most prestigious VCs (<a href="http://a16z.com/">Andreessen Horowitz</a>). 9 months later, they got acquired by Facebook.</p><p>Here you go. Perfect startup story. What is even more surprising is that when I asked Alexandre: <strong>“Your startup seems to be super successful from day 1, is that so?”</strong> his answer was:</p><p><strong><em>“Well… yes”.</em></strong></p><h4>Don’t worry, there is a “but”</h4><p>I was more looking for a “don’t be desperate, there are downsides behind all this, success <em>never</em> comes without struggle” kind of testimony. In reality, Wit.ai does indeed follow the success path from day 1, but it’s only because Wit.ai is Alexandre’s <em>second</em> startup. The story of his first venture, VirtuOz, involves many more mistakes that he learned from.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/601/1*5NCWr_yenKqlf2wl9S08QQ.jpeg" /><figcaption>Founders Alex Lebrun, Laurent Landowski and Willy Blandin</figcaption></figure><h3>Doing things right the second time around</h3><p>The story of Alex as an entrepreneur started in 2002, when he decided to launch <a href="https://www.crunchbase.com/organization/virtuoz">VirtuOz</a> in Paris. As an engineer passionate with voice recognition and artificial intelligence, his dream had always been to make robots understand human language. Inspired by chatterbots’ pioneers like Joseph Weizenbaum — who created <a href="https://en.wikipedia.org/wiki/ELIZA">ELIZA</a> in 1966 — he imagined a solution much similar to Siri. Back in 2002, building Siri was impossible, both from the technological and business perspective. Right after the Internet bubble burst, he decided he would focus on a more profitable venture, and started VirtuOz as a virtual assistant technology for businesses’ customer service.</p><h3>Alex Lebrun’s first startup VirtuOz’s story (and struggle)</h3><p>It took VirtuOz’s team 3 whole years before landing their first client, in 2005: VoyagesSncf.com, the biggest online travel agency in France. It was their lucky year: they also raised $1,6M. In 2007, they decided to move to the U.S to explore business opportunities as they realized the French market was too small — the tech team remained in France. They soon realized that selling a product to AOL, Ebay, and other big players required much more than a nice product: you need to have a local data center, a 24h/24 customer support, huge sales teams, etc.</p><p>Nevertheless, VirtuOz managed to raise a round of funding of $12M in August 2008 — literally days before the fall of Lehman Brothers — with Silicon Valley investors. Because the new company’s scale required more structured operations and financial reporting to investors, and because Alex felt more like focusing on the product, he decided it would be wiser to hire a “professional” CEO.</p><p>His feeling was that the “Eric-Schmidt model” at Google was a smart one and that they could make it work at VirtuOz. He ended up realizing that what works at Google doesn’t necessary elsewhere. There was a huge mismatch between the newly appointed CEO — and the VPs brought along — and the rest of the team, in terms of culture and product understanding. As VP of Advanced Technology, Alex realized that he was no longer in power and did not feel he belonged within his own company — he took a year-long sabbatical, after which the board re-appointed him as CEO, in June 2012.</p><p>In the meantime, the culture had already changed and what he left a “startup” had turned into a 70-people company selling enterprise software. Alex decided to reorganize the team and launch a new product which ultimately lead him to sell VirtuOz to Nuance Communications in January 2013.</p><p>After the acquisition, and after he made sure the transition went smoothly, Alex went back on track and decided to launch a new venture, focusing on an issue he witnessed: <strong>on the one hand, there was a huge demand for machines’ comprehension of human language (written and spoken), on the other hand, there were only custom solutions made for big companies (with big costs)</strong>. What is there were an API for developers that could give them the capacity to understand human language?</p><blockquote>“After selling VirtuOz, I felt nostalgic of the “garage” period and decided to launch a new startup”</blockquote><p>After spending ten years building and growing VirtuOz, Alex launched Wit.ai — a fully open API for voice recognition and language understanding, based on machine learning, and inspired by open models like Stripe and Twilio. He started coding it with his co-founder <a href="https://twitter.com/blandw">Willy Blandin</a> in April 2013. Wit.ai was acquired by Facebook in January 2015. Here are a few things that helped making things right the second time around.</p><h3>Spending time in non-important stuff VS building a product</h3><p>The first thing that Alex did completely differently is that he did not spend a second on unnecessary tasks. He and his co-founder spent 6 months coding, period. Their company was not incorporated, had no office and no money, even when they applied to Y Combinator.</p><p>In his previous venture, Alex had lost an incredible amount of time in paperwork, renting offices, trying to raise funds before even having a single client — a mistake he would not replicate.</p><p>Similarly, he had waited much too long for a perfect product before looking for his first users. With Wit.ai, he forced himself — and his co-founder — to launch the product as soon as possible on HackerNews. It was an alpha version, far from what they would be satisfied with, but it was operational.</p><blockquote>“It was a struggle to overcome the feeling that our product wasn’t ready before launching on HackerNews, but I knew we needed to confirm there was a need for our solution as early as possible”.</blockquote><p>Wit.ai remained on HN’s homepage #1 position for 24 hours and they became a small phenomenon in the Valley. By the time they applied to Y Combinator, they already had 3,000 developers using the API.</p><h3>Doing Enterprise Sales from the start VS Focusing on SaaS</h3><p>When building a SaaS product, it is very tempting to sign major contracts with big players early on: it gives financial comfort, you <em>feel</em> it gives you business legitimacy, and it’s kind of flattering. That’s what Alex did with VirtuOz, and he learned not to do it again: when your SaaS startup is still young, you need to focus on building your own product. Larger accounts will ask for many custom features, a fully dedicated account manager, and ultimately distract you from building a scalable product that can be used by anyone.</p><p>That’s why when Wit.ai launched and Alex got meeting requests from big players, he refused in order to focus on building his product. With VirtuOz, he spent entire days with tech consulting firms without making a single dollar. With Wit.ai, he would rather debug 1 indie developer on the other end of the world for hours if it meant making the product better, than working with a multi-national.</p><blockquote>“If you can afford to say “no” to big clients and partnerships, i.e. if you don’t have investors’ pressure or huge costs, and if you want your product to be used by the many, I’d say don’t sign the big contracts and focus on building a scalable startup.”</blockquote><p>Alex was so convinced of his vision that he wanted to build a startup truly used by millions that he would rather fail than becoming a consulting business for big customers. According to him, <em>time</em> is an entrepreneur’s most important asset: if you develop fast, you can take greater risks — funnily enough, “Fail fast” is one of Facebook’s mantras.</p><h3>Launching a startup in France VS San Francisco</h3><p>Surprisingly — for me! — Alex remains pretty certain that you can start your startup from anywhere and do not need to be in the Valley from day 1. According to him, it’s all a matter of personal context. He could never have started VirtuOz in the U.S in 2002, and launching in France had its advantage at the time: he was able to raise €100k with family and friends, which would have been impossible in the Valley. The recruitment was made much easier, especially for tech profiles.</p><p>When he launched Wit.ai, he already was in Palo Alto, which of course, also had its advantages. For instance, when he launched on HN, he asked in the comments if anyone could welcome him and his co-founder to their office, as they were working from home. 10 min later, the founder of Pebble offered them 2 desks, to use Pebble’s office, network, snacks, meeting rooms etc. for free, and Wit.ai stayed there for 6 months, up until it was a 6-engineer company!</p><p>There are many tactical mistakes you can make when your startup has offices both in the US and France, says Alex. For instance, having a modern, powerful teleconference system in every meeting room is key. It’s also important to have people from both offices travel to the other office from time to time, in order to build personal relationship that will prove important in stressful times. But these tactical mistakes don’t impact the broader vision.</p><p>From those lessons learned, Wit.ai followed an impressive path of growth and ultimately got acquired by Facebook. While Alex was constantly refusing meetings with the corporate development teams of potential acquirers, when David Marcus (i.e Facebook Messenger lead and previously CEO of Paypal) contacted him, he accepted the meeting, which led to the deal. For Wit.ai, Facebook was a great opportunity to work with an incredible A.I research team, great resources, and a much larger scale, says Alex. The acquisition was announced on January 5, 2015, and Alex has since remained head of Wit.ai which still exists inside Facebook, with a team of 10 engineers. They strongly contributed to the debut <a href="https://www.facebook.com/Davemarcus/posts/10156070660595195">of “M”</a> last August, and will continue to work on Facebook’s A.I projects.</p><p>When you look at the story of Wit.ai in hindsight, the crazy 21-months startup success took Alex a decade of entrepreneur experience — and a great co-founder, he adds — to build. It is because Wit.ai is a product built by expert founders, passionate about their fields, who put their product in the hands of users very early on, and solved a real issue, that it was so successful.</p><p>Thanks Alex for this great lesson of humility and hard work!</p><p><em>This article is part of the publication </em><a href="https://medium.com/unexpected-token"><em>Unexpected Token</em></a><em> powered by </em><a href="http://efounders.co/"><em>eFounders</em></a><em> — startup studio building SaaS startups. We have a very cool Hacker Program, learn more and apply </em><a href="http://efounders.co/hackers"><em>here</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1bf35b996808" width="1" height="1" alt=""><hr><p><a href="https://medium.com/unexpected-token/the-perfect-startup-story-of-wit-ai-acquired-by-facebook-in-21-months-1bf35b996808">The (perfect) startup story of Wit.ai, acquired by Facebook in 21 months</a> was originally published in <a href="https://medium.com/unexpected-token">Unexpected Token</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Mention’s CTO journey to 400,000 users]]></title>
            <link>https://medium.com/unexpected-token/mention-s-cto-journey-to-400-000-users-f22dc242eec?source=rss----2d2624499d2---4</link>
            <guid isPermaLink="false">https://medium.com/p/f22dc242eec</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[tech]]></category>
            <dc:creator><![CDATA[Hexa]]></dc:creator>
            <pubDate>Thu, 22 Oct 2015 12:17:15 GMT</pubDate>
            <atom:updated>2015-11-06T13:02:55.780Z</atom:updated>
            <content:encoded><![CDATA[<p><a href="https://mention.com/">Mention</a> is a real-time monitoring application used to track and analyze trends and e-reputation in a very complete and intuitive way. Co-founded in 2010, it now counts 400,000 users across the world. This impressive growth rate not only implies great marketing talent but also impressive technical achievements. <a href="https://twitter.com/arnaud_lb">Arnaud le Blanc</a>, Mention’s co-founder and CTO, tells us about how he got Mention there.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*xFThwueDTsiigFGByJ5w1w.png" /></figure><h4>You gotta love technical challenges</h4><p>“When we developed Mention, our main competitor was Google Alerts, which feels a little like being David versus Goliath at first. But then it became one of the reasons I like my job: it is very challenging. Getting to this point of a product development involves a true entrepreneurial mindset. Before being Mention’s CTO, I was a developer and then the lead developer working on the media monitoring feature at Pressking. eFounders offered me to become Mention’s co-founder. I might not have thought of myself as an entrepreneur before, although today, I really feel like Mention is my product: I’ve built it together with my co-founders.</p><p>Building an application like Mention is full of technical challenges. We handle a large amount of data, crawl thousands of web page per second, built an open API for our own apps, and use lots of third-party APIs.”</p><blockquote><strong><em>FOCUS: a challenge overcome when developing Mention’s web crawler</em></strong><em> Since Mention crawls a large amount of web pages in parallel, there is a point when the crawler reaches a high concurrency level and stresses the OS: that is when we got to the limit of our system. In our case, these limits entailed the appearance of a race condition in the libc’s DNS resolver. libc was sending over DNS queries on random unrelated file descriptors, which was leading to weird behaviors. The bug was </em><a href="https://sourceware.org/bugzilla/show_bug.cgi?id=15946"><em>reported</em></a><em> and fixed a few months later, but in the meantime, we had to use the plain-Go DNS resolve, which happened to work really well.</em></blockquote><p>“At Mention, several millions of Mentions are inserted in user feeds per day (see infographics above). Therefore, storage of data is an important issue with our product and entails. We chose MySQL as our main storage system, which is well understood and scalable. We are also using Redis, as a cache, and Kafka for messaging.”</p><blockquote><strong><em>FOCUS: Mention’s main storage runs on Percona MySQL servers:</em></strong></blockquote><blockquote>MySQL servers have a small layer of SSD caches (using flashcache)</blockquote><blockquote>Incremental backups using Percona Xtrabackup</blockquote><blockquote>Backups automatically checked everyday (loaded in a mysql server, queries ran against it)</blockquote><blockquote>Sharding for horizontal scalability</blockquote><blockquote>Sharding is done at the application level</blockquote><blockquote>Replication for high availability</blockquote><blockquote>Applications never read on slave servers — eventual consistency makes code eventually complex</blockquote><blockquote>Occasionally using slaves for large queries, dumps, etc</blockquote><blockquote>One of the shard groups stores 4.5B rows, 5TB of compressed data</blockquote><blockquote>Redis for small caches or data structures</blockquote><blockquote>40-nodes Cassandra cluster for the Crawler’s internal state</blockquote><p>“Building a product that works in the long term is key to success, according to me. That is why we focused on that from the beginning, especially in the choice of our technologies and the architecture. We have chosen <strong>proven technologies for the most critical parts of our infrastructure.</strong> For instance we choose MySQL for our main storage, which is proven to work well for I/O bound workloads — that impacts the volume of data our tool is capable of handling — and has well-understood performance characteristics.</p><p>On the other hand, sometimes we needed to use more <strong>bleeding-edge technologies </strong>such as Golang. We like to use the right techno for the right task, and Golang is outstanding at writing highly concurrent code doing lots of I/O. Choosing bleeding-edge technologies is risky because you never known how it will evolve, or if it will still be alive in 2 years. For the anecdote: when we built Mention, AngularJS or React — today’s references — virtually didn’t exist. Therefore, we are using Backbone.js for our frontend: among all the libraries that existed at the time, it is basically the only one that remains alive.”</p><blockquote>GNU/Linux Debian distro.</blockquote><blockquote>RAID everywhere. RAID1 for normal servers and RAID6 for backup.</blockquote><blockquote>MySQL, Kafka, Redis</blockquote><blockquote>PHP, Golang, Python, NodeJs</blockquote><blockquote>We are Monitoring them using StatsD, Graphite, Zabbix.</blockquote><p><em>This article is part of the publication </em><a href="https://medium.com/unexpected-token"><em>Unexpected Token</em></a><em> powered by </em><a href="http://efounders.co/"><em>eFounders</em></a><em> — startup studio. All eFounders’ startups are built by extraordinary CTOs. If you feel like it could be you, </em><a href="http://efounders.co/cto"><em>apply here</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f22dc242eec" width="1" height="1" alt=""><hr><p><a href="https://medium.com/unexpected-token/mention-s-cto-journey-to-400-000-users-f22dc242eec">Mention’s CTO journey to 400,000 users</a> was originally published in <a href="https://medium.com/unexpected-token">Unexpected Token</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The story of the guy who sold his startup to Box in 7 months]]></title>
            <link>https://medium.com/unexpected-token/the-story-of-the-guy-who-sold-his-startup-to-box-in-7-months-458739894945?source=rss----2d2624499d2---4</link>
            <guid isPermaLink="false">https://medium.com/p/458739894945</guid>
            <category><![CDATA[engineering]]></category>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[entrepreneurship]]></category>
            <dc:creator><![CDATA[Hexa]]></dc:creator>
            <pubDate>Thu, 15 Oct 2015 17:49:43 GMT</pubDate>
            <atom:updated>2015-10-15T18:39:01.848Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/400/1*LCo4ZQzUNT7hM-EUYbkPlQ.jpeg" /><figcaption>Martin Destagnol, him-self</figcaption></figure><h4>…And then became Director of Mobile</h4><p>Remember back in 2013, when reading files on “mobile” was new and everyone was wondering how the h*ck to do it? That’s when Martin Destagnol, entrepreneur and engineer, built Folders. And <em>seven</em> months laters, Folders got acquired by Aaron Levie’s <a href="https://www.box.com/">Box</a>.</p><p>Destagnol is now Director of Mobile and of Box Notes — the French “serial” “startuper” went from building a product in his apartment (we don’t get many garages in Paris) to managing a whole engineering team inside one of the fastest-growing startups in the Silicon Valley. How does one do that? Here’s the story.</p><h3>Startup genesis and crazy-fast acquisition</h3><p>As you might hear often times when wondering why an entrepreneur built a startup, Folders came from Martin’s own frustration: accessing cloud-stored files on mobile was just a pain. So he decided to build an iOS client providing the very best User Experience possible.</p><p>But Destagnol also brought a strong business rationale to the idea: as Folders was his 3rd startup, he knew what kind of risk he was willing to take and what outcome to expect. His previous company, Plyce, was a social network based on coupons, which had a great potential but also high risks. When coming up with Folders, his ambition was to build a product much more targeted, with higher chances of a “smaller scale” success. The bet was that one of the existing cloud providers could need a product like Folders; worst case scenario, he would still sell enough to make up for the money invested.</p><p>Then he shut down everything else but work, and built Folder in 7 months. Full time. Like, 24/7. As in <em>100%</em> of the time.</p><p>Once the app was approved by the Apple store, Destagnol decided to come to San Francisco to show it to Box, Dropbox and Google Drive. The product wasn’t launched, but he figured the sooner he would show it to the big players to get their feedback, the better — for those of you who are reading from elsewhere than San Francisco, yes, that’s what happens here, you can just meet people like that. Hence Destagnol coming; although to be fair, he had some introductions.</p><p>Right after his first meetings with the platform and mobile teams at Box, they asked him if he could stay a little longer to show it to some additional people. They all clicked instantly, and at that point, Destagnol had figured out this meeting was actually going somewhere.</p><p>During the same day, Martin met with 13 different people including Aaron Levie, Box’s CEO, Sam Schillace, SVP of Engineering and Sam Ghods, CTO, who were freaking out over how great the features and UX of Folders were. When Box offered to acquire Folders, Martin knew instantly that it would actually happen: that’s “entrepreneur’s intuition”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mNndCb3VdAbgpJTZFcXzag.jpeg" /><figcaption>source: Techcrunch</figcaption></figure><h4>How can you make a cloud content reader app so cool, the CEO of “<em>the”</em> cloud content manager company thought it was impossible?</h4><p>Today, Folders’ first features seem pretty obvious: fast picture loading, folder offline saving, snappy interface. But at the time, other products simply did not have them; in bigger companies, the back-and-forth movement between the product team and the engineering team takes a lot of time and energy. Product people make requests to the Tech team, the Tech team knows what’s possible or not, but does not necessarily have the overall vision. Destagnol had all the skills and was super detail-oriented; that’s how he managed to build the best UX, faster than them.</p><h3></h3><p></p><p><em>(tweet found, of course, via </em><a href="https://www.rudebaguette.com/2013/05/23/box-acquires-startup-folders-literally-right-out-of-the-box/"><em>RudeBaguette</em></a><em>)</em></p><blockquote>Secret formula (don’t tell anyone)</blockquote><blockquote>[Personal Frustration + Business rationale] * hard work + entrepreneur intuition = Successful startup</blockquote><h3>How a hands-on builder becomes a manager at scale</h3><p>When Destagnol joined Box, he started as a manager, and got <em>carte blanche</em> on re-building the whole iOS app for Box with a team of 10 people- and the opportunity to go up the ladder pretty fast.</p><p>Destagnol was basically coming to re-build everything using his ideas, which was potentially frustrating for the existing team. So Destagnol pushed the team to restart from a blank page together. They looked at each features and decided to take the best from both sides. That way, they all felt like they were part of a common project, and every engineer felt as if they were the owner of the decisions being made.</p><p>After a successful launch of the iOS app, Box asked Destagnol to do the same thing with Android as well. So when the annual review period arrived, Destagnol was pretty sure he would get promoted. After all, he had de-facto doubled the size of his team and had 2 successful launches. But he didn’t. And he was extremely disappointed about it.</p><p>When he discussed his non-promotion with Sam Schillace, SVP of Engineering at Box and former creator of Google Docs, Sam told him: “<em>If we had promoted you, you would have become an assh*le</em>” (he eventually became Destagnol’s mentor and they get along very well, in case you were worried).</p><p>“<em>It may sound harsh, but this was the most valuable feedback I ever received, and it really transformed the way he was thinking about leadership</em>” he says.</p><p>When you’re initially a hands-on manager, like Destagnol, it’s actually a huge challenge to learn to scale and delegate. What works when you are a small team doesn’t work anymore as you grow. He learned that it was not O.K to break an existing dynamics in a team, just to get results. Nor was it O.K to decide things by himself without bringing the team along with him. He had achieved outstanding results, but this had also led the product manager and designer to leave the company; so, even though the app launches went really well, there <em>was</em> an issue.</p><h4>How to not be an assh*le and still be an effective manager, then?</h4><p>For the next 6 months, after his reality check, Destagnol relied much more on his team to make decisions and was there only as a last resort. As a result, the team stepped up and felt more involved, and Destagnol got a lot more time to take on new initiatives. Destagnol started working with the Box Notes group and was promoted twice in a year. He now leads the iOS, Android, Windows and Box Notes teams, which represent more than 30 engineers and managers.</p><p>In a highly competitive atmosphere like the Valley, where every company is struggling to hire qualified people, it’s critical that Destagnol maintains a happy and productive team. For that, he makes sure to define a sense of purpose for each individual, which is a combination of many different things: how you believe in your company’s vision, how your own team contributes to it, what do you personally bring to it, how what you do is aligned with your career goals, how you get along with your teammates, etc.</p><p>All of these dimensions matter and every retention issue is related in a way or another to this sense of purpose. Destagnol and his managers make sure they talk openly and candidly with each teammate every week, so that can quickly identify issues and elaborate improvement plans with them.</p><p>“<em>When questions are asked the right way, 90% of the action plan actually comes from the employee himself</em>”, he says —” <em>the extra 10% comes from the good manager</em>”. In addition, Destagnol makes sure he is always reachable for anyone, especially as humility is a strong part of Box’s company culture.</p><p>Being a manager “at scale”, for Destagnol, means witnessing people growing around you. A manager’s own performance doesn’t matter, it’s his/her team’s that’s important. In a nutshell, Destagnol realized that a good manager makes himself optional.</p><p>Thanks Martin for this inspiring conversation. I hope this has encouraged you, other readers, to build your own. If’s it’s the case, see you back 7 months!</p><p>Interview + article by our Content Manager @VanierRachel</p><blockquote>This article is part of the publication <a href="https://medium.com/unexpected-token">Unexpected Token</a> powered by <a href="http://efounders.co/">eFounders</a> — startup studio. All eFounders’ startups are built by extraordinary CTOs. If you feel like it could be you,<a href="http://efounders.co/jobs?utm_source=UT&amp;utm_medium=UT&amp;utm_campaign=UT"> apply here</a>.</blockquote><blockquote>Did you like it? Hit “Recommend” and subscribe to our collection!</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=458739894945" width="1" height="1" alt=""><hr><p><a href="https://medium.com/unexpected-token/the-story-of-the-guy-who-sold-his-startup-to-box-in-7-months-458739894945">The story of the guy who sold his startup to Box in 7 months</a> was originally published in <a href="https://medium.com/unexpected-token">Unexpected Token</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How we scaled Wisembly’s infrastructure : moving from our Elephant to RabbitMQ]]></title>
            <link>https://medium.com/unexpected-token/how-we-scaled-wisembly-s-infrastructure-moving-from-our-elephant-to-rabbitmq-282e1fba68ed?source=rss----2d2624499d2---4</link>
            <guid isPermaLink="false">https://medium.com/p/282e1fba68ed</guid>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[growth]]></category>
            <category><![CDATA[tech]]></category>
            <dc:creator><![CDATA[Guillaume POTIER]]></dc:creator>
            <pubDate>Thu, 02 Jul 2015 13:31:56 GMT</pubDate>
            <atom:updated>2015-10-15T18:48:16.694Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7IpjF6Qa3jv8mhk5KIo-cQ.jpeg" /></figure><p>Hi, I’m Guillaume, I am the CTO and co-founder of <a href="http://wisembly.com/">Wisembly</a>, a SaaS solution facilitating interactions during your big meetings and events. We recently launched a beta of our new product: <a href="http://getsolid.io/?utm_source=medium&amp;utm_medium=referral&amp;utm_campaign=unexpectedtoken">Solid</a> to help you make your every-day-meetings more productive and actionable.</p><p>This is the story of how we improved our performance by changing and adding elements to our stack over the time. I’ll particularly focus on how using RabbitMQ on the backend to communicate between different stack and servers improved our life.</p><h3>Where we once were</h3><p>Here are the building blocks for our tech team’s philosophy: start small, DRY (Don’t Repeat Yourself) and YAGNI (You Ain’t Gonna Need It). Back in 2012, when we implemented real-time websockets communications with <a href="https://gist.github.com/efounders/0674b22e404a3638a9e0/nodejs.org">Node.js</a> and <a href="https://gist.github.com/efounders/0674b22e404a3638a9e0/socket.io">Socket.io</a>, we had a pretty small stack: everything fullstack on <a href="https://gist.github.com/efounders/0674b22e404a3638a9e0/symfony.com">Symfony2</a> with MySQL as single storage and some tiny parts of <a href="http://backbonejs.org/">Backbone.js</a> here and there to power up our application. One year later I presented <a href="http://fr.slideshare.net/guillaumepotier/symfony2-ba">these slides</a> at the Symfony2 Live Paris 2013 explaining how we implemented <a href="https://github.com/wisembly/elephant.io">Elephant</a> in raw PHP to communicate from our Symfony2 backend with our distant socket.io push server.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.slideshare.net%2Fslideshow%2Fembed_code%2Fkey%2FgThM9WMSy1xQu8&amp;url=http%3A%2F%2Ffr.slideshare.net%2Fguillaumepotier%2Fsymfony2-ba&amp;image=http%3A%2F%2Fcdn.slidesharecdn.com%2Fss_thumbnails%2Fsfliveparis2k13wisemblyfinal-130404093013-phpapp02-thumbnail-4.jpg%3Fcb%3D1370491088&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=slideshare" width="425" height="355" frameborder="0" scrolling="no"><a href="https://medium.com/media/dfdfc12635e346b3ceb1b2838fda5808/href">https://medium.com/media/dfdfc12635e346b3ceb1b2838fda5808/href</a></iframe><p>As I said, our stack was pretty minimal at the time. We didn’t feel the need to complexify it for the sake of the socket.io push server. So we looked at websockets and found a pretty way to implement them, connect and emit events with our Open Source library. It did the job, we open-sourced something cool (more than 500 stargazers now and still active!), on our way to live <em>happily ever after :)</em>… Or did we?</p><h3>Where we are now</h3><p>Quite recently, as the business was growing, more and more push events were sent every minute on the various customer meetings we handle daily. For example, we have a specific feature for very interactive seminars where more than 500 users can answer a live poll. Oftentimes, all the attendees submit their answers during the same 10-to-20-second time window, right after the poll is launched by the presenter. Aside from some MySQL resource concurrency problems (deadlocks) we had to deal with our friend Redis (that’s another story we might tell another time). We also had to deal with server pressure, as you can guess.</p><p>We had pretty shitty response time from our API. Skyrocketing from an average of 125 ms to ~350 ms, some time even more! The process was putting much pressure on php-fpm worker that had to fork again and again, spawning many children to the configured limit to handle all the sudden workload. It jeopardized other clients who were using the solution at the same time.</p><p>We ran <a href="https://blackfire.io/">blackfire.io</a> and look deeper into <a href="http://newrelic.com/">New Relic</a> data to spot bottlenecks, and then looked at our code to find where we could improve performances. We quickly noticed that external calls to the push server through cURL with Elephant were quite time and process consuming!</p><p><em>Sh*t! </em>Suddenly we realized that we could improve code here and there, add cache or move things to Redis to reduce concurrency and improve throughput, but the push events communication layer with our beloved and loyal Elephant would still be a burden!</p><h4>Looking at our stack</h4><p>When we stumbled upon this problem, we then looked at our ways to overcome that by taking a closer look at our stack. Since 2012, we’ve had two powerful allies: Redis and RabbitMQ. Both of them are great to publish events with data and a great way to communicate between servers.</p><p>We finally chose Rabbit as we were already using it intensively with Symfony recently and the <a href="https://github.com/swarrot/swarrot">great Swarrot library</a>. In a few minutes, thanks to amqplib and 50ish new lines later in our node pusher app, we connected our node server to our Rabbit queue and added the ability to receive events through websockets AND Rabbit.</p><p>In one more hour, we created a <em>RabbitTransport</em> with the exact same interface as our <em>ElephantTransport</em>. A simple Symfony config parameter later, the push events emitted by our API were not sent through Elephant but put in a Rabbit queue instead. And like magic, there were rightfully consumed by the distant push server, and it was blazing fast.</p><h4>Performance improvements</h4><p>Alright, after 3 long years of faithful and loyal service, could we get rid of Elephant, our baby, in only 3 short hours? Let’s dive into the numbers.</p><p>Fist of all, A to Z process (time between API call and broadcasted event reception) was not affected, even slightly improved: push events are received in less than 90ms (they still are received by listening users before the user that made the action receive the API response!). This does not vary a bit, even with 1000 events fired in a second to a single user. Good.</p><p>Then, looking only at server side, let’s try to send 100 “consequent” push events to our push server. On a standard developpement machine (1,8 GHz i7 dual core, 4GB Ram):</p><ul><li>SocketTransport (with Elephant): 100 events took <strong>8936ms</strong></li><li>AmqpTransport (with RabbitMQ): 100 events took <strong>521ms</strong></li></ul><p>No typo here, you read right: about <strong>17 times faster</strong>! We did not bother measuring the CPU consumption for that, as these results were more than enough.</p><p>Quite frankly, we supposed that PHP <em>curl</em> implementation that powers the core websocket communications of Elephant was more greedy than lower level RabbitMQ implementation (we use the pecl <em>C</em> implementation for Rabbit in production that even speeds things up a bit), but to that extent…</p><p>Last thing to check: the push server’s ability to consume events stored in a single queue as fast as they come in. For now and unless we deal rooms with more with 600 users, it appears that node/amqplib/socket unstack events from the queue like a charm. Once we’ll reach a limit, we’ll think about adding more push consumers to keep the pace going.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/689/0*KJ4f-qjyZKoYWd_2." /></figure><p><em>API mean response time &lt; 100 ms after deploy, external calls (in green) reduced</em></p><h3>Where we’re heading</h3><p>This story showed us that living without Rabbit and using Elephant to keep the stack simple at the time we were 2–3 devs was acceptable and allowed us to scale our application and business in a simple way. As usage grews, the need to refactorize parts of our application as codebase gets old and stack improves are needed. But it was all possible thanks to the awesome work we did in the last months on Rabbit.</p><p>Speaking of it, we now also use it to power other parts of our application. We use Rabbit to speak with various APIs, to make things asynchronous (emails, exports, stats, document conversion, heavy jobs). For example in <a href="http://getsolid.io/?utm_source=medium&amp;utm_medium=referral&amp;utm_campaign=unexpectedtoken">Solid</a> we are able to give you stats and insights about how long you spend each year in meetings by asynchronously crunching Google or Office365 calendar APIs and push you the result once it is done.</p><p>Two years ago, we were fine living without Rabbit. Today, we couldn’t do without it.</p><p>If you’d like to see it in action, you can signup for <a href="http://getsolid.io/?utm_source=medium&amp;utm_medium=referral&amp;utm_campaign=unexpectedtoken">Solid</a> here!</p><blockquote>This article is part of the publication <a href="https://medium.com/unexpected-token">Unexpected Token</a> powered by <a href="http://efounders.co/">eFounders</a> — startup studio. All eFounders’ startups are built by extraordinary CTOs. If you feel like it could be you,<a href="http://efounders.co/jobs?utm_source=UT&amp;utm_medium=UT&amp;utm_campaign=UT"> apply here</a>.</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=282e1fba68ed" width="1" height="1" alt=""><hr><p><a href="https://medium.com/unexpected-token/how-we-scaled-wisembly-s-infrastructure-moving-from-our-elephant-to-rabbitmq-282e1fba68ed">How we scaled Wisembly’s infrastructure : moving from our Elephant to RabbitMQ</a> was originally published in <a href="https://medium.com/unexpected-token">Unexpected Token</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[5 things I’ve learned being a CTO in startups]]></title>
            <link>https://medium.com/unexpected-token/5-things-i-ve-learned-being-a-cto-in-startups-5467a5896396?source=rss----2d2624499d2---4</link>
            <guid isPermaLink="false">https://medium.com/p/5467a5896396</guid>
            <dc:creator><![CDATA[Jean-Baptiste Escoyez]]></dc:creator>
            <pubDate>Thu, 25 Jun 2015 13:58:10 GMT</pubDate>
            <atom:updated>2015-10-15T18:49:15.260Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wHP9zRSnH_oEmxxZlwQcrw.jpeg" /></figure><p>In the past 5 years, I have been Chief Technical Officer of two startups — one, GoCar has been acquired and one, Solved, has been discontinued — and helped many others as a technical advisor. What characterizes startups is that they have to ship a lot of results with limited resources. As CTO, your daily job is to lead the technical team, set the goals and take the right technical decisions. You are in a constant tradeoff of immediate speed VS long-term productivity.</p><p>In this article, I want to share 5 rules I follow in order to make my choices. So far, they enabled me to keep shipping while avoiding to pile up “technical debt”.</p><h3><strong>1. Dedicate yourself to the business</strong></h3><p>The goal of any startup is to build a solution which will bring value to its customers. There are chances that your business co-founder will spend most of his/her time talking to them and understanding their needs. On this basis, your co-founder will set the priorities and report what customers’ problems are. Your role will be to find out and build an outstanding product that provides a solution to them.</p><p>As a technical person, it is easy to get excited by a new technological challenge or a new service that looks promising. When it occurs to me, I ask myself this simple question: “What is the business outcome of what I am doing”. This way, I always know if I am working on the right priority or not.</p><p>At Solved, we even dedicated a weekly meeting with my business co-founder, Thomas, where we were reviewing the features to ensure they match the business priorities. At any moment, I and any member of my dev team could say why we were working on any feature.</p><p>In order to ensure I did a good job, I was asking myself: how will it delight our users? how will it help our startup to make money? or help our operations team? If you can also answer these questions for your own project, there are chances you are on the right track.</p><h3><strong>2. Optimize for speed and flexibility</strong></h3><p>In its early days, your startup’s main challenge is to find the product-market fit. That means that your product embryo might evolve in many different directions and it has to evolve fast. As you don’t know how long it will take to get traction, you have to balance short-term benefits as well as productivity in the long run.</p><p>At the code level, I found out that the best way to do that is to organize my code in small, reusable modules that I can assemble like Lego bricks. It enables to quickly change the business logic and the flows of the app. In order to maintain a clean codebase, I never hesitate to throw away features that are not needed anymore.</p><p>As an illustration, here our Trello Board at Solved, my previous startup:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*zuX5QmPyWAY2K_I2." /></figure><p>At the organization level, I put in place simple processes so that everybody knows what are the priorities and who is working on what. Most of the time a simple <a href="https://trello.com/">Trello</a> board with the main tasks will be enough. I make sure not to go into too much detail in order to leave room for discussion. Often times, the best ideas and the tiny details that make the difference will come from these discussions.</p><h3><strong>3. Choose the right tool for the right job</strong></h3><p>There has never been so many tools in a developer’s toolbox. You can choose to externalize most of your dev stacks or to develop every single tool yourself.</p><p>At the beginning of your project, one of your main challenges will be to choose your stack. New tools and technologies have probably emerged since your last project. Should you choose a stack you already know or try a new one?</p><p>I never underestimate this phase since it will influence the whole life of my startup. I’ve seen too many CTOs struggling because they chose the most “trending” tools without realizing what are the technical implications. It is not because everybody is using a tool that this tool will fit to one’s particular case. For every tool I consider, I do my best to understand what are the pros and the cons. If I only see pros, it is often a sign that I have not dug enough.</p><p>For instance, I hear many developers thrilled by the power of MongoDB. So much that they use it in all their projects without realizing that it lacks of some SQL DB features they might need (think of the work required to maintain many-to-many relationships in Mongo). After a year spent coding, they are not taking advantages of Mongo and start struggling because they do not find the features required by their project. If they had taken the time to understand the pros and cons of each solution, they would have chosen the right DBMS from day one.</p><p>In order to make the right choices, I take time to understand what are the specificities of my project and what tool will answer the best to these ones. I especially like to discuss with other people who have tried these tools.</p><h3><strong>4. Hire people who are more skilled than you</strong></h3><p>When it comes to hiring, you might be tempted to start with interns or junior developers since they are easier to recruit and are more affordable than senior programmers. However, with inexperienced recruits, you will end up spending more time training them than actually shipping code. Never forget your goal: being fast and flexible.</p><p>I have experienced that hiring senior developers bring way more value to startups. Since I do not have to train them, I have more time for my own responsibilities. Moreover, they bring their own knowledge, their own tools and can help the team to take better decisions.</p><p>I even try to hire developers that are better than me in domains I consider key for the startup. Since I do not know everything on every subject, I am delighted to delegate responsibilities to members of my team. However, I ensure to understand what they are doing so that I still have the big picture and can coordinate the team.</p><p>At my previous startup, I had shortlisted two candidates who fitted to the team I wanted to create: one junior and a more senior (read 1 year vs 5 years experience). Choosing <a href="https://twitter.com/seyz_">Sandro</a>, the more experienced of the two, brought our startup much more than I could have expected. In addition to its experience, he brought his maturity and his culture of effectiveness that he had acquired during his career.</p><h3><strong>5. You are the example</strong></h3><p>Never forget that the whole team is looking at you. You set the standards and best practices. Whatever you do or don’t do, your teammates will follow you.</p><p>In order to ensure everybody speaks the same voice, I set up code policies and style guides at the very beginning of the project. I strongly believe in peer code reviews. It <a href="http://smartbear.com/resources/whitepapers/best-kept-secrets-of-peer-code-review/">has been proven</a> that they help communication in company, ensure a better code quality and reduce the number of bugs. At my previous startup, the policy was “two set of eyes on every line of code”. Every commit I wrote was reviewed by Sandro and vice-versa. Instead of committing directly to master, we were doing pull requests on Github that we merged once everything was ok.</p><p>Here is an example of a typical pull-request at Solved:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*l5CDrUkrnOjg0AA2." /></figure><p>Finally, I’ve found very important to do things before delegating them. If I do not know what I am asking to my teammates, it is very difficult to discuss their choices and put the reflexion further. Even if I do not do the things as well as they would (that’s why I hired them), doing it by myself in the first place give me fine grasp of the challenges they are tackling.</p><blockquote>This article is part of the publication <a href="https://medium.com/unexpected-token">Unexpected Token</a> powered by <a href="http://efounders.co/">eFounders</a> — startup studio. All eFounders’ startups are built by extraordinary CTOs. If you feel like it could be you,<a href="http://efounders.co/jobs?utm_source=UT&amp;utm_medium=UT&amp;utm_campaign=UT"> apply here</a>.</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5467a5896396" width="1" height="1" alt=""><hr><p><a href="https://medium.com/unexpected-token/5-things-i-ve-learned-being-a-cto-in-startups-5467a5896396">5 things I’ve learned being a CTO in startups</a> was originally published in <a href="https://medium.com/unexpected-token">Unexpected Token</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[3 Takeaways from Point Nine’s CTO Event on Scaling Up Tech and Tech Teams]]></title>
            <link>https://medium.com/unexpected-token/3-takeaways-from-point-nine-s-cto-event-on-scaling-up-tech-and-tech-teams-bf617a8ec175?source=rss----2d2624499d2---4</link>
            <guid isPermaLink="false">https://medium.com/p/bf617a8ec175</guid>
            <dc:creator><![CDATA[Moritz Dausinger]]></dc:creator>
            <pubDate>Wed, 13 May 2015 15:05:17 GMT</pubDate>
            <atom:updated>2015-05-13T15:50:33.336Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/666/1*j5wTx_-vXUDDrDQcOQANcQ.png" /><figcaption>illustration by <a href="https://dribbble.com/adrien-griveau">Adrien Griveau</a></figcaption></figure><p>Last week, Point Nine Capital invited the CTOs and VPs of Engineering of their portfolio companies. The event took place in Google’s offices in Berlin. I was flattered to get invited and had the opportunity of spending the day next to great people from famous startups such as <a href="https://twitter.com/primdahl">Morten Primdahl</a>, Co-founder and CTO at Zendesk, <a href="https://twitter.com/smagiatis">Spyros Magiatis</a>, Founder and CTO at Workable, or <a href="https://twitter.com/discordianfish">Johannes Ziemke</a>, Platform Engineer at Docker.</p><h3>Nicolas Wittenborn on Twitter</h3><p>Lots of brainpower in the room at the #p9techcircle thx to @GoogleDE for the great location! pic.twitter.com/yGTZJsxgL2</p><p>The agenda was quite packed with interesting topics around scaling tech and teams. You can find the complete agenda on <a href="https://medium.com/@decodingVC/are-you-only-competing-on-product-i-don-t-think-so-4c439f9b4365">this post</a> written by <a href="https://twitter.com/decodingvc">Rodrigo Martinez</a>, who did a fantastic job organising the event.</p><p>Next to great tech-centric talks (e.g. Continuous Integration Best Practices by <a href="https://twitter.com/flomotlik">Florian Motlick</a>, CTO at Codeship, Microservices by <a href="https://twitter.com/termie">Andy Smith</a>, CTO at Werker etc.), an important subject was hiring and scaling teams. In other words: a mix of the most important topics you need to know once you have traction. And as the CTO of one of <a href="http://efounders.co">eFounders</a>’ under-development startups, this really struck a chord.</p><p>So here are my key takeaways from this meetup.</p><h3>Takeaway #1: The hardest problems when scaling up are most of the time non-tech problems</h3><p>The panel was called ‘Best Practices on Scaling Tech’, but after a couple of minutes of discussion, it became very clear that the bottleneck is mostly due to organizational challenges.</p><p>Indeed, answers to well known technical problems such as how to scale a MySQL database are available most of the time. Despite all your preparation, be ready for your 3am emergency alert, stay focus, and you’ll resolve the problem. No, your true challenges will come from human and managerial situations.</p><p>Your job as a CTO is to have a working team in place which can perform, produce and scale with the success of the startup. Hiring tech talent is increasingly difficult and even if you manage to hire, scaling a team is not trivial. You need to find the right team size and get organized in a scalable way. The success of your startup heavily relies on how good you are at that (read the <a href="https://medium.com/@decodingVC/are-you-only-competing-on-product-i-don-t-think-so-4c439f9b4365">original article</a>).</p><blockquote>The success of your startup depends on your ability to scale your tech and tech team.</blockquote><h3>Takeaway #2: Try to maintain a pipeline of talents</h3><p>According to <a href="https://twitter.com/samlbckn">Ivo Betke</a>’s Keynote, every startup should have a talent pipeline. According to the <a href="http://webcrowd.net/">Webcrowd.net</a> founder:</p><blockquote>“The average time a developer stays in a startup is down to 1.4 years in Silicon Valley and around 2 years in Berlin. It’s crucial to maintain a big network of talents.”</blockquote><p>That being said, it’s not as simple as it sounds, and you’ll probably find yourself one day at a point where you need to rely on external recruiters if you want to hire fast.</p><p>In any case — internal or external talents — you still need to follow some rules and techniques if your want to hire the best (and you sure do).</p><h4>Move very fast at the beginning of the process</h4><p>A developer gets easily hired within one week. If you don’t quickly make a decision, you might just miss out an opportunity.</p><h4>Filter your pipeline</h4><p>Instead of spending 2 hours on-premise for each candidate, start with a short Skype interview. This will allow you to talk to a lot more candidates, and filter out the ones which don’t fit the open position before engaging further with the recruiting process.</p><h4>Always make a good impression, even if you do not hire the candidate</h4><p>While this should be obvious, a lot of startups make this mistake: once they decided to not take a candidate, they forget to end the hiring process properly. Don’t forget that a candidate still has a network you could tap in.</p><h4>Stay in touch with candidates</h4><p>Follow up a couple of months after talking with a candidate. As the average time spent in a startup is quite low, you might get lucky and catch someone who actually wants to leave his current position.</p><h4>Lower the requirements on your ad</h4><p>Too many job descriptions just look like a Christmas list. Don’t put all the requirements you can think of on your advert. You might miss out on great talents by doing so, who could easily learn the missing requirements. Just keep the ones that are crucial for your company, and discuss the other ones during the Skype interview.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_NrdxRe8T8D3ai1VGo4u1g.jpeg" /></figure><p>Ivo Betke’s recipe to recruiting the best talents:</p><blockquote>Maintain a pipeline of talents, and polish your recruitment process to make a good impression and hire the best</blockquote><h3>Takeaway #3: Promote internally when it makes sense, Hire from the outside when you need to go fast</h3><p>After Ivo’s Keynote and a presentation from former CTO of Brands4Friends <a href="https://twitter.com/codemonkeyism">Stephan Schmidt</a> on building high-performance tech teams, the next panel tackled the actual scaling up of tech teams.</p><p><strong><em>To scale up your tech team, do you promote internally or recruit externally?</em></strong></p><p>My biggest wonder was concerning people development, e.g. promoting a developer to a management position. I asked if people had success stories to share on the topic.</p><p>The answers to this question were quite diverse and it seems to depend heavily on the situation.</p><p>One good example was given by <a href="https://twitter.com/wiktorschmidt">Wiktor Schmidt</a>, CEO of <a href="https://netguru.co/">Netguru</a>, who scaled his team from <a href="https://netguru.co/blog/how-we-went-from-a-team-of-50-to-100">50 to 100 developers within one year</a>. In his case, a lot of key positions are handled by early employees who grew their responsibilities together with the startup.</p><p>Another interesting thought from the panel was on considering each individual case. It is wrong to assume that all developers aim at becoming a manager at one point in their career. Actually, it’s quite the opposite: a lot of developers don’t want to manage people and aim at becoming excellent senior engineers. If that’s the case, pushing them into a management position will just make them unhappy and probably drive them away. So make sure you discuss it thoroughly before making any move.</p><p>In any case, it became clear that once you have real traction you need to grow your team really quickly. So filling up key position with external candidates might become the only realistic option.</p><blockquote>Between internal promotions and external recruitments, make sure you choose wisely and bear in mind individual aspirations.</blockquote><p>As I mentioned earlier, the day was packed with interesting Keynotes and one could easily fill several blog posts with all the takeaways. I really enjoyed the fact that keynotes and panels where around “soft” topics like hiring and team scaling.</p><p>As written in Rodrigo’s post, this kind of knowledge is not available on the usual tech platforms like StackOverflow, Quora and so on. It’s something that you build with experience — or that you want to hear directly from someone who experienced it. Having the possibility to follow up with questions was amazingly valuable to me. Definitely an event I would love to attend again if I get a chance. Thanks again Point Nine, you nailed it!</p><blockquote>Are you a programmer? Read those <a href="https://medium.com/unexpected-token/programmers-here-are-some-tips-to-be-hired-by-a-great-tech-startup-2cc38f306664">tips to be hired by a great tech startup</a>.</blockquote><blockquote>This article is part of the publication <a href="https://medium.com/unexpected-token">Unexpected Token</a> powered by <a href="http://efounders.co/">eFounders</a> — startup studio. All eFounders’ startups are built by extraordinary CTOs. If you feel like it could be you, <a href="http://efounders.co/cto">apply here</a>.</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bf617a8ec175" width="1" height="1" alt=""><hr><p><a href="https://medium.com/unexpected-token/3-takeaways-from-point-nine-s-cto-event-on-scaling-up-tech-and-tech-teams-bf617a8ec175">3 Takeaways from Point Nine’s CTO Event on Scaling Up Tech and Tech Teams</a> was originally published in <a href="https://medium.com/unexpected-token">Unexpected Token</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to organize your files on your Meteor projects]]></title>
            <link>https://medium.com/unexpected-token/how-to-organize-your-files-on-your-meteor-projects-ef7f34373ed?source=rss----2d2624499d2---4</link>
            <guid isPermaLink="false">https://medium.com/p/ef7f34373ed</guid>
            <category><![CDATA[meteorjs]]></category>
            <category><![CDATA[meteor]]></category>
            <dc:creator><![CDATA[Vianney Lecroart]]></dc:creator>
            <pubDate>Thu, 07 May 2015 15:13:56 GMT</pubDate>
            <atom:updated>2015-05-07T15:13:56.379Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*jGrdwwREz_yVyJ75Dzuf4w.png" /><figcaption>illustration by Adrien Griveau</figcaption></figure><p>I have been working on Meteor projects for more than 2 years now. I already shared the reasons of this choice in a <a href="https://medium.com/unexpected-token/how-to-make-meteor-web-apps-communicate-together-a-comparison-with-the-rest-api-method-acef91040faf">previous post</a>. Today I want to address the question of <strong>file structure</strong>.</p><p>Unlike frameworks such as Ruby on Rails, which has clear instructions on how files should be organized, <a href="http://meteor.com">Meteor</a> lets you decide how you want to structure them. It only sets a <a href="http://docs.meteor.com/#/basic/filestructure">handful of rules</a> on files priorities.</p><p>For instance, files inside a directory called <em>lib</em> are always added above all other files. Also, Meteor sorts all files in alphabetic order.</p><p>But this autonomy leaves first-time users with a lot of questions, as you can see on <a href="http://stackoverflow.com/">StackOverflow</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bNSSBReiNilVS-jkqhrmpg.png" /></figure><p>or on Meteor’s <a href="https://forums.meteor.com">forum</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*o2ODaa5o0ryinr4MHcd4qg.png" /></figure><p>Obviously, the topic is hot.</p><p><a href="http://www.meteorpedia.com/read/Abigail_Watson">Abigail Watson</a>, a well-known developer in the Meteor family, wrote an article about it. In her awesome <a href="https://github.com/awatson1978/meteor-cookbook/blob/master/table-of-contents.md">Meteor cookbook</a>, she dedicated a section to describe the different <a href="https://github.com/awatson1978/meteor-cookbook/blob/master/cookbook/filestructure.md">file structures</a>, depending on your project. As you can see, there’s more than one solution.</p><p>So, how do you set up the right structure for your project? Here are my thoughts and return on experience based on the different projects I run at <a href="http://efounders.co/">eFounders</a>.</p><h3>Why I decided not to follow the Ruby on Rails file structure</h3><p>Meteor evangelist <a href="http://@joshowens">Josh Owens</a> (if you don’t know him, he’s the guy behind Meteor news site <a href="http://crater.io/">crater.io</a>, <a href="http://www.meteorpodcast.com/">The Meteor podcast</a>, and <a href="https://meteorjs.club/">The Meteor club</a>) reuses part of the directory structure used in Ruby on Rails. But as he explained in <a href="http://joshowens.me/how-to-organize-your-meteor-js-app/">this article</a>, his main reason for doing so being “having spent 9+ years working with that framework”, it didn’t convince me (<em>no offense Josh</em>).</p><p>Going a step further, here are my reasons <em>not</em> to use the Ruby on Rails file structures.</p><p>First, it generates too many small files and directories. You end up with tenths of open tabs, and switching between tabs can very quickly become annoying.</p><p>Second, I almost always work on a specific task on a specific part of the app (let say the comment system of a blog). Therefore, I like to have all files related to this task close to each other so that I can easily find and edit them. And the Ruby on Rails structure doesn’t let me do that.</p><p>For instance, let’s take a blog. Imagine you have a commenting module and you want to display the date on which each comment was posted. To do so, you have to update 3 different files:</p><ul><li>add the date on the <em>comments</em> collection —<em> client and server</em></li><li>update the template related to the comment to display the date — <em>client side</em></li><li>update the method to insert the date on which a new comment is posted — <em>server side</em></li></ul><p>In a typical Ruby on Rails structure, you will have to dig through 3 different paths spread across the project to find those 3 files. I prefer opting for the easy way.</p><p>Let me share with you 3 optimal structures on Meteor.</p><h3>Three file structures I use and recommend, based on the size of your project</h3><h4>Flat organization</h4><p>For a small project, Meteor lets you use a pretty simple file structure. When you create a <a href="https://github.com/meteor/meteor/tree/devel/tools/skel">new empty project</a>, it will generate:</p><ul><li>one single <em>.js</em> file with your entire code (client and server)</li><li>one <em>.html</em> with all html</li><li>one <em>.css</em> with all the styles</li></ul><p>Here’s how it looks:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/223/1*SBSXBjUql4WyofKrayTRaA.jpeg" /></figure><p>While it’s often enough when you create simple packages, I strongly recommend splitting files in a more structured way for more complex projects.</p><h4>Package Oriented</h4><p>For big or open source projects such as <a href="https://github.com/TelescopeJS/Telescope/tree/master/packages">Telescope</a>, the ultimate solution is to use packages to split functionalities. This method gives you the flexibility to decide to use some features or not and to manage dependencies between packages.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/440/1*OizMz446x1RQYm0Xau5P2w.jpeg" /></figure><p>As Meteor says in its documentation:</p><blockquote><em>This is the ultimate in code separation, modularity, and reusability. If you put the code for each feature in a separate package, the code for one feature won’t be able to access the code for the other feature except through exports, making every dependency explicit. This also allows for the easiest independent testing of features. You can also publish the packages and use them in multiple apps with meteor add.</em></blockquote><p>Indeed, it is the ultimate solution, but it also takes more a time to create, update and manage those packages. For instance, each time you want to add a file, you will need to update <em>package.js </em>to include this new file. Same goes for file editing, removing, etc.</p><p>As you can see, maintenance can be pretty heavy and time-consuming. Therefore, for my latest big project for eFounders, I implemented an intermediary approach, splitting files by features or module.</p><h4>Module Oriented</h4><p>Keeping the same example as above, all files linked to the ‘comments’ module of my blog will be stored close to each other. You can find them and access to the code in a heartbeat, as in the ‘package oriented’ approach.</p><p>However, this method gets rid of the <em>package.js </em>file, thus it becomes as simple as the “flat organization” of files as described above.</p><p>Here is how it looks like:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/222/1*IbNvwQPGwC_dampinKPutA.png" /></figure><p>As you can see, all files related to the module <em>banq</em> are now together. Each file contains the code for a specific Meteor system, one for <em>events</em>, one for <em>helpers</em>, one for <em>collection</em>, one for <em>publish</em>, ...</p><blockquote>A “module oriented” file structure balances easy maintenance and file separation.</blockquote><p>I’d love to know how other Meteor users structure their files: feel free to share it in the comment section.</p><blockquote>This article is part of the publication <a href="https://medium.com/unexpected-token">Unexpected Token</a> powered by <a href="http://efounders.co/">eFounders</a> — startup studio. All eFounders’ startups are built by extraordinary CTOs. If you feel like it could be you, <a href="http://efounders.co/cto">apply here</a>.</blockquote><blockquote><strong><em>Did you like it? Hit “Recommend” and subscribe to our collection!</em></strong></blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ef7f34373ed" width="1" height="1" alt=""><hr><p><a href="https://medium.com/unexpected-token/how-to-organize-your-files-on-your-meteor-projects-ef7f34373ed">How to organize your files on your Meteor projects</a> was originally published in <a href="https://medium.com/unexpected-token">Unexpected Token</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The art of the startup pivot from a founder-CTO point of view]]></title>
            <link>https://medium.com/unexpected-token/the-art-of-the-startup-pivot-from-a-founder-cto-point-of-view-b8747f80b5be?source=rss----2d2624499d2---4</link>
            <guid isPermaLink="false">https://medium.com/p/b8747f80b5be</guid>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[tech]]></category>
            <category><![CDATA[efounders]]></category>
            <dc:creator><![CDATA[Yann Lechelle]]></dc:creator>
            <pubDate>Thu, 30 Apr 2015 13:15:07 GMT</pubDate>
            <atom:updated>2015-10-07T11:02:11.421Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/749/1*tn9y9-41LK4mO0hmg4NRfw.png" /></figure><h4>A risk management perspective</h4><blockquote>Yann Lechelle (<a href="https://www.linkedin.com/in/ylechelle">LinkedIn</a>, <a href="http://twitter.com/ylechelle">Twitter</a>) is a Paris-based entrepreneur with a number of pivots under his belt. He was founder and CEO at Etheryl (acquired by private investors), co-founder at <a href="http://kickyourapp.com">KickYourApp.com</a> (acquired by Change), co-founder and COO/CTO at <a href="http://appsfire.com">Appsfire.com</a> (acquired by MNG), co-founder at <a href="http://sonetin.com">Sonetin.com</a> and currently COO at <a href="http://snips.ai">Snips.ai</a> using AI to make technology disappear. Yann occasionally invests in and advises other startups, on pivots among other things!</blockquote><h2>~</h2><p><strong><em>TL;DR</em></strong><em>: this post discusses the generic notion of a startup pivot. </em><strong><em>Technically minded readers might prefer to focus on the product &amp; tech sections, or anything else in bold.</em></strong></p><p>Pivots are a fact of life in the startup world. Yet, very few founders, especially first-time founders, will provision for it. The founder mindset is typically focused on a single go-to-market strategy. The investors are sold on the potential based on that initial strategy, signing off a budget calibrated accordingly. Everyone sings the same tune until the shareholders realize, hopefully before it’s too late, that the strategy is going nowhere, and that a radical change is required. This scenario occurs more often than not, <a href="http://www.quora.com/What-percentage-of-startups-pivot-their-business-model">over 65% of the time according to Fred Wilson</a>.</p><p>While this iterative process appears natural, and with the benefit of hindsight, accepted and even praised as part of the startup folklore, it remains a traumatic event from the inside, and possibly a direct cause for failure. Reversely, if done right, a pivot is almost inevitably cause for success.</p><p>Structurally, there can only be a handful of pivots within the lifetime of a company. Repeat entrepreneurs may have experienced it multiple times and therefore developed their art of the pivot… hence becoming pivot artists, a trait that VCs should consider as key risk management expertise! Here are a few awesome pivot artists:</p><ul><li>Multi-pivot repeat entrepreneur Stewart Butterfield: from video game to <em>Flickr</em> and from video game to <em>Slack; </em>product &amp; vision pivot.</li><li>One-time-pivot entrepreneur extraordinaire Mark Zuckerberg: from <em>Hot or Not</em> to <em>The Facebook; </em>product pivot, vision developed in hindsight?</li><li>Multi-pivot co-founders Jean-Baptiste Rudelle, Romain Niccolini and Franck Le Ouay: <em>CRITEO</em> and its 3 pivots to become a (too rare) French Unicorn.</li></ul><p>Let’s go back to our humble startups and itemize some of the issues that may arise during a pivot (with first hand examples):</p><ul><li>A sudden shift in business model affects the former revenue stream and structure, therefore affecting the operating budget;</li></ul><blockquote>For example, killing a revenue generating B2C product will certainly reduce the top line and increase the monthly burn. The lifeline suddenly becomes shorter.</blockquote><ul><li><strong>The team that had grown according to the needs of the previous product suddenly needs to be recast to the new configuration, leading to casting and head-count mismatch;</strong></li></ul><blockquote>For example, a team that had built an architecture around complex and intertwined relational databases with a balanced mix of read/writes suddenly needs to reconfigure for a product that needs massive reads (100x) optimised for low latency with a noSQL-based and map-reduced architecture. Different skills, different architecture, new learning curve.</blockquote><ul><li><strong>Parts of the older product needs to be transitioned, phased out, or worse maintained to some degree;</strong></li></ul><blockquote>For example, when the pivot requires to move from B2C to B2B, when do you pull the plug on the B2C product? Does it affect your revenue? It is probably a good idea to give reasonable notice to those users who have embraced your initial product; it is essential that those very users are onboard with the pivot and keep them as potential ambassadors of your brand equity. Who on the team can help maintain the legacy solution? for how long? should they instead focus on the new product?</blockquote><ul><li><strong>A new product needs to be developed, hopefully by leveraging existing infrastructure, skills, and capital, all of which are now more constrained;</strong></li></ul><blockquote>For example, shifting the model from B2C to B2B may involve refactoring a single platform into a SaaS offering… resulting in multiple instances of the same product. Other examples may involve refactoring some of the code and accelerate the design of a brand new product, for example by going up or down the value chain), while at the same time keeping the same clients or partners to speed up the go-to-market this second time around.</blockquote><ul><li>Worse of all, the time and energy considerations are now more constrained than ever: this is possibly the most difficult aspect to manage.</li></ul><blockquote>Here the founders need to lead by example, be on the ground and with the team at the same time; in a way, back to square one.</blockquote><p>As you can see, <strong>most of the above issues are product related</strong>, and yet fundamentally anchored in the HR ability to turn things around. Indeed, entrepreneurs thrive on constraints, and a pivot may in fact correspond to “a second wind”.</p><h3>How does one prepare for a pivot, or rather, how does one create the proper conditions to pivot properly?</h3><p>Let’s break it down around three main pillars: <strong>product &amp; tech</strong>, HR, and capital.</p><h4><strong>Product &amp; Tech Challenge</strong></h4><p>The product initially defined by the founders typically emanates from a global vision. In some cases, founders will start with the product and later realize, on their own or with external help, that there is a greater vision. Either way, the team must strive to work towards the greater vision, and consider that the product itself is just a means for achieving a greater goal. This serves two distinct purposes: pitch investors at a higher level of ambition (helps with the valuation), but <strong>most importantly, helps the product and engineering team build a category of assets that will be reusable when pivoting the product within the general framework of their vision.</strong></p><blockquote><strong>For example, building an architecture that isolates fundamental blocks of logic and imposes inter-process communication by way of a proper API supporting OAuth 2.0 may help migrate from a B2C product to a B2B offering that exposes those APIs to external entities. Building a B2C product that way may require a little more time and effort, but is in fact the correct way. Shortcuts or sloppy execution can easily turn into technical debt which is extremely penalizing in case of a pivot.</strong></blockquote><p><strong>While the pivot is a general management directive, the CTO is a key decision maker in this process. Indeed, only the CTO has a global view on the existing architecture and the individual skills that the technical team possesses. Reversely, smaller technical teams may be better at instigating what the new product could be. Either way, at the board level, the CTO can steer the ship smoothly towards a new product that leverages the current skillset and architecture, or else agree to ignore those assets and embark on a radically new creation (at a cost).</strong></p><p>It helps if the vision is both ambitious and not dependent on exogenous platforms like Facebook, Twitter, Apple or Google. With Appsfire, a company that I co-founded in 2010, our vision and mission was to solve “app discovery”. Unfortunately, that vision had very strong dependencies with the App Stores. Towards the end of 2013, changes within the App Store guidelines made our model unsustainable… forcing us to pivot both at the vision and product levels; a much harder feat.</p><p>Reshuffling the business model, or reshuffling a number of technical assets to re-define the product is much easier than having to start from scratch, in addition to helping keep the momentum and timing to achieve the holy grail: the product-market fit.</p><h4><strong>HR</strong></h4><p><em>It’s the people, stupid!</em> It always boils down to the people doesn’t it? Indeed, a startup isn’t a financial play on its own. It may be at the VC portfolio level, but at the micro level, within the startup itself, it’s all about energy and productivity, about beating the odds and overachieving, it’s about the core vision and the ability for the founders and the rest of the team to bind to it.</p><p>To that effect, to ensure that the team is effectively able to pivot, it should be composed of two key groups:</p><ul><li>the hard core team: founders and first employees. They must demonstrate charisma and the stamina to go the extra mile, especially during hard times and periods of doubt. They will lead by example and explain why the pivot is necessary, in full transparency.</li><li><strong>a larger group made of polyvalent engineers (also known as <em>the talent</em>): full stack, avid learners, passionate bunch, agile minds, sprinters (and not just in the agile sense), team players… typically people who are not too affected when their project suddenly shifts gears and they have to step outside of their comfort zone or preferred coding language or IDE</strong>.</li></ul><p>A third group inevitably exists and is made of people who are either back-office (accounting, finance), sales and business development agents, or technical specialists. During a pivot, some of these people will see their workload dwindle rapidly: if the business model changes, there is perhaps suddenly no more invoices to produce, nothing to sell for a while, or at the technical no need for a specific expertise that made sense pre-pivot. In the US, it’s quite easy to thank people and let them go — a harsh reality and necessity. In France, the labor framework does not make it easy even though, contrary to popular belief, it is definitely possible and reasonable if done right. I would argue that if the reason is communicated properly, employees will understand that the pivot creates a “casting mismatch” and that they are often better off by leaving the company. Working with them on their transition to a new job, or mutually agreeing on a smooth “exit” will give them ample time to rebound at a reasonable cost to the startup (the rest will be covered by the government’s unemployment subsidies).</p><h4><strong>Capital</strong></h4><p>At the capitalistic level, the pivot brings an interesting paradoxical twist. While the team and founders may have found a way to better address the market, they will almost inevitably do so from the existing cap table, and without fresh capital. Pivoting means the board acknowledges a local failure, and yet, the action of pivoting, in fact allows a swift and more educated go-to-market approach, bearing less risk, and therefore value creating.</p><p>It could be argued that if the pivot is radical enough, then the team and founders should probably start from a clean slate: new company, fresh cap table, and funds dedicated to the new product. Call it emotional attachment, loyalty or ignoring the notion of sunk cost, founders will often honor continuity and momentum even if it means less than ideal capitalistic terms. VCs should probably acknowledge that and recognize that a pivot done right deserves a little readjustment or nudge towards the effort. Reversely, when comes the time to pivot, founders should perhaps approach their investors in earnest and plead towards a new set of terms and incentive: relution against cash if pivot succeeds, dilution otherwise.</p><p>In reality, entrepreneurs keep at it and pivot within the capitalistic framework inherited from the pre-pivot period. To that effect, I only have one piece of advice: raise more funds if you can by adding some padding to your budget. In short, within your fundraising round, provision for a pivot by allocating an extra 50% of your initial budget. Early stage investors (seed or series A) will be more interested to discuss this notion of padding for a potential pivot rather than discuss unrealistic 3 year projections.</p><h4><strong>To conclude…</strong></h4><p>Pivoting is in fact a corollary to the <em>fail fast</em> doctrine. Execution and focus are key ingredients to a successful path until you reach that dead end. Yet, nothing prevents startup founders to think in broader terms, provision for the (almost) inevitable pivot by creating financial padding, <strong>recruit polyvalent talent, and finally productize around the vision rather than digging a grave around a mono-product approach</strong>.</p><blockquote>This article is part of the publication <a href="https://medium.com/unexpected-token">Unexpected Token</a> powered by <a href="http://efounders.co/">eFounders</a> — startup studio. All eFounders’ startups are built by extraordinary CTOs. If you feel like it could be you, <a href="http://efounders.co/cto">apply here</a>.</blockquote><blockquote><em>You like? Hit “Recommend” and subscribe to our collection!</em></blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b8747f80b5be" width="1" height="1" alt=""><hr><p><a href="https://medium.com/unexpected-token/the-art-of-the-startup-pivot-from-a-founder-cto-point-of-view-b8747f80b5be">The art of the startup pivot from a founder-CTO point of view</a> was originally published in <a href="https://medium.com/unexpected-token">Unexpected Token</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How your API could benefit from Hypermedia]]></title>
            <link>https://medium.com/unexpected-token/how-your-api-could-benefit-from-hypermedia-b62780771ccb?source=rss----2d2624499d2---4</link>
            <guid isPermaLink="false">https://medium.com/p/b62780771ccb</guid>
            <category><![CDATA[tech]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[computer-science]]></category>
            <dc:creator><![CDATA[Olivier Hervieu]]></dc:creator>
            <pubDate>Thu, 23 Apr 2015 13:15:46 GMT</pubDate>
            <atom:updated>2015-04-23T13:15:46.839Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/750/1*NwZ9HrCk6OCSt2Al-X1Tlg.png" /><figcaption>illustration by adrien griveau</figcaption></figure><p><a href="https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm">Roy Fielding’s dissertation thesis</a> on “Architectural Styles and the Design of Network-based Software Architectures” albeit published in 2000, is still a goldmine in 2015. For those who are not familiar with Fielding’s work, he is one of the authors of the Apache web server, he has worked on the first specification of HTTP, and he is the father of the REST acronym.</p><p>A REST architecture is an architecture that MUST (as in <a href="https://www.ietf.org/rfc/rfc2119.txt">RFC 2119</a>) respect the following architectural constraints:</p><ul><li>client-server</li><li>stateless</li><li>cacheable</li><li>layered-system</li><li>uniform interface</li><li>code-on-demand (optionally)</li></ul><p>HTTP and the 2000’s World Wide Web, fit perfectly in this description of a REST architecture (in fact, REST constraints seem to be chosen so that systems that would respect these constraints will look like the web ☺)</p><p>15 years later, everybody builds RESTful APIs. These APIs take full benefit from HTTP (and thus, from its REST-base architecture) but most APIs do not fully respect the “uniform interface” constraint.</p><p>In the Fielding sense, an API is really RESTful if it respects the uniform interface constraints:</p><ul><li>resources are unambiguously requested via URIs,</li><li>representations of resources are manipulated (you’re always playing with a “view” of a resource, not the resource itself),</li><li>messages are self-descriptive and self-contained,</li><li>transitions and actions should be clearly exposed to the client by the server, via hyperlinks and hypertext. This point is often referred as <a href="http://en.wikipedia.org/wiki/HATEOAS">HATEOS</a>: Hypermedia as the engine of application state.</li></ul><p>A classical website, like the one from which you’re reading this article, uses hypermedia as the engine of application state. You’re viewing representations of resources and, on each of them, a set of actions (going back to home, viewing a related article) is actionable via hypertext links. Clicking on one of these links will (hopefully) give you another view of another resource, modifying the application state.</p><p>Those links are materialized and explained by meaningful text and iconography to help you do what you want to achieve. The web everybody knows is fully compliant with the HATEOS constraint.</p><h3>HATEOS constraints applied to APIs</h3><p>Fine, but what’s the point with APIs? Let’s take an example with a widely-used API; the Twitter one. Twitter API exposes a way to retrieve your friends by doing the following call over HTTP</p><pre>GET <a href="https://api.twitter.com/1.1/friends/ids.json?cursor=-1&amp;screen_name=twitterapi&amp;count=5000">https://api.twitter.com/1.1/friends/ids.json?cursor=-1&amp;screen_name=twitterapi&amp;count=5000</a></pre><p>Then, the reply (as documented <a href="https://dev.twitter.com/rest/reference/get/friends/ids">here</a>) will be something like:</p><pre>{<br>  &quot;previous_cursor&quot;: 0,<br>  &quot;ids&quot;: [<br>    657693,<br>    ...,<br>    783214<br>  ],<br>  &quot;previous_cursor_str&quot;: &quot;0&quot;,<br>  &quot;next_cursor&quot;: 0,<br>  &quot;next_cursor_str&quot;: &quot;0&quot;<br>}</pre><p>Without any knowledge of the twitter API structure, what actions are easily actionable from this response? NONE.</p><blockquote>Server developers are responsible for providing the next actions a client can take from each point in the application.</blockquote><p>This is exactly where HATEOAS comes into play.</p><p>By being non-HATEOS compliant, most APIs, including “big” ones, do not respect the uniform interface constraint as defined by Fielding. Does it means that the web (well, APIs) is broken? NO ☺</p><p>Now, two hard questions arise:</p><ul><li>“As a client developer, is it really possible to create an API client smart enough to use hypermedia relations to perform actions on websites without any knowledge of the website structure?”</li><li>“As a server developer, can I describe my application logic via links and relations that would be self-comprehensive by any hypermedia client?”</li></ul><p>For instance, if every social network would expose Hypermedia APIs, fetching my friends on each of the network would be as easy as:</p><pre>client(any_website).auth(login, password).get_friends()</pre><p>(here: our client would request the “/” of the social network api, get the Content-Type to parse the response, look at any available link relation to authenticate, and then look at any available link relation to retrieve friends.)</p><p>The (optimistic) answer for these two questions is YES. Hypermedia advocates put a lot of energy in standardizing the web to allow the emergence of Hypermedia APIs:</p><ul><li>by creating formats for our APIs: Atom+Pub, Collections+JSON, Siren, HAL, …</li><li>by creating repositories of link relations (see <a href="http://schema.org/">schema.org</a>)</li></ul><blockquote>To approach hypermedia APIs, it is important to understand that every media type (or Content-Type) should define a processing model.</blockquote><p>Said otherwise, keep in mind this question: “<em>What would a browser do with my response?</em>”.</p><h3>Hypermedia APIs remain not massively used</h3><p>Sadly, there are a few limitations that could explain why Hypermedia APIs are not widespread:</p><ul><li>writing an exhaustive list of link relations seems unrealistic: even if efforts are made to simplify the description of new link relations (JSON-LD is a good example)</li><li>APIs are not (quite) the web, they are designed to interconnect services and feed end-user applications. Using hyperlinks and describing link relations yield bigger (in size) replies and slightly more requests in a world when connectivity is still an issue in many cases (notably in mobility: smartphones, etc..)</li></ul><p>Another reason for the rarity of such APIs might be the lack of commitment from WEB giants. Google might be the only one (as far as I know) to provide a Hypermedia API (their XML responses respect the AtomPUB format).</p><p>But there are a lot of things to learn and some benefits to take from Hypermedia-based APIs:</p><ul><li>definition of a processing model according to a Content-Type (or simpler: formatting of replies),</li><li>comprehensive description of your API via links and their associated descriptors (especially standard ones as defined by the IANA).</li></ul><h3>Hypermedia API case in point</h3><p>Let’s now go back to our previous example. As already described,</p><pre>GET <a href="https://api.twitter.com/1.1/friends/ids.json?cursor=-1&amp;screen_name=twitterapi&amp;count=5000">https://api.twitter.com/1.1/friends/ids.json?cursor=-1&amp;screen_name=twitterapi&amp;count=5000</a></pre><p>would return the following response:</p><pre>{<br>  &quot;previous_cursor&quot;: 0,<br>  &quot;ids&quot;: [<br>    657693,<br>    ...,<br>    783214<br>  ],<br>  &quot;previous_cursor_str&quot;: &quot;0&quot;,<br>  &quot;next_cursor&quot;: 0,<br>  &quot;next_cursor_str&quot;: &quot;0&quot;<br>}</pre><p>Under a “hypermedia” light, this response has several limitations:</p><ul><li>I have a list of id, which are, as we can guess, our friends’ ids, but what can I do with these? How can I fetch their user information?</li><li>As a human, I guess that next_cursor is something to fetch the next page of ids, but what is the associated URL? And is there something more generic to say that something can be used to fetch the previous and next page of results?</li></ul><p>In fact this answer is full of conventions. These conventions are documented in a human-readable format and accessible via twitter’s developer website.</p><p>Hence these conventions should be coded by a human within a library, leading to a strong coupling between client and servers.</p><p>The lack of URL usage in answers leads to a high number of links hardcoded in client APIs.</p><p>As an example, here is the output of a search for “url” in a python twitter api client.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*qdAOogeykrfl40hc." /></figure><p>Let’s try to make this answer a bit more « Hypermedia ».</p><p>IANA standard relations type (<a href="http://www.iana.org/assignments/link-relations/link-relations.xhtml">http://www.iana.org/assignments/link-relations/link-relations.xhtml</a>) defines « prev » (or « previous ») and « next » relations as:</p><ul><li>« prev »: indicates that the link’s context is a part of a series, and that the previous in the series is the link target.</li><li>« next »: indicates that the link’s context is a part of a series, and that the next in the series is the link target.</li></ul><p>Our previous answer could be rewritten as:</p><pre>{<br>  &quot;prev&quot;: &quot;<a href="https://api.twitter.com/1.1/friends/ids.json?cursor=-1&amp;screen_name=twitterapi&amp;count=5000">https://api.twitter.com/1.1/friends/ids.json?cursor=-1&amp;screen_name=twitterapi&amp;count=5000</a>&quot;,<br>  &quot;ids&quot;: [<br>    657693,<br>    ...,<br>    783214,<br>  ],<br>  &quot;next&quot;: &quot;<a href="https://api.twitter.com/1.1/friends/ids.json?screen_name=twitterapi&amp;count=10&amp;cursor=0">https://api.twitter.com/1.1/friends/ids.json?screen_name=twitterapi&amp;count=10&amp;cursor=0</a>&quot;,<br>}</pre><p>Then for each id, you could decide to return a data structure that could give you useful information about the user: lookup (as described in twitter api), friends, timeline, etc… It could give the following rewrite of your answer:</p><pre>{<br>  &quot;prev&quot;: &quot;<a href="https://api.twitter.com/1.1/friends/ids.json?cursor=-1&amp;screen_name=twitterapi&amp;count=5000">https://api.twitter.com/1.1/friends/ids.json?cursor=-1&amp;screen_name=twitterapi&amp;count=5000</a>&quot;,<br>  &quot;ids&quot;: [<br>    {<br>      &quot;657693&quot;: {<br>        &quot;user_lookup&quot;: &quot;<a href="https://api.twitter.com/1.1/users/lookup.json?user_id=657693">https://api.twitter.com/1.1/users/lookup.json?user_id=657693</a>&quot;,<br>        &quot;friends&quot;: &quot;<a href="https://api.twitter.com/1.1/friends/ids.json?user_id=657693">https://api.twitter.com/1.1/friends/ids.json?user_id=657693</a>&quot;<br>      },<br>      ...,<br>      &quot;783214&quot;: {<br>        &quot;user_lookup&quot;: &quot;<a href="https://api.twitter.com/1.1/users/lookup.json?user_id=783214">https://api.twitter.com/1.1/users/lookup.json?user_id=783214</a>&quot;,<br>        &quot;friends&quot;: &quot;<a href="https://api.twitter.com/1.1/friends/ids.json?user_id=783214">https://api.twitter.com/1.1/friends/ids.json?user_id=783214</a>&quot;<br>       }<br>    }<br>  ],<br>  &quot;next&quot;: &quot;<a href="https://api.twitter.com/1.1/friends/ids.json?cursor=-1&amp;screen_name=twitterapi&amp;count=10&amp;cursor=0">https://api.twitter.com/1.1/friends/ids.json?cursor=-1&amp;screen_name=twitterapi&amp;count=10&amp;cursor=0</a>&quot;,<br>}</pre><p>But wait! Here “user_lookup” and “friends” are not described as standard relations links in the previous IANA link relation lists. That is true, and it is, as described earlier, one of the fallacies of hypermedia. Here, the fun fact is that even the Person « type » described by <a href="http://schema.org/">schema.org</a> does not expose a « friends » link relation.</p><p>Finally, this response does not fit any existing format. With collection+JSON, the previous response might be:</p><pre>{<br>  &quot;collection&quot;: {<br>    &quot;version&quot;: &quot;1.0&quot;,<br>    &quot;href&quot;: &quot;<a href="https://api.twitter.com/1.1/friends/ids.json?cursor=-1&amp;screen_name=twitterapi&amp;count=5000">https://api.twitter.com/1.1/friends/ids.json?cursor=-1&amp;screen_name=twitterapi&amp;count=5000</a>&quot;,<br>    &quot;links&quot;: [<br>      {<br>        &quot;rel&quot;: &quot;prev&quot;,<br>        &quot;href&quot;: &quot;<a href="https://api.twitter.com/1.1/friends/ids.json?cursor=-1&amp;screen_name=twitterapi&amp;count=5000">https://api.twitter.com/1.1/friends/ids.json?cursor=-1&amp;screen_name=twitterapi&amp;count=5000</a>&quot;<br>      },<br>      {<br>        &quot;rel&quot;: &quot;next&quot;,<br>        &quot;href&quot;: &quot;<a href="https://api.twitter.com/1.1/friends/ids.json?cursor=-1&amp;screen_name=twitterapi&amp;count=10&amp;cursor=0">https://api.twitter.com/1.1/friends/ids.json?cursor=-1&amp;screen_name=twitterapi&amp;count=10&amp;cursor=0</a>&quot;<br>      }<br>    ],<br>    &quot;items&quot;: [<br>      {<br>        &quot;href&quot;: &quot;<a href="https://api.twitter.com/1.1/users/lookup.json?user_id=657693">https://api.twitter.com/1.1/users/lookup.json?user_id=657693</a>&quot;,<br>        &quot;data&quot;: [<br>          {<br>            &quot;name&quot;: &quot;user_id&quot;,<br>            &quot;value&quot;: &quot;657693&quot;<br>          }<br>        ],<br>        &quot;links&quot;: [<br>          {<br>            &quot;rel&quot;: &quot;user_lookup&quot;,<br>            &quot;href&quot;: &quot;<a href="https://api.twitter.com/1.1/users/lookup.json?user_id=657693">https://api.twitter.com/1.1/users/lookup.json?user_id=657693</a>&quot;,<br>            &quot;prompt&quot;: &quot;User Info&quot;<br>          },<br>          {<br>            &quot;rel&quot;: &quot;friends&quot;,<br>            &quot;href&quot;: &quot;<a href="https://api.twitter.com/1.1/friends/ids.json?user_id=657693">https://api.twitter.com/1.1/friends/ids.json?user_id=657693</a>&quot;,<br>            &quot;prompt&quot;: &quot;Friends&quot;,<br>            &quot;render&quot;: &quot;collection&quot;<br>          }<br>        ]<br>      },<br>      {<br>        &quot;href&quot;: &quot;<a href="https://api.twitter.com/1.1/users/lookup.json?user_id=783214">https://api.twitter.com/1.1/users/lookup.json?user_id=783214</a>&quot;,<br>        &quot;data&quot;: [<br>          {<br>            &quot;name&quot;: &quot;user_id&quot;,<br>            &quot;value&quot;: &quot;783214&quot;<br>          }<br>        ],<br>        &quot;links&quot;: [<br>          {<br>            &quot;rel&quot;: &quot;user_lookup&quot;,<br>            &quot;href&quot;: &quot;<a href="https://api.twitter.com/1.1/users/lookup.json?user_id=783214">https://api.twitter.com/1.1/users/lookup.json?user_id=783214</a>&quot;,<br>            &quot;prompt&quot;: &quot;User Info&quot;<br>          },<br>          {<br>            &quot;rel&quot;: &quot;friends&quot;,<br>            &quot;href&quot;: &quot;<a href="https://api.twitter.com/1.1/friends/ids.json?user_id=783214">https://api.twitter.com/1.1/friends/ids.json?user_id=783214</a>&quot;,<br>            &quot;prompt&quot;: &quot;Friends&quot;,<br>          }<br>        ]<br>      }<br>    ]<br>  }<br>}</pre><p>(note: As mentioned earlier, this response is far bigger compared to the original one, this is a huge limitation of hypermedia responses)</p><p>To conclude, why would we consider this rewrite of a Twitter response as better?</p><p>I think that every API should have the following qualities:</p><ul><li>stable</li><li>comprehensive</li><li>adaptable</li></ul><p>Providing links in your replies will let you change the link destination of a resource, making your API adaptable, and somehow stable (if client developers do not make any assumptions about your URLs)</p><p>Providing relations will make your links comprehensive and will make your responses self-descriptive.</p><p>Using a stable format will make the format of your replies predictable and, as a server developer, will give you a guide to forge responses.</p><p>Following this advice might let you build APIs that would be more adaptable and their clients might be more resilient to changes.</p><h3>Useful Resources</h3><p>If all of this makes sense to you, I truly recommend you read <a href="http://shop.oreilly.com/product/0636920028468.do">this book</a>. Mike Amundsen is one of the best advocates of Hypermedia APIs and this book goes deep into standards description.</p><p>I should mention too <a href="https://github.com/basti1302/traverson">traverson</a> which is the coolest attempt to build a functional hypermedia client and HAL browser which is a project where you can play with <a href="http://haltalk.herokuapp.com/explorer/browser.html#/">HAL</a>. By the way, you will find a short API client for HAL browser in one of my slide deck <a href="https://speakerdeck.com/ohe/apis-hypermedia?slide=41">here</a>.</p><blockquote><em>This article is part of the publication </em><a href="https://medium.com/unexpected-token"><em>Unexpected Token</em></a><em> powered by </em><a href="http://efounders.co/"><em>eFounders</em></a><em> — startup studio. All eFounders’ startups are built by extraordinary CTOs. If you feel like it could be you, </em><a href="http://efounders.co/cto"><em>apply here</em></a><em>.</em></blockquote><blockquote>You like? Hit “Recommend” and subscribe to our collection!</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b62780771ccb" width="1" height="1" alt=""><hr><p><a href="https://medium.com/unexpected-token/how-your-api-could-benefit-from-hypermedia-b62780771ccb">How your API could benefit from Hypermedia</a> was originally published in <a href="https://medium.com/unexpected-token">Unexpected Token</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Making your website multi-regional using top-level domains]]></title>
            <link>https://medium.com/unexpected-token/making-your-website-multi-regional-using-top-level-domains-cdbbdb951b65?source=rss----2d2624499d2---4</link>
            <guid isPermaLink="false">https://medium.com/p/cdbbdb951b65</guid>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[tech]]></category>
            <category><![CDATA[development]]></category>
            <dc:creator><![CDATA[Nicolas Mondollot]]></dc:creator>
            <pubDate>Wed, 15 Apr 2015 12:19:08 GMT</pubDate>
            <atom:updated>2016-04-21T10:59:02.227Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/749/1*KU5KOnT7RcuIKoLGGsCYgQ.png" /><figcaption>illustration: Adrien Griveau</figcaption></figure><p><em>Hi there. My name is Nicolas Mondollot, I am the CTO of </em><a href="https://www.drivy.com"><em>Drivy</em></a><em> — an </em><a href="http://techcrunch.com/2014/05/05/drivy-raises-8-3-million-for-its-community-based-car-rental-service/"><em>awesome</em></a><em> peer-to-peer car rental service. We launched our </em><a href="https://www.drivy.de"><em>german website</em></a><em> in early 2015. Here are some things we learned along the way.</em></p><p>When you start a website you usually start small: one website, hosted on one domain, targeting one country and one language. Simple, right?</p><p>Then, one day you decide to go international (exciting!). One problem, though: people don’t all speak/read the same language everywhere. You <em>must</em> localize you content in multiple languages.</p><p>The standardized way to do so is to use a <a href="http://en.wikipedia.org/wiki/Locale">locale</a> for each language and geographical region you are targeting. For instance if you want to make your website available in the US, France and Canada you’ll need 4 locales:</p><ul><li><em>en</em> : English (US)</li><li><em>fr</em> : French (France)</li><li><em>fr-CA</em> : French (Canada)</li><li><em>en-CA</em> : English (Canada)</li></ul><p><em>side note: this is a ‘pragmatic’ approach to locale naming, where we drop the regional part when it is not needed (more information </em><a href="http://guides.rubyonrails.org/i18n.html#configure-the-i18n-module"><em>here</em></a><em>).</em></p><p>Great. Now, how do you make your website available in all these locales?</p><h4>Locales and URLs</h4><p>The first rule of <a href="http://en.wikipedia.org/wiki/Search_engine_optimization">Search Engine Optimization</a> when you go international is: the locale must appear in the URL. Google suggests choosing among <a href="https://support.google.com/webmasters/answer/182192?hl=en">several options</a>:</p><ul><li>URL parameters: <strong>example.com?locale=fr</strong></li><li>Subdirectories with a generic top-level domain (gTLD): <strong>example.com/fr/</strong></li><li>Subdomains with a generic top-level domain (gTLD): <strong>fr.example.com</strong></li><li>Country-specific top-level domains (ccTLD): <strong>example.fr</strong></li></ul><p>There is no one-size-fits-all approach. The best solution really depends on your specific requirements (<a href="http://moz.com/blog/the-international-seo-checklist">this article</a> from Moz may give you some pointers). At Drivy we decided to use ccTLDs because it was the best solution SEO-wise to target different countries. Plus it’s prettier.</p><h3>First implementation</h3><p>In Rails this is pretty straightforward. You just need to point your new domain DNS to your application server and drop this code in your <em>ApplicationController</em> (inspired by the <a href="http://guides.rubyonrails.org/i18n.html#setting-the-locale-from-the-domain-name">official Rails guide</a>):</p><pre>class ApplicationController &lt; ActionController::Base<br>  before_action :set_locale<br> <br>  def set_locale<br>    I18n.locale = request.host.split(&#39;.&#39;).last || :en<br>  end<br>end</pre><p>We basically take the last part of the URL domain (<em>fr</em> in the case of <em>example.fr</em>) and we set the locale to this value. Simple.</p><p>It works, but it has major drawbacks:</p><ul><li>it doesn’t work for ccTLDs that don’t correspond to a valid locale (e.g. example.ca)</li><li>it doesn’t work with second-level domains (e.g. example.co.uk)</li><li>it doesn’t work in dev environment (where you usually use http://localhost:3000)</li></ul><p>One other thing that may cause trouble down the road: what if you can’t map a ccTLD to a given locale? This can happen in several scenarios:</p><ul><li>the ccTLD is already taken by somebody else — in which case the next best solution is to use a subdomain</li><li>you want to offer several locales for a given ccTLD (e.g. French and English for Canada)</li></ul><p>And this gets even more complex as you add different environments (production, staging, dev) and more subdomains.</p><p>There must be a more robust way.</p><h3>Second implementation</h3><p>Let’s be more explicit and define a clear one-to-one mapping between the locale and the host:</p><pre>HOSTS_MAPPING = {<br>  &#39;en&#39;    =&gt; &#39;example.com&#39;,<br>  &#39;fr&#39;    =&gt; &#39;example.fr&#39;,<br>  &#39;fr-CA&#39; =&gt; &#39;fr.example.ca&#39;,<br>  &#39;en-CA&#39; =&gt; &#39;en.example.ca&#39;<br>}</pre><p>Now let’s use this new mapping in our <em>ApplicationController</em>:</p><pre>class ApplicationController &lt; ActionController::Base<br>  before_action :set_locale</pre><pre>  def set_locale<br>    I18n.locale = HOSTS_MAPPING.invert[request.host] || I18n.default_locale<br>  end<br>end</pre><p>We can now easily make this work in our staging environment by using a different hash:</p><pre>HOSTS_MAPPING_STAGING = {<br>  &#39;en&#39;    =&gt; &#39;staging.example.com&#39;,<br>  &#39;fr&#39;    =&gt; &#39;staging.example.fr&#39;,<br>  &#39;fr-CA&#39; =&gt; &#39;fr.staging.example.ca&#39;,<br>  &#39;en-CA&#39; =&gt; &#39;en.staging.example.ca&#39;<br>}</pre><p><em>side note: this breaks </em><a href="http://12factor.net/dev-prod-parity"><em>dev/prod parity</em></a><em>, so you should probably avoid this and instead buy a dedicated domain for your staging environment</em></p><p>Same thing for our dev environment:</p><pre>HOSTS_MAPPING_DEV = {<br>  &#39;en&#39;    =&gt; &#39;dev-example.com&#39;,<br>  &#39;fr&#39;    =&gt; &#39;dev-example.fr&#39;,<br>  &#39;fr-CA&#39; =&gt; &#39;fr.dev-example.ca&#39;,<br>  &#39;en-CA&#39; =&gt; &#39;en.dev-example.ca&#39;<br>}</pre><p><em>side note: this means every member of your dev team must setup his </em><a href="https://www.weg.ucar.edu/documentation/hostfile-unix.html"><em>etc/hosts</em></a><em> to make all the domains above point to his/her local machine</em></p><h3>One major gotcha: emails</h3><p>Our implementation works pretty well and is pretty flexible. But there is one big gotcha: <strong>what host do we use when we send emails to our users?</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*h-7cos9HX7GIh9V3Pusg7w.png" /></figure><p>The first solution that comes to mind is to use the default host and then redirect the user based on his latest locale:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eLI3b8c3DHJZLLOT3nOa6g.png" /></figure><p>One big problem: although it is easy to share cookies across subdomains, <a href="http://stackoverflow.com/questions/3342140/cross-domain-cookies">it’s impossible to share cookies across top-level domains</a>. And since server-side sessions are usually based on cookies this means <strong>you cannot have proper sessions across all your domains</strong> — unless you implement some kind of OAuth mechanism, which isn’t trivial.</p><p>If one our your users signs in on your French website (<em>example.fr</em>) he won’t be signed in on <em>example.com</em>, which means you won’t be able to retrieve his locale and you won’t be able to automatically redirect him to the correct domain. Bummer.</p><p>One solution is to use the correct domain in your emails. But since we are sending emails asynchronously we can’t rely on the <a href="http://guides.rubyonrails.org/action_controller_overview.html#the-request-and-response-objects">request object</a> like we did previously inside our <em>ApplicationController</em>.</p><p>We can work around this by hacking <a href="http://guides.rubyonrails.org/action_mailer_basics.html"><em>ActionMailer</em></a> a bit:</p><pre>class MyMailer &lt; ActionMailer::Base<br>  def welcome(user)<br>    @user = user<br>    mail(to: user.email)<br>  end</pre><pre>  def url_options<br>    super.merge({host: HOSTS_MAPPING[@user.locale]})<br>  end<br>end</pre><p>We retrieve the user’s locale (stored in our database) and we set the default host dynamically. All the links present in the email will use the correct host. It works!</p><h3>More gotchas?</h3><p>A few other gotchas to be aware of:</p><ul><li>You must set up multiple analytics accounts, one for each domain.</li><li>You must buy a multi-domain SSL certificate (unless you are ok with managing one certificate per domain). If you want to secure multiple domains AND multiple subdomains things can get very expensive very quickly. At Drivy we chose to use a <a href="https://www.geotrust.com/ssl/ssl-certificates/">GeoTrust True BusinessID</a> certificate because it is possible to add up to 25 domains or subdomains for a reasonable price: around €300 for a 5-domain pack, plus €20 per additional domain. This is still very expensive, but there aren’t a lot of alternatives apparently.</li><li>Your SEO juice will be split between your domains — there is no cumulative effect. If you open a new country you will start from zero SEO-wise. One way to mitigate this is to use <a href="https://support.google.com/webmasters/answer/189077?hl=en">alternate hreflang</a>.</li></ul><p>Despite all the efforts and all the gotchas I am pretty happy about the way it turned out for Drivy. Top-level domains really are a great strategy for the long term as it gives you clean URLs and a strong branding in each country.</p><p>If you are unsure about the strategy you want to adopt I really recommend reading <a href="http://moz.com/blog/the-international-seo-checklist">this article</a> from Moz as it will give you concrete pointers.</p><p>Happy internationalization!</p><blockquote>This article is part of the publication <a href="https://medium.com/unexpected-token">Unexpected Token</a> powered by <a href="http://efounders.co/">eFounders</a> — startup studio. All eFounders’ startups are built by extraordinary CTOs. If you feel like it could be you, <a href="http://efounders.co/cto">apply here</a>.</blockquote><blockquote><em>You like? Hit “Recommend” and subscribe to our collection!</em></blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cdbbdb951b65" width="1" height="1" alt=""><hr><p><a href="https://medium.com/unexpected-token/making-your-website-multi-regional-using-top-level-domains-cdbbdb951b65">Making your website multi-regional using top-level domains</a> was originally published in <a href="https://medium.com/unexpected-token">Unexpected Token</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>