[{"data":1,"prerenderedAt":12166},["ShallowReactive",2],{"blog-learning-from-failure":3,"all-blog-posts":151},{"id":4,"title":5,"author":6,"body":7,"date":138,"description":139,"extension":140,"headline":141,"icon":142,"icon_author":141,"icon_url":141,"layout":143,"location":141,"meta":144,"meta_description":141,"navigation":145,"path":146,"quote":141,"seo":147,"slug":142,"stem":148,"tags":149,"template":141,"__hash__":150},"blog/blog/en/2024-01-01-learning-from-failure.md","Learning from Failure: Lessons from the Challenger Disaster and Engineering Ethics","teleyinex",{"type":8,"value":9,"toc":129},"minimark",[10,14,19,22,25,28,33,44,52,55,58,61,64,67,70,73,76,80,83,86,89,92,95,98,101,104,107,111,114,117,120,123,126],[11,12,13],"p",{},"We all make mistakes. The only difference is how we deal with them; hiding them is always the worst solution. Let's check one of the most famous human failures that lead to the worst possible outcome: deaths.",[15,16,18],"h2",{"id":17},"the-challenger-disaster","The Challenger Disaster",[11,20,21],{},"The year was 1986. On the 28th of January, the Space Shuttle Challenger exploded after 73 seconds, killing all the crew.",[11,23,24],{},"But why it happened? What was the cause?",[11,26,27],{},"As with any disaster like this, the local authorities set up a committee to understand what happened so they could learn from the mistakes and avoid repeating the same errors again.",[29,30,32],"h3",{"id":31},"the-o-ring-problem","The O-ring problem",[11,34,35,36,43],{},"The Challenger used ",[37,38,42],"a",{"href":39,"rel":40},"https://en.wikipedia.org/wiki/Space_Shuttle_Solid_Rocket_Booster",[41],"nofollow","solid rocket boosters"," (SRBs). The SRBs were the first solid-propellant rockets used for primary propulsion on a vehicle for human spaceflight.",[11,45,46,51],{},[47,48],"img",{"alt":49,"src":50},"","/img/blog/learning-from-failure-1.jpg","Two solid rocket boosters perched on top from the Vehicle Assembly Building's",[11,53,54],{},"The SRBs had seven sections, six of which were joined in pairs. These created 4 resulting segments that were sealed with asbestos-silica insulation. Then, each joint was sealed with two rubber O-rings.",[11,56,57],{},"As with any engineering project, they had tests to ensure everything worked as expected. In 1977, they ran a test that showed that under pressurized water, the metal parts bent away from each other, opening a gap. This phenomenon, known as \"joint rotation\", caused a momentary drop in air pressure, which made it possible that combustion gasses could erode O-rings. If this were the case, then a flame path could be developed, causing the joint to burst, and if this happens, then the booster and the Shuttle.",[11,59,60],{},"With this knowledge, thanks to the experiments, the engineers wrote to the manager of the SRBs project, saying that the O-rings design was not acceptable for a flight. Now, guess what happened: the manager didn't share this information with the SRBs engineers, and the field joints were accepted for flight in 1980.",[11,62,63],{},"While this knowledge was based on tests, the first confirmed case was found on the second space shuttle mission, STS-2. You might be wondering, well, they reported it back so they could address the problem. Well, the reality is quite different: instead of following the regular rules to report it, the Marshall Center decided to not do it to senior management at NASA and share it directly with the contractor that built the boosters (Thiokol).",[11,65,66],{},"But how? They already knew 3 years before that this could be a problem, but they ignored it. Instead of briefing everyone, they wanted to keep it low and handle it with the contractor.",[11,68,69],{},"After all these reports, the O-rings were finally classified as \"Criticality 1\", which means that in the case of a failure, it could cause the destruction of the orbiter. Did they decide with this information to stop flights? No one at Marshall Center suggested grounding all the flights until they had a fix.",[11,71,72],{},"On the next flights, they got more evidence that O-rings were unsafe. The STS-41-D flight post-analysis found that O-rings suffered erosion, but the risk was low as they had two rings.",[11,74,75],{},"Flights continue to show more and more evidence that O-rings could cause the Shuttle explosion if they didn't find a solution. The STS-51-B flight showed for the very first time that O-rings were utterly eroded, removing the sealing and causing erosion on the second ring. At this point, it was clear from an engineering point of view that flights should be stopped at all costs. However, flights continued.",[29,77,79],{"id":78},"adding-cold-weather-to-the-mix","Adding cold weather to the mix",[11,81,82],{},"All the previous evidence was captured in \"good weather conditions\". None of the flights or tests were run under really low temperatures, so the O-rings were never certified to operate at low temps. The forecasts for the launch day predicted temperatures below -1 degrees Celsius, the minimum temperature permitted for launch.",[11,84,85],{},"The contractor engineers were worried that others would not share their concerns regarding the low-temperature effects on the boosters. Engineer Bob Ebeling, in October 1985, wrote a memo titled \"Help!\" You can imagine his desperation because his goal was that someone would read it and take action regarding flying about low temperatures.",[11,87,88],{},"After the weather forecast for the launch day, NASA contacted the contractor about this issue. A contractor manager asked Ebeling about the possibility of a launch at 18º F (-8º C). He answered: \"We're only qualified to 40º (4ºC) ... what business does anyone even have thinking about 18°, we're in no-man's land.'\" At this moment, the team agreed that a launch risked disaster, so they called NASA, recommending postponing the launch day until temperatures were within the approval ranges. NASA manager Jud Lovingood said they cannot recommend this without providing a safe temperature. The contractor organized a teleconference two hours later to justify the no-launch recommendation.",[11,90,91],{},"At the teleconference, several engineers reiterated their concerns about the effects of the low temperatures on the O-rings and insisted on postponing the launch. The conversation was centered on not having enough data to determine whether the O-rings would properly work under 54º F (12º C). This was important because, if you remember, SRB O-rings were designated as a \"Criticality 1\" component, meaning there is no backup if both rings fail. The failure could destroy the orbiter and kill its crew.",[11,93,94],{},"While NASA was against postponing the launch, the contractors tried to convince them. During the conference, NASA said things like: \"I am appalled by your recommendation.\" or \"My God, Thiokol, when do you want me to launch—next April?\"",[11,96,97],{},"NASA believed the first O-Ring could fail, but the second one would work. However, this was not tested at all, and in any case, this could not be argued because it was marked as a \"Criticality 1\" component. Astronaut Sally Ride stated before the Rogers Commission that it is forbidden to rely on a backup for a \"Criticality 1\" component.",[11,99,100],{},"With all this mess, the clock was running, and it looked like a second conference was scheduled with NASA and the contractor, but without the engineers. It is still being determined why the contractor's managers disregarded its engineer's warning and finally recommended launching as initially scheduled. Ebeling told his wife that night that Challenger would blow up.",[11,102,103],{},"The launch day arrived, and the temperatures were below freezing: 28º to 28.9º F (-2.2 to -1.7ºC). Due to all the ice covering the Shuttle that day, NASA postponed the launch by an hour so the Ice Team could perform another inspection. This last inspection showed that ice appeared to be melting, so Challenger got the green light for launch at 11:38 am EST.",[11,105,106],{},"At T+73.191 the mission control said: \"We have a report from the Flight Dynamics Officer that the vehicle has exploded. The flight director confirms that. We are looking at checking with the recovery forces to see what can be done at this point.\"",[15,108,110],{"id":109},"what-can-we-learn-from-this","What can we learn from this?",[11,112,113],{},"It's been shown in this article that several engineers warned several times about the O-ring's issues. However, they \"ignored them\" even with precise data that showed that the orbiter could explode.",[11,115,116],{},"Hence, was the message not clear enough? Didn't they provide enough good information? They did, but there was pressure from other spheres about the launch day. The critical part is meeting without any engineers between NASA and the contractor. Why do you want to remove them if it is not to silence them and manipulate the rest to achieve your goal of launching the day you wanted it to do it? The most depressing part is that engineers asked to postpone the launch, not to cancel the flight (even though this was risky as hell as well).",[11,118,119],{},"Luckily, all engineers involved with the O-ring tests and problems documented everything, which helped clarify the problem and how NASA pressured Thiokol to get the approval. They left signed documents recommending postponing the launch, as well as not signing documents that approved the launch.",[11,121,122],{},"These engineers were the best professionals I can think of: they risked their jobs by opposing top bosses within the command line.",[11,124,125],{},"The takeaway from this specific case, and other engineers, is to always document everything. Documentation will save you and your project if something is pushed like this without your approval. If things go awry, you will always have proof that you at least tried to inform your superiors about the possible consequences. Also, build tests. Test everything. Even when testing everything, there will be tons of uncertainty and errors. Tests help us reduce, manage, and handle that uncertainty properly.",[11,127,128],{},"And yes, I'm a computer engineer; I don't build rockets, but pressures to launch products without proper tests always happen. Finding the right balance is something you have learned over the years, but launching a project because someone is pushing you is different from the right way of doing things. And if you re-read everything, that scenario could lead to the worst possible outcome: deaths. Yes, this is an exaggeration because most of us build web or phone apps, but now that software is ubiquitous, engineers should take all this stuff more seriously. AI, web3, etc. possess great power, and we should be vigilant and take care of what we build, how we test it, and also, really importantly, how we report problems back to our superiors and convince them to avoid the subsequent big failure.",{"title":49,"searchDepth":130,"depth":130,"links":131},2,[132,137],{"id":17,"depth":130,"text":18,"children":133},[134,136],{"id":31,"depth":135,"text":32},3,{"id":78,"depth":135,"text":79},{"id":109,"depth":130,"text":110},"2024-01-01T00:00:00.000Z","undefined","md",null,"learning-from-failure","blog",{},true,"/blog/en/2024-01-01-learning-from-failure",{"title":5,"description":139},"blog/en/2024-01-01-learning-from-failure","develpment, engineering, failure, ethics","U_P4Tew3IMn4a9koPH_vUNh3gvHB0RWLEsB_ICq6gPs",[152,461,541,703,786,935,1019,1090,1490,2065,2184,2397,2637,2880,3080,3280,3452,3641,3800,3885,5217,5809,6324,6693,7301,7553,7750,7925,8372,8528,8788,8955,9322,9775,10012,10082,10202,10372,10667,10837,11294,11482,11672,11833,12062],{"id":153,"title":154,"author":6,"body":155,"date":452,"description":453,"extension":140,"headline":141,"icon":454,"icon_author":141,"icon_url":141,"layout":143,"location":141,"meta":455,"meta_description":141,"navigation":145,"path":456,"quote":141,"seo":457,"slug":458,"stem":459,"tags":141,"template":141,"__hash__":460},"blog/blog/en/2026-03-01-claude-improved-my-keyboard-firmware.md","I let Claude improve my keyboard's firmware",{"type":8,"value":156,"toc":440},[157,160,163,172,175,179,182,191,195,210,213,217,220,227,230,234,237,240,244,250,253,256,259,263,266,269,272,276,279,288,291,296,299,302,305,309,312,315,318,321,324,327,331,334,337,340,358,361,366,372,375,378,381,384,390,393,396,400,403,406,409,412,415,418,421,424,435],[11,158,159],{},"About a year ago, I decided it was time to move from my mechanical, cheap keyboards to something fancier.",[11,161,162],{},"While I love the clicky sounds of mechanical keyboards, I was missing something: I code for long hours, and my\nback and neck hurt a lot, not because of the keyboard, but it had something to do with it.",[11,164,165,166,171],{},"When my last keyboard started to fail, I found a Spanish builder of ",[37,167,170],{"href":168,"rel":169},"https://github.com/foostan/crkbd",[41],"Corne Keyboards","\n(unfortunately the shop closed a few months ago). The corne got my attention because it is a split keyboard and I thought\nthat it would help me to relax my back, as I could have my arms in a more natural position while typing. Thus, I got one!",[11,173,174],{},"When the keyboard arrived, I was really excited to test it, but, as with any big change, I was going to suffer a lot in the beginning. Why? Because it is an ortholineal keyboard (the keys are just one finger away in up, down, left, and right directions)\nand you need to learn the new positions while you adapt. Moreover, I type in Spanish, but I also write in English, so chars like Ñ\nwere difficult in the first place :-)",[15,176,178],{"id":177},"the-first-stages-with-the-keyboard","The first stages with the keyboard",[11,180,181],{},"As you start adapting to the keyboard, you discover you can flash different configurations into it.\nWhy would you want to flash a firmware to your keyboard? Well, I'm glad that you have asked that question; you want to do it because\nyou can customize it for yourself. More importantly, as this keyboard has fewer keys than a normal keyboard, you need to enable \"layers\" that\nallow you type them (layers are what you enable in your Android or iOS phone to type numbers, symbols, etc.).",[11,183,184,185,190],{},"The first approach for this flashing is connecting your keyboard to a ",[37,186,189],{"href":187,"rel":188},"https://www.usevia.app/",[41],"web page"," where you can modify the keys by clicking and typing\nsome commands. At the beginning, this works, but at some point, while you read what your keyboard and others are doing, you say fuck it, I will do it\nby actually compiling some C code. What could go wrong, right?",[15,192,194],{"id":193},"the-enlightenment-phase","The Enlightenment phase",[11,196,197,198,203,204,209],{},"It turns out that compiling your QMK firmware isn't that difficult. The ",[37,199,202],{"href":200,"rel":201},"https://qmk.fm",[41],"documentation site"," is amazing, and you only have\nto ",[37,205,208],{"href":206,"rel":207},"https://en.wikipedia.org/wiki/RTFM",[41],"RTFM",", and play along.",[11,211,212],{},"At this moment, I was actually hacking the firmware of my keyboard almost every single day. As you can now improve every single aspect of it,\nyou end up looking for hacks and improvements to maximize your WPM while having the best typing experience.",[29,214,216],{"id":215},"first-hacks","First hacks",[11,218,219],{},"The first thing I did was turn off all the lights. I don't know how people can type with so many bright lights; they're distracting to me.",[11,221,222,223,226],{},"The next hack was handling the symbols: ",[224,225],"span",{},", (), {}. With QMK, you can make it so that when you type just {, it writes that curly brace, but if you type it twice\nquickly, it actually types }. The same for all the symbols, so you could save one character from your keyboard if you remember this hack.",[11,228,229],{},"As you can imagine, and I don't want to write all the changes I made, I was changing this behavior here and there until I had something I felt good about.",[15,231,233],{"id":232},"my-keyboard-meets-ai","My keyboard meets AI",[11,235,236],{},"While I was fine with the current setup for my keyboard, I realized that the code was pretty small, only 3 files that you touch, they are easy to understand, and\ndue to the constraints of my keyboards's memory I cannot do too many fancy stuff.",[11,238,239],{},"In any case, while I have not been compiling the firmware for some weeks, I had some keys and combos that didn't work out as I wanted, so I thought: what if I give\nmy files to Gemini, ChatGPT, or Claude to get some improvements? So I started with ChatGPT.",[29,241,243],{"id":242},"chatgpt","ChatGPT",[11,245,246],{},[247,248,249],"em",{},"NOTE: This test was run before November 2025.",[11,251,252],{},"With ChatGPT, it was just a disaster. I copied and pasted the layout with all the layers, my old animations, etc., and the recommendations were bad, really bad.",[11,254,255],{},"The AI didn't know which keys were in which hand; it gave me solutions to press two keys with the same finger, making the combo impossible, etc.",[11,257,258],{},"It was that bad that I didn't use it at all.",[29,260,262],{"id":261},"gemini","Gemini",[11,264,265],{},"With Gemini, I had the same experience as with ChatGPT. It didn't work well because it was mixing all the keys and giving me advice that didn't work.",[11,267,268],{},"Thus, I just gave up as I was better on my own.",[11,270,271],{},"Now fast forward to Feb 2026.",[29,273,275],{"id":274},"claude","Claude",[11,277,278],{},"I started paying Claude in January 2026 to update my old website (where you are reading this blog post, I assume). I will write about this experiment in another blog\npost because I have a lot to share. The best part? My site was using a very old version of VueJS and NuxtJS with external JS libraries that are non-existent right now\nin npm, and updating it to the latest versions of everything will be a nightmare.",[11,280,281,282,287],{},"Well, back to my keyboard. This time, I have been extensively using Claude for coding, asking questions, and fixing stuff here and there, and I said, \"Let's try it again.\" Specially\nbecause I'm using a Mac at work and I have installed a tiling window manager (hello ",[37,283,286],{"href":284,"rel":285},"https://github.com/nikitabobko/AeroSpace",[41],"AeroSpace","), so I was thinking of ways of improving my keyboard firmware to better serve me\nusing AeroSpace.",[11,289,290],{},"At the beginning, I asked Claude what I could remove from my AeroSpace, as some of them were there for testing and I probably wasn't using them. The suggestions came\nin, I removed them, and I was happy, then I thought: what if I tell Claude that I have a corne keyboard and I upload my C files so Claude can help me? Well, if you want to know the answer,\nfollow me on this adventure.",[292,293,295],"h4",{"id":294},"cleaning-up-the-code","Cleaning up the code",[11,297,298],{},"The first part was asking for some suggestions, and Claude suggested some nice fixes for my code. They were nice suggestions, so I asked Claude to fix them for me. The files came in,\nand the compilation went smoothly. Easy peasy, first impression is good.",[11,300,301],{},"Then, I asked Claude about the animations and what I wasn't using because of the configurations in my files. Well, Claude found all the issues and suggested proper fixes for me.\nAll of them worked like a charm.",[11,303,304],{},"As everything was working, I thought: what if I explain to Claude my problems with the current layout and see what Claude suggests?",[292,306,308],{"id":307},"breaking-the-code","Breaking the code",[11,310,311],{},"At this stage, I explained to Claude: I'm a Spanish person, so my keyboard has to be in Spanish, but I write in English as well. Take this into account because the ñ must exist by default\nin my keyboard (the C files explicitly use the Spanish layout, so the code already tells you this, ok?).\nThen I said, \"What can I improve with the current layouts? What do you suggest?\"",[11,313,314],{},"The first suggestions were to remove some keys in some layers that I have duplicated (in most cases, from my experiments to see how a specific code works). I asked Claude to fix them by removing\nthem, and this worked well.",[11,316,317],{},"Then I asked for other improvements, and Claude started doing stupid things.",[11,319,320],{},"The most frustrating part was to know that Claude had all the layers and code, so everything was there for Claude to explore and improve; however, after each improvement, Claude was removing keys\nto fit other keys from its improvements. Claude didn't know which letters were on the left hand or in the right hand, even though the code clearly states that. After several errors and my frustration\nI told Claude to tell me which keys are on the left and which are on the right, and that the number of keys I have available is not the number of keys on a regular keyboard. Yep, Claude couldn't get this\nright on its own.",[11,322,323],{},"After working on this for some time, Claude finally started to make sense again, and the suggestions started to work again. Actually, the layouts I'm using have been reorganized by Claude, and they work well (I'm still adapting to them, but so far, so good).",[11,325,326],{},"With the layers in place, I wanted to try something different: what can Claude do with the OLED screens? Can Claude make them more useful?",[292,328,330],{"id":329},"playing-with-oled-screens","Playing with OLED screens",[11,332,333],{},"My previous designs were simple: on the left screen, a design with 4 layers to show in which layer I'm in while I'm typing, and on the right side, some icons, nothing fancy.",[11,335,336],{},"While the layer design is nice, I asked Claude what can be done to improve it. Claude suggested adding a WPM counter. I thought that it was a good idea, so I asked Claude to design something so\nI could try it. Claude suggests creating an oscilloscope to display WPM, and it is a good idea. Actually, Claude suggests creating a web page to show me the designs, so I can validate before\nflashing the firmware.",[11,338,339],{},"As I liked what Claude showed me, I decided to ask for something more complex: what if you could design it like an old sci-fi film, like Alien's Mother computer, Tron, or Star Trek?",[11,341,342,346,350,354],{},[47,343],{"alt":344,"src":345},"Hal theme","/img/blog/hal.jpg",[47,347],{"alt":348,"src":349},"L-Cars theme","/img/blog/l-cars.jpg",[47,351],{"alt":352,"src":353},"Ghost in the shell theme","/img/blog/ghost-in-the-shell.jpg",[47,355],{"alt":356,"src":357},"Tron theme","/img/blog/tron.jpg",[11,359,360],{},"The first designs were ok because the mockups looked good. Actually, some of them look promising. At this moment, it might be possible to use a custom font to make things more interesting. The answer was yes, but at what cost? I shared two Google fonts, so Claude could work with them. The reality and the mockups were harsh. Moreover, I own a Garmin, and since it has an MFT screen, the designs available for this watch are, in general, amazing, so I uploaded some screenshots of themes I like as inspiration. Here you have two of the themes that Claude created for me:",[11,362,363],{},[47,364],{"alt":356,"src":365},"/img/blog/tron-theme.jpg",[11,367,368],{},[47,369],{"alt":370,"src":371},"Garmin theme","/img/blog/garmin-theme.jpg",[11,373,374],{},"While Claude thought everything worked as expected (the mockups showed something working more or less), in the real OLED display, only some characters used the real font. At the same time, the rest kept using the QMK firmware font.",[11,376,377],{},"Interestingly, I discussed a lot with Claude about this, and we finally\ngot something that somehow worked (I gave up on getting the font everywhere). With the font looking good enough, I decided to use it in the WPM. Bad decision.",[11,379,380],{},"The WPM was designed by Claude as an oscilloscope: the faster you type, the bigger the signal, so you can see how fast you type, as the bars go up and down as you write. The first design worked really well, pretty\nbasic, but well. Then I asked Claude to make it a bit different, use the font we worked on together, and put the chart on top. This is when things got messy: the font started to overwrite itself all\nthe time, leaving blank spaces in the characters.",[11,382,383],{},"For me, it was clear that the problem was related to the OLED display's refresh, but Claude was not sure. Claude invested a lot of time trying to fix it, only to end up with a solution that was too ugly and expensive to use.\nThe AI suggested using a bigger font, so it could render it properly, but while it looked good, the design was bad, really bad, so I asked Claude to completely ditch it. The following screenshot is where you can see Claude thinking and trying hard to solve the problem:",[11,385,386],{},[47,387],{"alt":388,"src":389},"Claude thinking","/img/blog/claude_oled_thinking.jpg",[11,391,392],{},"At the end, the real cause of this problem was that Claude used two different rendering systems, fighting to write characters to the screen.",[11,394,395],{},"Up to this moment, I was working only on one screen, but the other one should work as well and should show something: the layer, the wpm, something. I asked Claude to add something simple, and it suggested showing the layer\nname and the wpm without the oscilloscope. I compiled the firmware, flashed it, and discovered that nothing happened. The display showed the text, but when I typed, nothing changed, and if I changed the layer, nothing was\nreflected. I told Claude about it, and Claude started to think about where the problem could be. At some point, it suggests that the problem was related to having a split keyboard -seriously- so it suggests adding one config\nto fix it. It actually fixes it, but it is incredible that after having the code, telling Claude that I have a corne, which is a split keyboard, Claude does not realize anything like this.",[29,397,399],{"id":398},"the-good-the-bad-and-the-ugly","The good, the bad, and the ugly",[11,401,402],{},"While I had suffered Claude, and with Claude, the truth is that it works. Using AI to build firmware that the LLM cannot test on real hardware is a problem. When you develop with AI, you should use\nsome tests to allow the AI to know what's working,  what's not, so you can avoid future problems when it hallucinates. Because that will happen (I have been there).",[11,404,405],{},"But even with these problems, it has created a smooth animation for my keyboard that would have been really difficult for me to do on my own. Also, it has suggested some configurations that I would not have thought about, so\nall this thinking out of the box pays off to some extent. Also, it is fun, really fun, to develop like this.",[11,407,408],{},"The biggest problem was with the custom font. Claude tried as hard as possible, actually taking minutes to think and correcting itself several times. It contradicted, fixed, and wrote the same conclusions, finally offering a solution that worked, somehow, but was suboptimal. Even with this big problem, it was fun to watch it discussing with itself while I was afraid of all the tokens it was burning (knowing that the answer was going to be bad).",[11,410,411],{},"Will I use the Claude again for this? Yes, for sure. And I'm planning to add some skills as well, because my configuration has some quirks and needs to remember them. Is it ready for everyone? Nope, not yet, especially\nif you are using the keyboard yourself every day, you still need to read the code, tell Claude where things are wrong, what keys and suggestions do not work because it is suggesting something impossible, or because it breaks\nyour compilation completely. But it is fun, and it works if you know what you are doing.",[11,413,414],{},"This experience has been really useful. Using AI gives you super-powers, as you can try more things, learn more things, and improve what you do. But don't get me wrong, you need to be the one leading, as some crazy ideas will be thrown at you.",[11,416,417],{},"While I have been using Claude for other software projects, building firmware with it is quite different. Not having a way for the AI to test what happens in the hardware is a problem, as it cannot check what's going on, see errors, and fix them. For my keyboard, the AI would need a webcam to check the OLED designs, a robotic hand to type and verify that everything works, and, more importantly, to deal with my Homerow configuration, which is not easy to manage.",[11,419,420],{},"In summary, Claude has been and remains really useful. It has its issues, but that's fine.",[11,422,423],{},"Here you have two videos about how the oscilloscope works and how layers switch. At the end, I didn't use any of the original themes, and I kept a simple list of 1s and 0s to look like the Matrix. This time, simplicity won out. However, I might change it later, as the Ghost\nIn the Shell and LCARS designs look good again to me after writing this blog post :-)",[425,426,428,429,434],"video",{"width":427,"controls":145},"100%","\n  ",[430,431],"source",{"src":432,"type":433},"/vid/corne-wpm.mp4","video/mp4","\n  Your browser does not support HTML5 video.\n",[425,436,428,437,434],{"width":427,"controls":145},[430,438],{"src":439,"type":433},"/vid/corne-layers.mp4",{"title":49,"searchDepth":130,"depth":130,"links":441},[442,443,446],{"id":177,"depth":130,"text":178},{"id":193,"depth":130,"text":194,"children":444},[445],{"id":215,"depth":135,"text":216},{"id":232,"depth":130,"text":233,"children":447},[448,449,450,451],{"id":242,"depth":135,"text":243},{"id":261,"depth":135,"text":262},{"id":274,"depth":135,"text":275},{"id":398,"depth":135,"text":399},"2026-03-01T00:00:00.000Z","A short story about how Claude improved my keyboard's firmware","claude-keyboard-firmware",{},"/blog/en/2026-03-01-claude-improved-my-keyboard-firmware",{"title":154,"description":453},"claude-improved-my-keyboard-firmware","blog/en/2026-03-01-claude-improved-my-keyboard-firmware","x9vsQ5yTa4PDvk5MFllQSAx3o6eHeULHdKWNI-r-w4g",{"id":462,"title":463,"author":6,"body":464,"date":533,"description":534,"extension":140,"headline":141,"icon":535,"icon_author":141,"icon_url":141,"layout":143,"location":141,"meta":536,"meta_description":141,"navigation":145,"path":537,"quote":141,"seo":538,"slug":535,"stem":539,"tags":141,"template":141,"__hash__":540},"blog/blog/en/2024-11-30-farcaster-vs-at-protocol.md","Farcaster vs AT Protocol",{"type":8,"value":465,"toc":530},[466,475,479,482,485,488,491,494,497,500,503,506,518,521,524,527],[11,467,468,469,474],{},"A long time ago, I wrote about two decentralized protocols: ",[37,470,473],{"href":471,"rel":472},"https://paragraph.xyz/@teleyinex.eth/farcaster-vs-lens-protocol",[41],"Lens vs Farcaster",". That blog post explored the differences and similarities of both protocols. Time has passed, and while I still have an account on Lens, I mainly use Farcaster through Warpcast. However, at some point, I got an invite to join Bluesky. Again, I should have been using it more. Still, recently, on Farcaster, people have been asking about Bluesky protocol, AT, and I decided to write a new blog post comparing Farcaster and AT protocol.",[15,476,478],{"id":477},"shared-vision-decentralization-user-empowerment","Shared Vision: Decentralization & User Empowerment",[11,480,481],{},"At their core, the AT Protocol and Farcaster share the vision of decentralizing social media. These protocols were not just created to give back control to their users, but to empower them in a world where control is often elusive.",[11,483,484],{},"Both protocols use robust cryptographic solutions to ensure that everything you post or cast (as it is said on Farcaster) belongs to you and no one else. This level of security provides a strong reassurance that you can prove you are the author everywhere.",[11,486,487],{},"As I wrote in a previous article, Farcaster uses what they call Farcaster IDs. These IDs are numeric identifiers linked to user-controlled cryptographic keys. These IDs are handled on smart contracts, and while they are kept under control by the contract owner, they are kind of \"decentralized.\"",[11,489,490],{},"On the other hand, the AT protocol uses the definition of Decentralized IDs and supports two of them: did:web and did:plc. The first one allows you to use DNS solutions to link it to your domain (if you check my handle in Bluesky, you will see my domain); the second one did:plc was created by them because they were unsatisfied with any of the existing DID methods. As with the FIDs, these are also a bit centralized, so they remain more or less the same in terms of functionalities and \"decentralization\".",[11,492,493],{},"Once we know how to create an account, it is time to think about how to create content on those networks. The AT protocol uses Content Identifiers (CIDs) to link and reference data. Any change to one of these items will produce a new CID. Farcaster uses hashes for each message, which ensures that if someone modifies it, a new hash will be produced.",[11,495,496],{},"The content in the AT protocol is defined through Lexicons. A lexicon defines how content can be created and which specific format for posts, profiles, etc.",[11,498,499],{},"On Farcaster, we have messages that will belong to the network's global social graph. The messages have information about the author, their content, a timestamp, and their relationship to other messages.",[11,501,502],{},"We now know more or less how you can create your content, but how do they distribute them within their network?",[11,504,505],{},"In the case of the AT protocol, they use Personal Data Servers. These servers are controlled by people like you and me but also by third parties like Bluesky themselves, so you can use the protocol without having to do anything fancy on your side. To distribute the content, they use relays that index all or part of these PDS to create a unique view that can be consumed by other clients to present a state of the world in the AT sense.",[11,507,508,509,513,514,517],{},"Farcaster uses Hubs. These nodes are connected using the \"gossippub protocol\" that allows them to distribute the messages that you have created, likes, follows and unfollows. Farcaster uses ",[510,511,512],"strong",{},"CRDTs"," to enable concurrent updates to the message-graph, ensuring eventual consistency across all Hubs. It also uses ",[510,515,516],{},"Diff Sync"," as a backup mechanism, ensuring complete synchronization even if gossip encounters issues. With all these technologies and solutions involved, Farcaster will eventually find consistency over immediate updates, which means that you and your friend will almost always see the same trending topics simultaneously.",[11,519,520],{},"While the Farcaster protocol explains how they deal with conflicts, I have not found how they deal with these scenarios within the AT protocol's documentation. If someone has information about it, it would be great if you shared it with me so I can add it here.",[11,522,523],{},"Finally, Farcaster has something really cool. It allows developers to create apps that lean on the network within the protocol. This technology, called Frames, will enable people to run mini-applications directly with their clients, so they don't have to leave their clients to do something. It is really cool because you can buy stuff directly there, create polls, read blog posts, etc.",[11,525,526],{},"AT protocol provides documentation about how to create your own software using their solution, but it seems to have a different approach regarding how Farcasters is evolving.",[11,528,529],{},"With all that said, while both protocols seem similar they have core technical differences. I still like more Farcaster but probably because it is the network I use the most.",{"title":49,"searchDepth":130,"depth":130,"links":531},[532],{"id":477,"depth":130,"text":478},"2024-11-30T00:00:00.000Z","Decentralizing networks one bit at a time ","farcaster-vs-at-protocol",{},"/blog/en/2024-11-30-farcaster-vs-at-protocol",{"title":463,"description":534},"blog/en/2024-11-30-farcaster-vs-at-protocol","CPqm8I627xvCtZc1sXjfx3SIBk4DD6BGSXrVzgF4cjY",{"id":542,"title":543,"author":6,"body":544,"date":694,"description":695,"extension":140,"headline":141,"icon":696,"icon_author":141,"icon_url":141,"layout":143,"location":141,"meta":697,"meta_description":141,"navigation":145,"path":698,"quote":141,"seo":699,"slug":696,"stem":700,"tags":701,"template":141,"__hash__":702},"blog/blog/en/2024-01-28-farcaster-frames.md","Farcaster Frames Unleashed",{"type":8,"value":545,"toc":685},[546,555,558,561,564,580,583,586,590,593,596,599,603,611,616,625,628,631,634,640,644,647,650,654,657,660,667,671,674,682],[11,547,548,549,554],{},"This last Friday, the Farcaster team released something cool: ",[37,550,553],{"href":551,"rel":552},"https://warpcast.notion.site/Farcaster-Frames-4bd47fe97dc74a42a48d3a234636d8c5",[41],"frames",".",[11,556,557],{},"Frames are just \"little\" web apps that you can build if you know how to code a bit of HTML and JS and generate some images (on the fly or with your preferred tool).",[11,559,560],{},"These apps' magic comes from hacking the open graph from Meta (aka Facebook). What they have done is really smart: they've added a few custom meta-tags that allow you to add functionality to any URL posted into the Farcaster ecosystem.",[11,562,563],{},"If you want to know all the details, just read the full documentation, but basically, you add 3 new tags into your HTML head:",[565,566,567,571,574,577],"ul",{},[568,569,570],"li",{},"\"fc:frame\": specifies which version of the frames you are using",[568,572,573],{},"\"fc:frame:image\": the image that will be shown to the users in their apps.",[568,575,576],{},"\"fc:frame:button:N\": the Button (or buttons, up to 4) to be created by the Farcaster client so people can interact with your web app.",[568,578,579],{},"\"fc:frame:post_url\": and a link where you will get a payload with the button that the user clicked.",[11,581,582],{},"And this is magical. Why? You can create web apps really quickly, but let's go over something else: what if you get not only the button that the user clicked but also real proof that you can validate against any of the nodes of Farcaster to validate the real user and not a fake bot? That's even better, and it allows you to do things like minting NFTs directly in the Farcaster ecosystem.",[11,584,585],{},"As this was released on Friday, I couldn't resist, and instead of watching some new Netflix shows, I decided to try it and build something.",[15,587,589],{"id":588},"rock-paper-scissors-game","Rock, paper, scissors game",[11,591,592],{},"Friday night was about finding my way with the requisites and building something to work. I created a proof of concept that showed only one button and that when you click it, you get another image. Nothing useful, but it worked.",[11,594,595],{},"When I was satisfied and going to bed, it occurred to me that I could do better, and suddenly, the game rock, paper, scissors looked like a nice project to publish.",[11,597,598],{},"The idea is to show a welcome image, just the rock, paper, and scissors. Then, three buttons with the names of rock, paper, and scissors. If you click one of them, the chosen option is sent to my API. The API will randomly pick one of the three options and see who wins. Based on that, the API returns the new image to show the user so she can know if she won.",[29,600,602],{"id":601},"technologies-that-i-used-to-create-it","Technologies that I used to create it",[11,604,605,606],{},"For creating the images, I've used Inkscape and some SVGs from ",[37,607,610],{"href":608,"rel":609},"https://openmoji.org/",[41],"Openmoji",[11,612,613],{},[47,614],{"alt":49,"src":615},"/img/blog/farcaster-frames-1.jpg",[11,617,618,619,624],{},"Then, for the API and the website, I chose ",[37,620,623],{"href":621,"rel":622},"https://nuxt.com/",[41],"NuxtJS",". The reason is that I love Vue, and it is one of those tools that can help you build a site in minutes easily. The best part is that it has SSR, so you can write your own APIs directly, managing the back and the front in only one place.",[11,626,627],{},"The web app has only two elements: the web page with its farcaster meta tags and the callback post API endpoint, where I will get the buttons that the user has clicked.",[11,629,630],{},"With all this up and running, I deployed it to Vercel and got it running. At this point, I wanted to test something else: saving the number of times a farcaster user wins, loses, and gets a tie with the machine. To do this, I have used the Vercel kv Redis solution.",[11,632,633],{},"After publishing the game, Farcaster's users started to play, and in a matter of minutes, I ran out of queries against Redis because I'm using the free plan :-) 3000 queries were done in a matter of minutes, so the game got some really good traction. Luckily, this limit is reset every day, so today you can play it until I run out again of queries 😋",[11,635,636],{},[37,637,638],{"href":638,"rel":639},"https://warpcast.com/teleyinex.eth/0x3eb254ce",[41],[15,641,643],{"id":642},"choose-your-own-adventure","Choose your own adventure",[11,645,646],{},"With the previous game already finished, I started to see a pattern: generating images on the fly will be a problem in general because the server takes time to connect to other services like Redis or another DB, so adding on top of that generating images will make people think that your app is not working. The solution is simple: pregenerate all the images at once.",[11,648,649],{},"To do that, I created a Choose Your Own Adventure game. The idea was to user AI to create the story, so I jumped into chatGPT and asked a story for an elf, crawling a dungeon. The AI returned a JSON that had all the options, so all that was left to me was to create a Python script that would generate images with the written text from that JSON file.",[29,651,653],{"id":652},"technologies-i-used-for-choose-your-own-adventure","Technologies I used for Choose Your Own Adventure",[11,655,656],{},"For the images, my beloved Python was the choice. I used Pillow, and after figuring out how to split the lines of text to fit the size of the frame, I got something up and running easily.",[11,658,659],{},"Now it was time to write a new frame with NuxtJS. Re-using part of the rock, paper, scissors frame, I was able to create this game quickly. All I had to do was use the Redis KV solution from Vercel to save the last step chosen by the user to present the next image and which option she has to advance on her adventure.",[11,661,662,663],{},"Now go and play it: ",[37,664,665],{"href":665,"rel":666},"https://warpcast.com/teleyinex.eth/0xb36887c2",[41],[15,668,670],{"id":669},"lessons-learned","Lessons learned",[11,672,673],{},"I think the Farcaster team has done something really unique and smart here. These apps could bring lots of devs into the Farcaster ecosystem because it's damn easy to create a frame. Moreover, the possibilities are endless with all the web3 stuff you can do. However, there are some issues they will need to address for future versions:",[565,675,676,679],{},[568,677,678],{},"Loading states: if your API is slow, you get the impression that nothing is happening. The clients usually blur the image, but you don't know if it is loading. It will be cool to have something like that in new versions.",[568,680,681],{},"Getting a first POST as soon as the user visualizes the frame: why? For example, my Choose Your Own Adventure game will allow me to show the user her last step. This will allow users to resume any frame where they left it, which I think is pretty nice.",[11,683,684],{},"My next steps involve using the web3 aspect of it. I've not used it because it involves connecting through a hub, and the prices for hobbyists like me are too high. Hopefully, more hub runners will soon offer APIs with a free plan.",{"title":49,"searchDepth":130,"depth":130,"links":686},[687,690,693],{"id":588,"depth":130,"text":589,"children":688},[689],{"id":601,"depth":135,"text":602},{"id":642,"depth":130,"text":643,"children":691},[692],{"id":652,"depth":135,"text":653},{"id":669,"depth":130,"text":670},"2024-01-28T00:00:00.000Z","Simplifying App Development within Your Social Graph","farcaster-frames",{},"/blog/en/2024-01-28-farcaster-frames",{"title":543,"description":695},"blog/en/2024-01-28-farcaster-frames","web3, farcaster, webapp","vBpfmwI_Tv62G3GRkYVT2uXyZM0UiylVeAfQ9HoLhFU",{"id":4,"title":5,"author":6,"body":704,"date":138,"description":139,"extension":140,"headline":141,"icon":142,"icon_author":141,"icon_url":141,"layout":143,"location":141,"meta":784,"meta_description":141,"navigation":145,"path":146,"quote":141,"seo":785,"slug":142,"stem":148,"tags":149,"template":141,"__hash__":150},{"type":8,"value":705,"toc":777},[706,708,710,712,714,716,718,723,727,729,731,733,735,737,739,741,743,745,747,749,751,753,755,757,759,761,763,765,767,769,771,773,775],[11,707,13],{},[15,709,18],{"id":17},[11,711,21],{},[11,713,24],{},[11,715,27],{},[29,717,32],{"id":31},[11,719,35,720,43],{},[37,721,42],{"href":39,"rel":722},[41],[11,724,725,51],{},[47,726],{"alt":49,"src":50},[11,728,54],{},[11,730,57],{},[11,732,60],{},[11,734,63],{},[11,736,66],{},[11,738,69],{},[11,740,72],{},[11,742,75],{},[29,744,79],{"id":78},[11,746,82],{},[11,748,85],{},[11,750,88],{},[11,752,91],{},[11,754,94],{},[11,756,97],{},[11,758,100],{},[11,760,103],{},[11,762,106],{},[15,764,110],{"id":109},[11,766,113],{},[11,768,116],{},[11,770,119],{},[11,772,122],{},[11,774,125],{},[11,776,128],{},{"title":49,"searchDepth":130,"depth":130,"links":778},[779,783],{"id":17,"depth":130,"text":18,"children":780},[781,782],{"id":31,"depth":135,"text":32},{"id":78,"depth":135,"text":79},{"id":109,"depth":130,"text":110},{},{"title":5,"description":139},{"id":787,"title":788,"author":6,"body":789,"date":926,"description":927,"extension":140,"headline":141,"icon":928,"icon_author":141,"icon_url":141,"layout":143,"location":141,"meta":929,"meta_description":141,"navigation":145,"path":930,"quote":141,"seo":931,"slug":928,"stem":932,"tags":933,"template":141,"__hash__":934},"blog/blog/en/2023-09-17-securing-minting-links.md","Ensuring secure minting amidst scam link threats",{"type":8,"value":790,"toc":917},[791,795,798,804,807,811,814,817,820,824,830,833,841,845,854,857,861,868,873,876,881,892,898,901,904,907,911,914],[15,792,794],{"id":793},"understanding-the-threat","Understanding the Threat",[11,796,797],{},"Scam links pose a significant risk in the world of cryptocurrency, especially when it comes to minting new tokens. A few days ago, Vitalik's Twitter (or X, or whatever) account was hacked, and a tweet message was posted:",[11,799,800,803],{},[47,801],{"alt":49,"src":802},"/img/blog/securing-minting-links-1.jpg","Image embeds on cast",[11,805,806],{},"The link is fake, but some people will not notice it because the Twitter card shows phony information, and people will try to claim it. Then, bad things happen.",[15,808,810],{"id":809},"identifying-scam-links","Identifying Scam Links",[11,812,813],{},"Several red flags can help identify potential scam links. However, they involve a lot of effort, and usually, people will not check it. This is where wallets should start catching up ASAP because the safety of everyone is paramount, especially within the web3 ecosystem.",[11,815,816],{},"The trick in the previous tweet is that you can put any information in that card, so people can jump without checking anything. The subtle change of the domain is difficult to catch, and as this tweet comes from a genuine verified (sigh) account on Twitter, most people will trust it without double-checking.",[11,818,819],{},"Impersonating prominent people is one of the most successful vectors because people usually trust anything they publish. But when an account gets compromised, the links they publish should be verifiable so the users (or even better, the wallets) can double-check if the posted link is valid for the smart contract they are promoting.",[15,821,823],{"id":822},"using-gpg-for-signing-and-verifying-minting-links","Using GPG for signing and verifying minting links",[11,825,826,827,554],{},"In my head, the only feasible solution was to use GPG so creators, especially smart contract developers of NFTs, could sign their official site with their private key, and anyone could verify it using its public key. In this way, as users, we will be able to verify the posted link once we open it in our browser, or even better, before doing that, we could verify the link is legit because ",[510,828,829],{},"the owner has signed it",[11,831,832],{},"If the Twitter account gets compromised, they could publish a malicious link, but it will be much harder to sign the link unless they have hacked the user's laptop and password to unlock it. If we wanted top-notch security, this could be even \"impossible\" if the GPG key is stored in a Yubikey, as you will need again to steal the actual hardware and the pin to access it.",[11,834,835,836],{},"While this sounds safe, I was missing the web3 approach to it. And then, I discovered ",[37,837,840],{"href":838,"rel":839},"http://attest.sh",[41],"attest.sh",[15,842,844],{"id":843},"using-attest-for-signing-and-verifying-minting-links","Using attest for signing and verifying minting links",[11,846,847,848,853],{},"If you don't know, ",[37,849,852],{"href":850,"rel":851},"http://Attest.sh",[41],"Attest.sh"," you should check it out. This fantastic solution allows you to create, verify, and revoke on/off-chain attestations.",[11,855,856],{},"The exciting part is that you can create a schema that could be re-used by other projects and improve the security among the NFT community.",[29,858,860],{"id":859},"how-would-it-work","How would it work",[11,862,863,864,867],{},"The ",[37,865,852],{"href":850,"rel":866},[41]," site has several schemas that you can directly use. For example, a simple way of attesting links would be using the Website URL schema:",[11,869,870],{},[47,871],{"alt":49,"src":872},"/img/blog/securing-minting-links-2.jpg",[11,874,875],{},"With this schema, then you can do an attest that can look like this:",[11,877,878],{},[47,879],{"alt":49,"src":880},"/img/blog/securing-minting-links-3.jpg",[11,882,883,884,887,888,891],{},"With this schema, we can, as the owners of our NFT contract, attest the official link to our minting project. We will use our wallet address, the same that deployed the contract, in the ",[247,885,886],{},"From"," field, and in the ",[247,889,890],{},"To,"," we will use the just deployed contract address.",[11,893,894,895,554],{},"Then, ANYONE can verify that the link is valid and safe because ",[510,896,897],{},"only the contract deployer would be the one attesting to a valid link to the contract she just deployed",[11,899,900],{},"This will be as secure as the wallet and the person who manages it. While soft wallets will be mildly secure, the best way would be with a hardware wallet or, even better, a multi-sig wallet. In the last two cases, only by stealing the hardware wallet and knowing the pin or hacking the multi-sig wallets would it be possible to publish a fake link to the minting site.",[11,902,903],{},"The best part of the attestations is that you can do them on-chain, so the wallets could verify this automatically when you are trying to mint to warn you or even forbid you to sign any transaction to protect you from fake links.",[11,905,906],{},"Now you might wonder: what if the link has expired, or if we want to change it? If the link has expired or has been updated, they can always revoke the attestation and create a new one with the updated URL.",[15,908,910],{"id":909},"conclusion","Conclusion",[11,912,913],{},"Signing links could be the way to build trust within the NFT community, especially for those projects that have tons of users. When they have to publish a new project, they have to tell people to check retweets from other founders and double-check on Discord to know that the link is legit and none of the owners' accounts have been hacked (this has happened so many times on Discord that I've lost the count).",[11,915,916],{},"The process will be as simple as publishing the link and the attestation so anyone can verify that the attest was created by the wallet that deployed the contract and that the contract's owner is the attestation recipient.",{"title":49,"searchDepth":130,"depth":130,"links":918},[919,920,921,922,925],{"id":793,"depth":130,"text":794},{"id":809,"depth":130,"text":810},{"id":822,"depth":130,"text":823},{"id":843,"depth":130,"text":844,"children":923},[924],{"id":859,"depth":135,"text":860},{"id":909,"depth":130,"text":910},"2023-09-17T00:00:00.000Z","Learn the best practices for secure minting and protect yourself from scam link threats.","securing-minting-links",{},"/blog/en/2023-09-17-securing-minting-links",{"title":788,"description":927},"blog/en/2023-09-17-securing-minting-links","web3, security, nft","mGf_DkZtjUAclTeP2FvKk3MVIGniyZLJidI7diYYVjQ",{"id":936,"title":937,"author":6,"body":938,"date":1011,"description":1012,"extension":140,"headline":141,"icon":968,"icon_author":141,"icon_url":141,"layout":143,"location":141,"meta":1013,"meta_description":141,"navigation":145,"path":1014,"quote":141,"seo":1015,"slug":968,"stem":1016,"tags":1017,"template":141,"__hash__":1018},"blog/blog/en/2023-06-18-farcaster-bot.md","Writing a Farcaster Bot",{"type":8,"value":939,"toc":1007},[940,955,958,966,970,977,980,983,992,995,999],[11,941,942,943,948,949,954],{},"A long time ago, I wrote a ",[37,944,947],{"href":945,"rel":946},"https://github.com/scifabric/twitterbot",[41],"twitter-bot solution",". This solution was built to be used by me and my team at ",[37,950,953],{"href":951,"rel":952},"https://scifabric.com",[41],"Scifabric",". The main reason is that we had one Twitter account, and we wanted to tweet automatically at given times without using third-party tools (because of their price).",[11,956,957],{},"The solution was \"simple\": using a Google Spreadsheet where each row is a tweet and a script that every N hours tweets one of the messages in that spreadsheet. The best part? You can share the spreadsheet with your team; they could add new tweets to it, and the script would take care of them. Moreover, the bot reshared them over time (using round robin), encouraging the team to add more content so we seem less repetitive than we should.",[11,959,960,961,554],{},"Fast forward to 2023. Elon takes over Twitter and bans almost all Twitter API solutions. My personal bot was discontinued, and I decided to move the bot to ",[37,962,965],{"href":963,"rel":964},"https://farcaster.xyz",[41],"Farcaster",[15,967,969],{"id":968},"farcaster-bot","Farcaster bot",[11,971,972,973],{},"Reusing some of the code and redoing some of it, I simplified it to be the bare minimum. The license, as the previous one, is AGPLv3 so that anyone can use and/or modify it :-) You can clone the repository here: ",[37,974,975],{"href":975,"rel":976},"https://github.com/teleyinex/farcaster-bot",[41],[11,978,979],{},"What do you need? As mentioned before, you only need a Farcaster account and a Google Spreadsheet.",[11,981,982],{},"If you fork the project, you could use GitHub Actions to cast messages without having to require any nice infrastructure :-) Check out the Github Action and adapt it to your needs.",[11,984,985,986,991],{},"The previous bot allowed me also to include images in the tweets. However, the a16z farcaster library is unclear about how to do it. I've created an ",[37,987,990],{"href":988,"rel":989},"https://github.com/a16z/farcaster-py/issues/446",[41],"issue"," in their repo, so hopefully, I can add that missing feature in the next few days/weeks. This will allow artists to showcase their own collections within Farcaster much faster than ever and even plan ahead of time their content.",[11,993,994],{},"NOTE: if you don't have a Farcaster account, you can ask me; I might have some invitations left.",[15,996,998],{"id":997},"stoicism-and-software-quotes-in-farcaster","Stoicism and software quotes in Farcaster",[11,1000,1001,1002,1006],{},"If you want to see it live, just go to ",[37,1003,1004],{"href":1004,"rel":1005},"https://warpcast.com/stoicism",[41]," and give it a follow. If you don't have an account, you can just read the quotes (which will be about science, stoicism, and coding).",{"title":49,"searchDepth":130,"depth":130,"links":1008},[1009,1010],{"id":968,"depth":130,"text":969},{"id":997,"depth":130,"text":998},"2023-06-18T00:00:00.000Z","A simple way to cast messages using Github Actions and Google Spreadsheets",{},"/blog/en/2023-06-18-farcaster-bot",{"title":937,"description":1012},"blog/en/2023-06-18-farcaster-bot","farcaster, bot, python, web3, social","YXPfE2sifHppSa9dQjr4yIRYZxNkCvy5pCjRv-Uoh10",{"id":1020,"title":1021,"author":6,"body":1022,"date":1081,"description":1082,"extension":140,"headline":141,"icon":1083,"icon_author":141,"icon_url":141,"layout":143,"location":141,"meta":1084,"meta_description":141,"navigation":145,"path":1085,"quote":141,"seo":1086,"slug":1083,"stem":1087,"tags":1088,"template":141,"__hash__":1089},"blog/blog/en/2023-06-02-eclipse.md","Chapter one: Eclipse",{"type":8,"value":1023,"toc":1079},[1024,1027,1030,1033,1036,1039,1042,1045,1048,1051,1054,1057,1060,1063,1066,1069],[11,1025,1026],{},"If things were not crazy enough, my boss just came asking me to recruit someone who, as far as I know, is just an illusion. After doing some research on the decentralized web, I could manage to find some clues about where this \"Eclipse\" warrior could be hanging out. The truth is that only a few messages shared within the Farcaster protocol led me to this bar downtown, but who knows if this were just a few guys bluffing about who they know to get some extra engagement. However, that's my only tip, and I should check it out.",[11,1028,1029],{},"The bar is tucked away in the back alleys of the city. It's a popular hangout spot for mercenaries, hackers, and other shady characters who prefer to keep a low profile. When I enter, the air is heavy with the smell of alcohol and electronic fumes, and the neon lights cast eerie shadows on the walls. The furniture is worn and mismatched, cobbled together from salvaged parts, and the bar counter is lined with various gadgets and tools of the trade. The bartender is a grizzled veteran with cybernetic enhancements, scanning the room with a suspicious eye. The atmosphere is tense, and the patrons exchange whispers of deals and secrets. It's the kind of place where one must watch their back and choose their words carefully, as danger lurks in every corner.",[11,1031,1032],{},"As I take a sit, the bartender, a grizzled cyborg with glowing red eyes, leans in and asks me what I want.",[11,1034,1035],{},"Me: \"A cold beer and some intel, if I may\"",[11,1037,1038],{},"Bartender: \"Coming right up.\" The bartender grabs a cold beer from the cooler and slides it across the counter to me, the condensation leaving a wet ring on the surface. I take a sip, savoring the refreshing taste.",[11,1040,1041],{},"Bartender: \"What kind of intel are you looking for?\"",[11,1043,1044],{},"Me: \"I need information about Luna 'Eclipse' Chen and Spectra. I've heard they're skilled hackers and warriors, and I need their help for a complicated mission.\"",[11,1046,1047],{},"Bartender: \"Ah, Luna and Spectra. They're known around here, but they're elusive. Luna is a prodigious hacker and cyber warfare expert known for her unparalleled skills in infiltrating systems and using light and shadows to her advantage. Spectra is another skilled operator, often seen in the underground hubs of the metaverse, dealing in illegal tech and information.\"",[11,1049,1050],{},"Me: \"Any idea where I can find them?\"",[11,1052,1053],{},"Bartender: \"Hmm, they're not easy to pin down. They're like ghosts, always slipping in and out of the shadows. But I've heard they frequent the BlackNet and the Shadow's Den, two notorious cyberpunk hangouts known for attracting the best of its kind\"",[11,1055,1056],{},"Me: \"Thanks for the info. Do you know anything else about them?\"",[11,1058,1059],{},"Bartender: \"Not much, my friend. Luna and Spectra keep their secrets close. But be careful if you cross paths with them. They're not to be taken lightly. Luna's hacking skills are unmatched, and Spectra is known for ruthlessness and cunning.\"",[11,1061,1062],{},"Me: \"Noted. I'll keep that in mind. Thanks for the beer and the intel.\"",[11,1064,1065],{},"Bartender: \"You're welcome. Good luck with your mission, friend. Stay sharp.\"",[11,1067,1068],{},"I nod, finishing my beer and leaving some credits on the counter before heading out, determined to track down Luna and Spectra, knowing that their expertise could be the key to unlocking the secrets of my mission and ensuring its success in the treacherous world of cyber warfare.",[11,1070,1071],{},[37,1072,1075,1078],{"href":1073,"rel":1074},"https://zora.co/collect/0x079a5B14590a2bd1065A89aa7266181Ce207E781/1",[41],[47,1076],{"alt":49,"src":1077},"/img/blog/eclipse-1.jpg","https://zora.coLuna is a petite and agile Chinese woman in her mid-20s, with a mischievous grin and a playful attitude. Her exoskeleton is optimized for cyber infiltration, with specialized interfaces and data jacks that allow her to hack into systems with ease. She carries a pair of energy daggers for close combat.",{"title":49,"searchDepth":130,"depth":130,"links":1080},[],"2023-06-02T00:00:00.000Z","Searching for ","eclipse",{},"/blog/en/2023-06-02-eclipse",{"title":1021,"description":1082},"blog/en/2023-06-02-eclipse","scifi, warriors","MqhWvmM74m8yxVVdloCmqi9tQ0XTI0dHglUsWaIxuJI",{"id":1091,"title":1092,"author":6,"body":1093,"date":1481,"description":1482,"extension":140,"headline":141,"icon":1483,"icon_author":141,"icon_url":141,"layout":143,"location":141,"meta":1484,"meta_description":141,"navigation":145,"path":1485,"quote":141,"seo":1486,"slug":1483,"stem":1487,"tags":1488,"template":141,"__hash__":1489},"blog/blog/en/2023-04-15-paragraph-vs-mirror-web3-publishing.md","Paragraph.xyz vs Mirror.xyz",{"type":8,"value":1094,"toc":1460},[1095,1098,1118,1132,1135,1139,1142,1145,1149,1152,1163,1166,1170,1173,1176,1179,1182,1186,1189,1192,1195,1198,1202,1205,1209,1212,1215,1238,1241,1244,1247,1254,1257,1261,1264,1267,1271,1274,1278,1281,1307,1311,1331,1351,1354,1358,1361,1364,1367,1370,1373,1376,1379,1382,1385,1388,1391,1395,1398,1401,1404,1407,1410,1413,1416,1419,1423,1426,1429,1451,1454,1457],[11,1096,1097],{},"I've been playing a lot with web3 blogging platforms if we can name them like that. Nowadays, things are not as easy as in the good old days: a blog is a blog. Today we have tools with two types of features: a blog post and a newsletter.",[11,1099,1100,1101,1106,1107,1112,1113,554],{},"Within web2, the most popular solution is ",[37,1102,1105],{"href":1103,"rel":1104},"https://substack.com/",[41],"Substack",". This platform has gained a lot of momentum, but within the web3 ecosystem, two platforms are getting a lot of traction and attention lately: ",[37,1108,1111],{"href":1109,"rel":1110},"http://paragraph.xyz",[41],"paragraph.xyz"," and ",[37,1114,1117],{"href":1115,"rel":1116},"http://mirror.xyz",[41],"mirror.xyz",[11,1119,1120,1121,1125,1126,1131],{},"As with my previous analysis of ",[37,1122,1124],{"href":471,"rel":1123},[41],"Farcaster vs Lens protocol",", I started wondering which platform is the best for my own writing experience (and also because ",[37,1127,1130],{"href":1128,"rel":1129},"https://warpcast.com/kugusha",[41],"Kugusa"," asked me about Farcaster).",[11,1133,1134],{},"Thus, here we are, a new and nice comparison between two tools.",[15,1136,1138],{"id":1137},"paragraph","Paragraph",[11,1140,1141],{},"Paragraph is a web3 newsletter. What does it mean? It means that you can publish content and decide if it is published as a blog post and/or a newsletter. This duality is nice, as it allows people to discover your content and subscribe to it if they like it.",[11,1143,1144],{},"Users can subscribe to your content using their emails and/or wallets.",[29,1146,1148],{"id":1147},"creating-an-account","Creating an account",[11,1150,1151],{},"The first thing you must do on this platform is register an account. You can do it in three different ways:",[565,1153,1154,1157,1160],{},[568,1155,1156],{},"Email and password (web2)",[568,1158,1159],{},"Wallet (web3)",[568,1161,1162],{},"Unstoppable Domains (web3)",[11,1164,1165],{},"Thus, you can connect your wallet and start using the platform out of the box.",[29,1167,1169],{"id":1168},"account-settings","Account settings",[11,1171,1172],{},"Paragraph has the basic data that you expect from this type of platforms: name, social media links, avatar, etc., and two cool different features: Social and Subscriptions.",[11,1174,1175],{},"The subscriptions tab is where you can see to whom you have subscribed and manage your subscriptions from there.",[11,1177,1178],{},"On the other hand, the social tab uses the Farcaster protocol to suggest Paragraph users that you already know and follow in the protocol. This is really cool because you can connect and learn more from your social network thanks to decentralization. This is a really cool feature from web3 products.",[11,1180,1181],{},"One data entry that you might want to add is your email. Why? Well, because you will want to get notifications when someone leaves a comment on your posts or if they subscribe to your newsletter. Paragraph allows you to post your content as blog posts and/or a newsletter.",[29,1183,1185],{"id":1184},"publishing-posts","Publishing posts",[11,1187,1188],{},"Paragraph allows you to create posts with a simple editor. You can add titles, bolds, italics, etc., and embed Youtube videos and images. The interface is simple and clean.",[11,1190,1191],{},"Within the editor and after the title, you can add several tags (it is called Categories) to classify your content. This helps Paragraph to filter content and allows other users to find similar content.",[11,1193,1194],{},"The editor saves everything automatically, so you don't have to click save on any place to keep your post saved.",[11,1196,1197],{},"Posts are heavily optimized for SEO. Pages are rendered statically, meaning ultra-blazing-past loads. All content is saved (and exposed in their sitemap) in its top-level domain, meaning that SEO ranking gets shared with your content.",[29,1199,1201],{"id":1200},"communities","Communities",[11,1203,1204],{},"Paragraph allows you to create different communities and send them your content via the newsletter feature. You can create as many as you want. By default, they create for you a Community, and that's the one that people subscribe to. If you create another community, subscribers can choose which one they want to subscribe to.",[29,1206,1208],{"id":1207},"token-gating-your-content","Token gating your content",[11,1210,1211],{},"As we are on web3, we can token-gate our content.",[11,1213,1214],{},"Paragraph allows you to use any ERC721 or ERC20 token from the following networks:",[565,1216,1217,1220,1223,1226,1229,1232,1235],{},[568,1218,1219],{},"Ethereum",[568,1221,1222],{},"Polygon",[568,1224,1225],{},"Binance Smart Chain",[568,1227,1228],{},"Gnosis",[568,1230,1231],{},"Avalanche",[568,1233,1234],{},"Arbitrum",[568,1236,1237],{},"Optimism",[11,1239,1240],{},"Moreover, if you don't have any token to use, you can mint one NFT for 0 gas fees and use it directly from the platform. Paragraph uses Polygon for this feature.",[11,1242,1243],{},"Another option for token-gating your content is using a Newsletter Subscription Gate.",[11,1245,1246],{},"With these two options, Paragraph then shows you a wizard that allows you to customize how you want to configure the token gate for your content.",[11,1248,1249,1250,1253],{},"The wizard is really nice because it allows you to create ",[510,1251,1252],{},"or"," conditions. For example, you can token gate your content by requiring a subscription to your newsletter and an NFT or an NFT pass that you sold some time ago.",[11,1255,1256],{},"As you can imagine, if you are sending the content as newsletters, only the users that have subscribed and have the tokens will receive the email with your content.",[29,1258,1260],{"id":1259},"custom-domains","Custom domains",[11,1262,1263],{},"Paragraph allows you to have your custom domain paying a one-time 50 USD fee.",[11,1265,1266],{},"This feature enables you to have your domain for all your content.",[29,1268,1270],{"id":1269},"teams","Teams",[11,1272,1273],{},"You can add team members so they can write with you. You can do it by adding an email and/or wallet address.",[29,1275,1277],{"id":1276},"collectibles","Collectibles",[11,1279,1280],{},"Within Paragraph you can offer different types of collectibles:",[565,1282,1283,1289,1295],{},[568,1284,1285,1288],{},[510,1286,1287],{},"Highlights"," : people can highlight some text and save it as an NFT. You control everything: which pieces can have this feature, the price, and the supply.",[568,1290,1291,1294],{},[510,1292,1293],{},"Posts"," : you can offer your writing as an NFT that people can save in their wallets. This feature is announced but is not available yet.",[568,1296,1297,1300,1301,1306],{},[510,1298,1299],{},"Embedded NFTs"," : people can mint directly from your post images, audio, and/or videos. To enable this feature, you must first mint your tokens in ",[37,1302,1305],{"href":1303,"rel":1304},"https://tools.highlight.xyz/",[41],"Highlight",". Then, all you have to do is paste the URL of the minting page in your post, and Paragraph will turn it into a claim/mintable page.",[29,1308,1310],{"id":1309},"advance-features","Advance features",[11,1312,1313,1314,1319,1320,1325,1326,554],{},"While Paragraph is pretty complete with all its features, they even allow you to create a ",[37,1315,1318],{"href":1316,"rel":1317},"https://docs.paragraph.xyz/docs/advanced/referral-program",[41],"referral program",", ",[37,1321,1324],{"href":1322,"rel":1323},"https://docs.paragraph.xyz/docs/advanced/streaming-payments",[41],"streaming payments",", and ",[37,1327,1330],{"href":1328,"rel":1329},"https://docs.paragraph.xyz/docs/advanced/recurring-payments",[41],"recurring payments",[11,1332,1333,1334,1339,1340,1345,1346,554],{},"You can also integrate it with ",[37,1335,1338],{"href":1336,"rel":1337},"https://docs.paragraph.xyz/docs/integrations/coinvise",[41],"Coinvise"," for creating memberships and verifying ownership with ",[37,1341,1344],{"href":1342,"rel":1343},"https://docs.paragraph.xyz/docs/integrations/nftd",[41],"NF.TD"," and use ",[37,1347,1350],{"href":1348,"rel":1349},"https://docs.paragraph.xyz/docs/integrations/unlock-protocol",[41],"Unlock Protocol",[11,1352,1353],{},"Finally, they open the door to build on top of Paragraph by providing you with the Polygon contract and their Arweave address. Unfortunately, they don't have a public API address yet, but they open the door to contact them directly to discuss this option.",[15,1355,1357],{"id":1356},"mirror","Mirror",[11,1359,1360],{},"Mirror defines itself as a web3 publishing platform.",[11,1362,1363],{},"To know what Mirror does, you will need to connect your wallet. There's a link in the footer of their home site to their support page, where you can find all the features and tutorials about using the platform. It is interesting how this is really buried in the footer. I would love to know more about this decision.",[29,1365,1148],{"id":1366},"creating-an-account-1",[11,1368,1369],{},"To set up an account in Mirror, you only have to log in with your wallet. Once you are in, you can change your avatar, set up your nickname, bio, and include your Google Analytics Tag ID.",[11,1371,1372],{},"You can also verify your email to get notifications regarding the platform and subscriptions to your posts.",[29,1374,1185],{"id":1375},"publishing-posts-1",[11,1377,1378],{},"Mirror has two modes: edit and preview. Within the edit mode, you can write, while in preview mode, you can see how it will look from the reader's point of view.",[11,1380,1381],{},"Mirror allows you to compose entries using media blocks: images, videos, NFTs, etc. It supports Markdown with some extra features.",[11,1383,1384],{},"One interesting feature of the editor is that you can choose between 3 different layouts for your posts: default, medium and large. The difference is how the images or media blocks are sized according to the browser's viewport.",[11,1386,1387],{},"Another interesting media block is NFTs. This media block lets you share a specific NFT within your post by specifying the contract, blockchain, and token ID. People cannot mint it but view it.",[11,1389,1390],{},"One interesting feature of Mirror is that it generates an RSS feed for your site, so people can subscribe from other sites using it. The solution is pretty simple; you append to your site in Mirror /feed/atom.",[29,1392,1394],{"id":1393},"importing-posts-from-your-blogging-platform","Importing posts from your blogging platform",[11,1396,1397],{},"While Paragraph does not have this feature, Mirror allows you to import blog posts from another site that you have. I tried with my NuxtJS home site, and I got a message that it was not possible, so not sure what works.",[29,1399,1270],{"id":1400},"teams-1",[11,1402,1403],{},"You can add contributors to your posts, by sharing a link or by adding their wallet or ENS name. Contributors can collaborate with you in an entry but cannot add new contributors, which is nice.",[29,1405,1277],{"id":1406},"collectibles-1",[11,1408,1409],{},"Mirror allows you to create an Embed named Collect, allowing people to collect the post.",[11,1411,1412],{},"The Collectable entry includes the banner image, the entry title, description, author, subdomain name, link to the entry, Arweave content link, etc.",[11,1414,1415],{},"Collectible entries are deployed on Optimism (L2). You will pay only for gas, which is usually less than 2 USD. Collected entries will be shown in the Mirror Collections and Leaderboards sections.",[11,1417,1418],{},"If someone buys one of your entries, the money will go directly to the Ethereum address that set up the Mirror publication.",[15,1420,1422],{"id":1421},"my-own-experience","My own experience",[11,1424,1425],{},"First things first. I've not used Mirror, only Paragraph, so I'm a bit biased already. However, after checking the full documentation of both platforms, I think that Paragraph is the best option for anyone setting up a new web3 blog/newsletter platform.",[11,1427,1428],{},"Why? Well, you have more flexibility. Paragraph has the following features that are completely missing in Mirror:",[565,1430,1431,1433,1436,1439,1442,1445,1448],{},[568,1432,1260],{},[568,1434,1435],{},"Collectibles: highlights, posts (this feature is available in Mirror as well), and NFTs",[568,1437,1438],{},"Referral program",[568,1440,1441],{},"Streaming payments",[568,1443,1444],{},"Recurring payments",[568,1446,1447],{},"Token gating entries",[568,1449,1450],{},"Farcaster integration",[11,1452,1453],{},"While some of these features might be too advance for some people, having the option feels amazing. Also, the documentation of Paragraph is AMAZING, seriously. Mirror has all the documentation in the footer, making it difficult to find.",[11,1455,1456],{},"I will play with Mirror, but I will stay with Paragraph for now. I think they are doing an amazing job with this tool. The team is amazing and really responsive in Farcaster. I hope Mirror gets a boost soon and starts adding interesting features to its solution so we have some nice competition.",[11,1458,1459],{},"If you have read until here, thanks! If you like it, subscribe!",{"title":49,"searchDepth":130,"depth":130,"links":1461},[1462,1473,1480],{"id":1137,"depth":130,"text":1138,"children":1463},[1464,1465,1466,1467,1468,1469,1470,1471,1472],{"id":1147,"depth":135,"text":1148},{"id":1168,"depth":135,"text":1169},{"id":1184,"depth":135,"text":1185},{"id":1200,"depth":135,"text":1201},{"id":1207,"depth":135,"text":1208},{"id":1259,"depth":135,"text":1260},{"id":1269,"depth":135,"text":1270},{"id":1276,"depth":135,"text":1277},{"id":1309,"depth":135,"text":1310},{"id":1356,"depth":130,"text":1357,"children":1474},[1475,1476,1477,1478,1479],{"id":1366,"depth":135,"text":1148},{"id":1375,"depth":135,"text":1185},{"id":1393,"depth":135,"text":1394},{"id":1400,"depth":135,"text":1270},{"id":1406,"depth":135,"text":1277},{"id":1421,"depth":130,"text":1422},"2023-04-15T00:00:00.000Z","Which web3 newsletter/blog platform is the best?","paragraph-vs-mirror-web3-publishing",{},"/blog/en/2023-04-15-paragraph-vs-mirror-web3-publishing",{"title":1092,"description":1482},"blog/en/2023-04-15-paragraph-vs-mirror-web3-publishing","web3, blog, newsletter, content creation","t7ad6y9HXZBYj_C19P-1y6l1mPiFaSpeV_QVzxqiwoo",{"id":1491,"title":1492,"author":6,"body":1493,"date":2057,"description":2058,"extension":140,"headline":141,"icon":1920,"icon_author":141,"icon_url":141,"layout":143,"location":141,"meta":2059,"meta_description":141,"navigation":145,"path":2060,"quote":141,"seo":2061,"slug":1920,"stem":2062,"tags":2063,"template":141,"__hash__":2064},"blog/blog/en/2023-03-25-farcaster-vs-lens-protocol.md","Farcaster vs Lens Protocol",{"type":8,"value":1494,"toc":2033},[1495,1498,1523,1526,1529,1532,1535,1542,1545,1548,1554,1558,1561,1570,1573,1576,1580,1583,1602,1616,1619,1628,1634,1638,1649,1658,1673,1684,1700,1703,1707,1715,1718,1722,1725,1728,1731,1738,1745,1752,1759,1766,1773,1776,1779,1783,1786,1800,1809,1812,1821,1824,1828,1831,1834,1841,1856,1859,1862,1865,1869,1872,1875,1878,1881,1883,1886,1889,1892,1896,1899,1902,1906,1909,1912,1915,1918,1922,1925,1928,1932,1935,1938,1941,1945,1948,1951,1955,1958,1967,1971,1974,1976,1979,1982,1991,2018,2021,2024],[11,1496,1497],{},"I've been a user of both decentralized solutions for a few months now, and I wanted to compare them to understand how each solution has been built and what are the main differences and similarities between the two.",[11,1499,1500,1501,1505,1506,1511,1512,1505,1517,1522],{},"Right now, I use daily: ",[37,1502,965],{"href":1503,"rel":1504},"https://www.farcaster.xyz/",[41]," (",[37,1507,1510],{"href":1508,"rel":1509},"https://warpcast.com/~/download",[41],"Warpcast"," client), ",[37,1513,1516],{"href":1514,"rel":1515},"https://docs.lens.xyz/docs",[41],"Lens Protocol",[37,1518,1521],{"href":1519,"rel":1520},"https://orb.ac/",[41],"Orb"," client), and obviously the web2 Twitter solution. So far, I found the most insightful content in Farcaster, while Lens has a unique experience focused on creators. Finally, I have to keep an eye on my Twitter account as most of the projects keep their information there (basically because to join Lens or Farcaster, you need an invite).",[11,1524,1525],{},"Before jumping into the comparison, I wanted to create a \"short\" guide about each protocol. Then at the end, I will compare them and see if there's a winner, which I think is not because each of them has its cool features.",[11,1527,1528],{},"Let's start with Farcaster!",[15,1530,965],{"id":1531},"farcaster",[11,1533,1534],{},"Farcaster is built on top of the L1 blockchain Ethereum. The L1 manages the user identities, while the protocol uses an L2 network to propagate updates between its users (Farcaster Hubs). The protocol then offers the following features:",[11,1536,1537,1538],{},"1. Secure, memorable, and human-readable user identifiers like ",[1539,1540,1541],"code",{},"@alice",[11,1543,1544],{},"2. Real-time settlement and propagation of changes between users.",[11,1546,1547],{},"3. Decentralized access to all data on the network at reasonable costs.",[11,1549,1550,1553],{},[510,1551,1552],{},"UPDATE"," : as pointed out by some members of the CrisisDAO the delta-graph nodes are not an L2, as it does not use a blockchain to settle on its state. Thus, the protocol uses an off-chain peer-to-peer network to sync the data.",[29,1555,1557],{"id":1556},"how-does-it-work","How does it work?",[11,1559,1560],{},"To join the Farcaster protocol, you must register a public-private key pair and an ID with an Ethereum contract. This public-private key-pair (a new Ethereum address) will be used for signing messages plus the ID (a canonical reference for a user on the Ethereum network), so they are made tamper-proof and self-authenticating. Moreover, recipients can check the key pair associated with the ID in the contract and verify the message's authenticity.",[11,1562,1563,1564,1569],{},"Signed messages are uploaded to the Farcaster Hub, which works like a blockchain network. The Hubs use a peer-to-peer protocol to share messages between them and store them, using delta ",[37,1565,1568],{"href":1566,"rel":1567},"https://github.com/farcasterxyz/protocol#3-delta-graph",[41],"graphs"," to reach a consensus about their state. The most interesting aspect of using delta graphs is that Hubs can reach a consensus without coordination.",[11,1571,1572],{},"With Hubs storing and managing the network status, the client apps will connect to them so companies and people can build different clients for the protocol, customizing the experience for their users. This is fantastic because each app could be completely different based on the protocol, allowing the creation of an ecosystem of apps within the Farcaster protocol.",[11,1574,1575],{},"Farcaster IDs and the Ethereum address (the public-private key pair) are managed within the Farcaster Ethereum contracts, so we can be sure that the ownership of the identities is decentralized and secure.",[29,1577,1579],{"id":1578},"farcaster-ids","Farcaster IDs",[11,1581,1582],{},"From the official documentation of Farcaster:",[11,1584,1585,1586,1589,1592,1593,1596,1592,1599],{},"\"",[247,1587,1588],{},"A Farcaster ID or",[1539,1590,1591],{},"fid"," ",[247,1594,1595],{},"is the canonical identifier for a user or organization. Fids are numerical values like !8098, distinguished from other numbers by prefixing them with an exclamation mark. Users register fids to an Ethereum address, also known as the",[1539,1597,1598],{},"custody address",[247,1600,1601],{},". Users can transfer fids to a new custody address, though each address can own exactly one fid at a time. \"",[11,1603,1604,1605,1607,1608,1613,1614,554],{},"Thus, the ",[1539,1606,1591],{}," is generated by interacting with the ",[37,1609,1612],{"href":1610,"rel":1611},"https://github.com/farcasterxyz/contracts/",[41],"Farcaster ID Registry",". As this is a smart contract on Ethereum, anyone can read the contract to find out which Ethereum address owns a given ",[1539,1615,1591],{},[11,1617,1618],{},"At this point, we have all the necessary parts to send messages to the protocol:",[565,1620,1621,1624],{},[568,1622,1623],{},"The ECDSA key-pair from the custody address, and",[568,1625,863,1626],{},[1539,1627,1591],{},[11,1629,1630,1631,1633],{},"With those two pieces, we can sign a message and send it to the hub, and the recipient can also verify everything. Moreover, the protocol does not allow anyone to reclaim or revoke a ",[1539,1632,1591],{}," once an address claims it, we have \"sufficient decentralization\" by allowing tamper-proof communications over the Hubs.",[29,1635,1637],{"id":1636},"farcaster-names","Farcaster Names",[11,1639,1640,1641,1644,1645,1648],{},"While we have the required items to send messages, we need a human-readable way of referencing the ",[1539,1642,1643],{},"fids",". For this reason, Farcaster has an optional ",[1539,1646,1647],{},"fname",", i.e., @alice.",[11,1650,1651,1654,1655,1657],{},[1539,1652,1653],{},"fnames"," are alpha-numeric strings like @john or @alice, distinguished from other text by prefixing it with an at-symbol (",[1539,1656,1643],{}," have an exclamation mark).",[11,1659,1660,1661,1663,1664,1667,1668,554],{},"One interesting feature of ",[1539,1662,1653],{}," is that all of them must adhere to the following regular expression: ",[1539,1665,1666],{},"/^[a-z0-9][a-z0-9-]{0,15}$/",". Why? Because it avoids ",[37,1669,1672],{"href":1670,"rel":1671},"https://en.wikipedia.org/wiki/IDN_homograph_attack",[41],"homoglyph attacks",[11,1674,1675,1677,1678,1683],{},[1539,1676,1653],{}," are ",[37,1679,1682],{"href":1680,"rel":1681},"https://github.com/farcasterxyz/protocol#33-recovery",[41],"recoverable"," as well, which is really nice.",[11,1685,1686,1688,1689,1693,1694,1696,1697,1699],{},[1539,1687,1653],{}," have to be renewed once a year, paying a fee to the ",[37,1690,1692],{"href":1610,"rel":1691},[41],"Farcaster Name Registry",", which issues each one as an NFT. ",[1539,1695,1653],{}," can be renewed 90 days before it expires. If it expires, ",[1539,1698,1653],{}," enter a dutch auction where the price is set to a yearly fee plus a premium, which decays until it reaches zero.",[11,1701,1702],{},"The protocol's core team sets the price for these NFTs. This fee controls who can join, getting bots out of the protocol while keeping a reasonable price to get the community valuable.",[29,1704,1706],{"id":1705},"account-recovery","Account recovery",[11,1708,1709,1710,1112,1712,1714],{},"As we already know, we can forget the passphrase to our wallet, so having a nice way to recover your digital identity is critical for a protocol. For this reason, the Farcaster protocol allows users to set a recovery address to protect their ",[1539,1711,1653],{},[1539,1713,1643],{},". It is important to note that this recovery only works for loss of access, not address compromise.",[11,1716,1717],{},"The recovery address can request a transfer to a new custody address after a three-day escrow.",[29,1719,1721],{"id":1720},"how-is-everything-stored","How is everything stored?",[11,1723,1724],{},"As mentioned before, the Hubs use delta graphs to save the messages and synchronize the social network state between the nodes.",[11,1726,1727],{},"In this graph, each vertex is an entity like a user or message, and an edge is a relationship between the entities. When @alice creates a message, and @bob likes it, the protocol will create a series of deltas that will be easy to synchronize between the nodes.",[11,1729,1730],{},"Farcaster distinguishes between six types of deltas:",[11,1732,1733,1734,1737],{},"1. ",[510,1735,1736],{},"casts"," , which are messages from a user",[11,1739,1740,1741,1744],{},"2. ",[510,1742,1743],{},"reactions"," , which are reactions to a user's messages from another user (e.g., a like)",[11,1746,1747,1748,1751],{},"3. ",[510,1749,1750],{},"amps"," , which are amplifications or endorsements of a user",[11,1753,1754,1755,1758],{},"4. ",[510,1756,1757],{},"verifications"," , which are proofs of ownership (e.g., an Ethereum address signature)",[11,1760,1761,1762,1765],{},"5. ",[510,1763,1764],{},"signers"," , which are key pairs authorized by a user to sign their deltas",[11,1767,1768,1769,1772],{},"6. ",[510,1770,1771],{},"user data"," , which are metadata about the user (e.g., their profile picture)",[15,1774,1516],{"id":1775},"lens-protocol",[11,1777,1778],{},"While Farcaster lives in Ethereum and has an off-chain solution (Farcaster Hubs) for storing the information, Lens uses the L2 Polygon blockchain.",[29,1780,1782],{"id":1781},"profiles","Profiles",[11,1784,1785],{},"Like Farcaster, you will need a \"Profile\" to participate in the protocol. A Profile is a sequential ID that an NFT will represent. The NFT will belong to a wallet address, and the owner is the person who will control the profile. Profile owners can:",[565,1787,1788,1791,1794,1797],{},[568,1789,1790],{},"Publish to the profile.",[568,1792,1793],{},"Set the profile's \"follow module\": the logic allowing others to follow this profile.",[568,1795,1796],{},"Set the profile's avatar (image URI).",[568,1798,1799],{},"Set the profile's \"dispatcher\".",[11,1801,1802,1803,1808],{},"You can mint your profile in ",[37,1804,1807],{"href":1805,"rel":1806},"https://docs.lens.xyz/docs/lenshub",[41],"LensHub.sol"," upgradable contract if your wallet address is included in the list (as with Farcaster, right now, you can only join by invitation or by buying a profile on a marketplace like OpenSea).",[11,1810,1811],{},"Once you have a Lens Profile NFT, you can post publications to it. Moreover, the NFT will have the history of all the publications, comments, etc., that the owner generates.",[11,1813,1814,1815,1820],{},"One interesting feature of LEns is that Profiles, and almost every protocol item, can have different modules that expand their functionality. For example, Profile NFTs contain a ",[37,1816,1819],{"href":1817,"rel":1818},"https://docs.lens.xyz/docs/follow",[41],"FollowModule",". This module has rules allowing other Profiles to follow it back and save it on-chain.",[11,1822,1823],{},"Right now, as with Farcaster, Profiles can only be minted by addresses that its government has approved. As before, this is done to avoid bots and fake accounts.",[29,1825,1827],{"id":1826},"publication","Publication",[11,1829,1830],{},"Once you have a Profile NFT, you can start posting Publications. A Publication can be a message, a comment, etc.",[11,1832,1833],{},"Lens has 3 types of Publications: posts, comments, and mirrors.",[11,1835,1836,1837,1840],{},"Publications are posted directly to a user's Profile. This means that all the created content by the user will remain in the person's wallet. It is important to note that Publications are ",[510,1838,1839],{},"NOT"," NFTs.",[11,1842,1843,1844,1849,1850,1855],{},"Each Publication has a ContentURI that has a link to the content that the publication contains. This link could point to a text, an image, a video... stored on a decentralized solution like ",[37,1845,1848],{"href":1846,"rel":1847},"https://arweave.net/",[41],"Arweave"," or ",[37,1851,1854],{"href":1852,"rel":1853},"https://ipfs.io/",[41],"IPFS",", or a web2 storage facility like AWS S3.",[11,1857,1858],{},"When you post a Publication, two modules are attached to them: the Collect Module and the Reference Module.",[11,1860,1861],{},"The Collect Module has all the logic that allows other users to mint the publication as an NFT. The minted NFT will reference the original Publication's URI.",[11,1863,1864],{},"The Reference Module has all the logic related to comments on the publication's Publication and the mirrors (retweets).",[29,1866,1868],{"id":1867},"comment","Comment",[11,1870,1871],{},"Comments give users the power to add feedback. Under the hood, they are like Publications with some extra checks and features.",[11,1873,1874],{},"As Comments are like Publications, comments are stored as well in the user's Profile.",[11,1876,1877],{},"One interesting feature of comments is that they must follow the rules of the original publication Reference module conditions. If, for example, there is a rule that sets that only followers of the Profile NFT can comment, then if a Profile NFT tries to comment on the publication and it is not following the original poster, the transaction will fail, and the comment will not be published.",[11,1879,1880],{},"Comments can also be collected, as they are based on Publications. Thus, people can mint an NFT from a good comment they like.",[29,1882,1357],{"id":1356},[11,1884,1885],{},"Mirrors are the way we retweet Tweets on Twitter. From the Protocol point of view, they work the same as Publications with some special treats.",[11,1887,1888],{},"As with comments, mirrors must adhere to the reference module's original poster conditions. If a publication limit mirrors only accounts that follow the original poster, then anyone not meeting the rule cannot mirror the post.",[11,1890,1891],{},"Unlike Publications and Comments, mirrors cannot be collected.",[29,1893,1895],{"id":1894},"collect","Collect",[11,1897,1898],{},"Collect is a native feature of Lens that allows creators to monetize their content. As creators can publish almost anything: images, videos, podcasts, art, etc., this module was created to set a price and allow other profiles to collect (mint) them.",[11,1900,1901],{},"The process is simple: when you create a Publication, you can enable the Collect Module. This module opens the minting functionality for that Publication based on the ContentURI. The module can have any arbitrary logic to set the rules the creator wants to create, for example: free for a given amount of time or a given amount of collects.",[29,1903,1905],{"id":1904},"follow","Follow",[11,1907,1908],{},"Finally, following other users in the Lens Protocol differs slightly from Farcaster and other web2 social networks. As we've seen, everything becomes an NFT or is saved within the Profile NFT. Thus, users who follow a profile on the Lens Protocol receive a Follow NFT.",[11,1910,1911],{},"As with all the previous items, Profile NFTs can have their own Follow Module, setting their own rules. This means you could enforce that to follow you back you have to pay 5 MATIC. Ultimately, you are \"minting\" the token showing that you are following that profile, and the profile owner can set the rules.",[11,1913,1914],{},"One really cool feature of the Follow NFTs is that this module has built-in governance capabilities like vote delegation. This feature can enable the creation of Social DAOs within the Lens Protocol.",[11,1916,1917],{},"It could be possible to create rules that allow giving followers more voting power if they were followers since the beginning or similar things.",[15,1919,1921],{"id":1920},"farcaster-vs-lens-protocol","Farcaster vs. Lens Protocol",[11,1923,1924],{},"If you have read until here, you should now have more or less a clear idea of the design principles of these two social decentralized networks. Each of them has its advantages and problems.",[11,1926,1927],{},"Let's get into the pros and cons.",[29,1929,1931],{"id":1930},"ids-or-profiles","IDs or Profiles",[11,1933,1934],{},"On Farcaster, you will have to renew your handle once a year. On Lens, you only will do this once. Which one is better? Well, it depends.",[11,1936,1937],{},"Farcaster has always wanted to have high-quality conversations, and one of the reasons for asking people to pay for their profiles is to support the Hubs and ensure that you will put some skin in the game. While I can see the benefits, in my head, I hesitate if this will ensure that Farcaster will be massively adopted. But do they want to be massively adopted? More users will mean more noise, and I think they are trying to reduce that ratio by providing high-quality profiles in their network. So far, I can assure you that the conversations on Farcaster are amazing and deep.",[11,1939,1940],{},"On the other hand, we have Lens. Anyone can mint their handle and will not have to renew it. While this is neat, it allows people to create profiles for big brands (like it is happening already with ENS or domains) and charge people to control that social media profile. Is this good? Speculation will be a big problem, as the profiles do not expire (like in Farcaster do), so only time will tell.",[29,1942,1944],{"id":1943},"social-graph","Social graph",[11,1946,1947],{},"One of Lens's most interesting features is that everything is saved on-chain in your profile. The protocol creates contracts for your publications, so any client that uses the protocol will show you exactly the same content. Your followers and content go with you.",[11,1949,1950],{},"On the other hand, Farcaster allows you to have more flexibility. While Lens seems nice, I've been playing with \"Instagram clones\" that show only the Publications that are images. This sounds cool, but I cannot separate my content, while on Farcaster, I could. Each app could rely on the delta graph and build its list of followers. The only problem with this is that you will have to \"export somehow\" your followers if you want to change your clients. Is it good? Bad? Time will tell.",[29,1952,1954],{"id":1953},"everything-on-chain-vs-something-on-chain","Everything on-chain vs. Something on-chain",[11,1956,1957],{},"Lens uses Polygon for all the transactions. Everything is saved in Polygon, while Farcaster uses its off-chain solution.",[11,1959,1960,1961,1966],{},"The approach from Lens is that everything will be saved in your wallet as an NFT with different contracts created for you (the modules). This is smart because your social graph and posts could grow in number forever. However, Hubs on Farcaster have a ",[37,1962,1965],{"href":1963,"rel":1964},"https://github.com/farcasterxyz/protocol#34-bounding-graph-size",[41],"limitation on the size"," of the delta graph (64TB). This graph size has been limited to removing old posts and making things interesting, to say the least. I like this approach because the graph forgets, aligning with GDPR principles about the right to be forgotten. The lens approach is \"simple\"; as you own everything, you should be able to destroy/burn everything. But as you know, the blockchain will have the history, so everyone can point out what you said/did at a given time. It could be interesting to see where the GDPR stands here.",[29,1968,1970],{"id":1969},"extending-the-protocol","Extending the protocol",[11,1972,1973],{},"On Lens, you can extend the modules, so the options are endless. On Farcaster, you will have to propose changes to the protocol, and all the hubs should be upgraded to support those changes. Which one is better? I like a lot the Lens approach, as everything is a contract that can be deployed with its own rules. However, the Farcaster approach seems more like any other open-source project, which is nice and well done. As with other solutions, time will tell.",[29,1975,1422],{"id":1421},[11,1977,1978],{},"Well, this is completely subjective because I use both, and I like both. However, I can see big differences so far.",[11,1980,1981],{},"Farcaster, for me, is the place to find deep and interesting conversations. The engagement with the community is amazing, and I'm always learning from someone. It is huge compared to Twitter, where all I see in general is promotion and discussions with tons of hate involved. Here the discussions are civilized, people behave, and even when disagreeing, you feel at home learning from everyone.",[11,1983,1984,1985,1990],{},"On the other hand, Lens is the place for artists and creators. I've many more followers on Lens than Farcaster but less engagement. While my publications get several likes and mirrors, I indeed get almost zero interaction from comments on my posts. It looks like all the likes and followers are fake, as I don't have interaction via comments with other people. It is a weird feeling even though the technology is amazing. I love collecting; I love how you can set up rules for following you, collecting your posts, etc. One cool feature from Lens is ",[37,1986,1989],{"href":1987,"rel":1988},"https://wav3s.app/",[41],"Wav3s"," which allows you to create paid conditions for people who mirror your posts. Instead of paying the platform, you pay your followers and Lens users for helping you bring your content to others. This is neat, but it opens the door to discussing if people with less money will always have difficulty growing a community around. Obviously, the answer to this question is: if you have good content, people will come, but that's not always the case.",[11,1992,1993,1994,1319,1999,1325,2002,2007,2008,1112,2013,2017],{},"Both protocols now have several client apps. Each one has its own pros/cons, but it is becoming fun to test them all and see the experience. ",[37,1995,1998],{"href":1996,"rel":1997},"https://lenster.xyz/u/buttrfly",[41],"Buttrfly",[37,2000,1521],{"href":1519,"rel":2001},[41],[37,2003,2006],{"href":2004,"rel":2005},"https://phaver.com/",[41],"Phaver"," are the 3 mobile apps that you can use on Lens, while ",[37,2009,2012],{"href":2010,"rel":2011},"https://jam.so/",[41],"Jam",[37,2014,1510],{"href":2015,"rel":2016},"https://warpcast.com/",[41]," are the ones on Farcaster.",[11,2019,2020],{},"Warpcast is, for now, the only full-featured client on Farcaster, but Jam will join soon enough (looking forward to testing it). As explained before, what will be interesting to test here is that my social graph on Warpcast will not exist on Jam, so I will have to create a new one from scratch.",[11,2022,2023],{},"With Lens, I've tried Phaver and Orb. Phaver is weird; I don't get it. The UX is strange because they have its social network, and you can switch between theirs and Lens. This also forces you to change some settings to use it, making it a bit awkward. Orb, on the other hand, is a full-featured solution. Minor details are missing, like setting the collect options from the client, but this will be solved in the coming releases for sure.",[11,2025,2026,2027,2032],{},"In summary: if you can try both. I think they are going to have their communities, and it will be fun to be on both at the same time. As everything is decentralized, several apps will make it possible to have only one app that allows you to have everything in one place, like ",[37,2028,2031],{"href":2029,"rel":2030},"https://app.yup.io/",[41],"Yup"," (looking to test it as well). The truth is that social networks were not been this exciting in years.",{"title":49,"searchDepth":130,"depth":130,"links":2034},[2035,2042,2050],{"id":1531,"depth":130,"text":965,"children":2036},[2037,2038,2039,2040,2041],{"id":1556,"depth":135,"text":1557},{"id":1578,"depth":135,"text":1579},{"id":1636,"depth":135,"text":1637},{"id":1705,"depth":135,"text":1706},{"id":1720,"depth":135,"text":1721},{"id":1775,"depth":130,"text":1516,"children":2043},[2044,2045,2046,2047,2048,2049],{"id":1781,"depth":135,"text":1782},{"id":1826,"depth":135,"text":1827},{"id":1867,"depth":135,"text":1868},{"id":1356,"depth":135,"text":1357},{"id":1894,"depth":135,"text":1895},{"id":1904,"depth":135,"text":1905},{"id":1920,"depth":130,"text":1921,"children":2051},[2052,2053,2054,2055,2056],{"id":1930,"depth":135,"text":1931},{"id":1943,"depth":135,"text":1944},{"id":1953,"depth":135,"text":1954},{"id":1969,"depth":135,"text":1970},{"id":1421,"depth":135,"text":1422},"2023-03-25T00:00:00.000Z","Decentralized social protocols face to face",{},"/blog/en/2023-03-25-farcaster-vs-lens-protocol",{"title":1492,"description":2058},"blog/en/2023-03-25-farcaster-vs-lens-protocol","web3, social, protocol","nLL1BGrBOuujhyXpQN3k5pM0x-adAn8HmTTEEaiONKk",{"id":2066,"title":2067,"author":6,"body":2068,"date":2175,"description":2176,"extension":140,"headline":141,"icon":2177,"icon_author":141,"icon_url":141,"layout":143,"location":141,"meta":2178,"meta_description":141,"navigation":145,"path":2179,"quote":141,"seo":2180,"slug":2177,"stem":2181,"tags":2182,"template":141,"__hash__":2183},"blog/blog/en/2023-03-05-breathing-letters.md","Breathing Letters",{"type":8,"value":2069,"toc":2173},[2070,2073,2076,2091,2094,2097,2100,2103,2106,2113,2116,2119,2122,2125,2134,2137,2144,2147,2150,2158,2161,2170],[11,2071,2072],{},"I've been a web3 developer for some time, especially with the OBEY crew. I've created the backend, the front end, and the smart contract, but I have never launched my collection.",[11,2074,2075],{},"For a long time, this has been something in the back of my mind, but I never had the time or the idea (even though I've been playing a lot with crazy ideas).",[11,2077,2078,2079,2084,2085,2090],{},"Through this journey, I created in Christmas 2022 two web apps that allowed me to do some simple tasks: (a) an app to get ",[37,2080,2083],{"href":2081,"rel":2082},"https://yearinreview.teleyinex.xyz/",[41],"your year in review"," and (b) an app to ",[37,2086,2089],{"href":2087,"rel":2088},"https://nftshare.teleyinex.xyz/",[41],"share your NFTs"," easily (without having to connect your wallet and more importantly sharing JPGs, GIFs, and SVGs, from one place).",[11,2092,2093],{},"When I created both, I found the Nabla web font. This font is special because it allows you to create an isometric font in COLRv1 format. And what does it mean? Well, it means you can use CSS with the font to create awesome effects that cannot be done with other fonts, like changing the depth and highlighting.",[11,2095,2096],{},"While this is really cool, not all browsers support it, but as most browsers are built on top of WebKit, most of them support COLRv1 and, therefore, can render these features within the browser.",[11,2098,2099],{},"I used this font for both previous web apps, and while playing with it, I had the idea of creating a dynamic NFT that could use each letter in lowercase from the alphabet using this font. Why this font? Because I could change the depth of it dynamically, so I could make it breathe. While most letters can change size and weight, only a few can change their depth, and Nabla was there for me.",[11,2101,2102],{},"My first experiment was just a simple letter with some CSS that would change its depth of it. That worked out, so my next obvious step was to create a script that would allow me to use that HTML as a template to fill in the gaps for each letter and render them easily running one command.",[11,2104,2105],{},"My preferred programming language is Python, so I hacked a very simple script that read the HTML template and made some substitutions for me: the alphabet letters. I wanted to keep everything as simple as possible, so instead of using a templating system or library, I created my own :-)",[11,2107,2108,2109,2112],{},"Jinja2 heavily inspires the templating solution, so I used ",[2110,2111],"binding",{"value":49}," to replace the code where I wanted. The next step was randomly choosing beautiful color palettes, so my script could use them and feed them into the template. For this case, I used the seaborn python library, as it has some beautifully made color palettes that I could easily use with the letters.",[11,2114,2115],{},"The color palettes can be transformed into hexadecimal colors, and that was perfect because Nabla font can have up to 9 colors to create gradients within the font. This was awesome because I could randomly choose a color palette, then reduce it to 9 colors and feed them to the template's CSS, so the letters could be rendered using those colors. Moreover, I could inject them as variables and use them later within the CSS to have a consistent color palette for the NFT.",[11,2117,2118],{},"With all this solved, it was time to make the NFT dynamic. As the letters could breathe, I wanted to give them some personality. I realized that nowadays, people get stressed out in crypto, and my breathing letters could help them relax. But how? Following the well-known breathing exercise: 4:4:4:4. You inhale for 4 seconds, hold for 4 seconds, exhale for 4 seconds, and hold for another 4 seconds. Repeat several times, and your body and mind will be more relaxed.",[11,2120,2121],{},"At this point, I had a breathing letter you could use as a relaxing buddy, but I felt something was missing: the background was empty. Nothing was there. Hence, I thought that the thing that people stress out in web3 is the price of Eth, so I wanted to reflect in the background on how that worked out.",[11,2123,2124],{},"The template had a small Js file that checks the ETH price from today and compares it with yesterday. If the price is mostly the same, it will not do anything, but if the price has gone up, the background will move up, while if it goes down, the background will go down.",[11,2126,2127,2128,2133],{},"The background is created randomly again using some python functions: it creates circles and squares of different sizes. Additionally, I wanted to place them in different places. A simple solution was to use the default python random methods, but it was insufficient, so I decided to use a ",[37,2129,2132],{"href":2130,"rel":2131},"https://en.wikipedia.org/wiki/Perlin_noise#:~:text=Perlin%20noise%20is%20a%20procedural,details%20are%20the%20same%20size.",[41],"Perlin noise"," JS function to locate them, bringing a more natural feeling to the locations and how they will be moving.",[11,2135,2136],{},"The result? Well, this beautiful animated letters:",[11,2138,2139],{},[37,2140,2143],{"href":2141,"rel":2142},"https://twitter.com/breathingABC/status/1631709616173088771",[41],"Tweet by @breathingABC",[11,2145,2146],{},"With the script ready to create any letter with any color palette, I was ready to launch it. But I found a problem: none of the available no-code tools allowed me to deploy them easily. I ended up using Manifold because it is easy to use, but I have to mint each letter one by one (with the associated cost, as batch minting is not available for dynamic NFTs). I cannot have a claim page either because dynamic NFTs are not supported, so the only solution left is to deploy to the main net and then list each token on OpenSea or Blur so people can buy it.",[11,2148,2149],{},"Is it perfect? No, but it will work out :-) As you have read in the previous tweet, the price will be for one letter 0.0069ETH (~10 USD) in this first batch of 3 letters: a, b, and c.",[11,2151,2152,2153,2157],{},"You can check the available letters here: ",[37,2154,2155],{"href":2155,"rel":2156},"https://opensea.io/collection/breathing-letters",[41],", and if you like them, get one! I'll be listing the available ones tomorrow, Monday 6th of March, and hopefully, someone will get one :-)",[11,2159,2160],{},"There will be all the English alphabet plus a ñ as I'm from Spain. Each letter will have its distribution based on its frequency in English. I just released the first three letters as I think they are the most well-known ones.",[11,2162,2163,2164,2169],{},"All the NFTs have been saved in Arweave (using ",[37,2165,2168],{"href":2166,"rel":2167},"https://ardrive.io/",[41],"ArDrive","). Why Arweave and not IPFs? Well, I wanted to learn Arweave, and all I can say is that I might never use IPFS again. The simplicity and fast serving stuff is a winning point over IFPS (also not needing any gateway).",[11,2171,2172],{},"Thanks for reading until here! Let me know if you like it.",{"title":49,"searchDepth":130,"depth":130,"links":2174},[],"2023-03-05T00:00:00.000Z","A dynamic NFT collection for relaxing your mind","breathing-letters",{},"/blog/en/2023-03-05-breathing-letters",{"title":2067,"description":2176},"blog/en/2023-03-05-breathing-letters","nft, art, dynamic","cS6lUeDbdE45YOy4Ef4RoWF-1v2varA2vtnzqgltkgI",{"id":2185,"title":2186,"author":6,"body":2187,"date":2388,"description":2389,"extension":140,"headline":141,"icon":2390,"icon_author":141,"icon_url":141,"layout":143,"location":141,"meta":2391,"meta_description":141,"navigation":145,"path":2392,"quote":141,"seo":2393,"slug":2390,"stem":2394,"tags":2395,"template":141,"__hash__":2396},"blog/blog/en/2023-02-12-handling-your-nfts-collection-safely.md","Handling your NFTs collection safely",{"type":8,"value":2188,"toc":2379},[2189,2198,2202,2205,2208,2211,2214,2217,2220,2224,2227,2233,2236,2239,2243,2246,2249,2252,2255,2259,2262,2265,2268,2271,2274,2283,2286,2290,2293,2299,2302,2305,2312,2316,2325,2328,2336,2343,2354,2369,2376],[11,2190,2191,2192,2197],{},"In my previous ",[37,2193,2196],{"href":2194,"rel":2195},"https://paragraph.xyz/@teleyinex.eth/my-first-year-in-web3",[41],"post",", I explained how my first year in web3 went. Now, one year later, I've collected around 150 NFTs, and while none are over 1 ETH, I would be really sad if I lost one.",[15,2199,2201],{"id":2200},"first-steps-toward-security","First steps toward security",[11,2203,2204],{},"While I was already buying ETH and minting some NFTs, I did everything with my Metamask wallet. Yes, that's the easy way, and most people will do it like that because of all the things you need to learn before even considering what's a hard or cold wallet.",[11,2206,2207],{},"The typical situation in these cases is that you start buying with your Metanmask wallet, and suddenly you have not only ETH and other ERC20 tokens but some NFTs that you like, and you don't want to lose. But how can you protect them? And most importantly, why is it not that secure to keep using the Metamask (or any other hot wallet)?",[11,2209,2210],{},"Well, the answer is more or less straightforward: the seed phrase used to create your wallet is stored in your hard drive (or phone SD memory) and protected by the password that you have used to create the wallet.",[11,2212,2213],{},"The first problem is the password. Are you using a difficult password with numbers, letters, uppercase and lowercase chars, plus some symbols and longer than eight chars? The answer to this question is usually: 1234password or something even worst. Thus, the first thing to review is which password you have used.",[11,2215,2216],{},"-_But teleyinex, I don 't share my computer with anyone else, or if I do they are people I trust. Why should I care? _",[11,2218,2219],{},"Well, the answer is simple: malware, virus, and phishing attacks are your enemies. And if they get you, they will hit you with all they have.",[29,2221,2223],{"id":2222},"virus-and-malware","Virus and malware",[11,2225,2226],{},"Nowadays, people creating malware and viruses know that people use crypto wallets and that by accessing your wallet, they can automatically transfer all your funds to theirs because if they get your seed phrase, there's no one, I repeat, no one, that can stop them from robbing you. Why? Because they have the access keys to your wallet, they can enter and exit whenever they want and transfer anything.",[11,2228,2229,2232],{},[510,2230,2231],{},"Yes, re-read that part",". It is hard to digest because we are used to web2 services where in case of getting hacked, all you have to do is talk to the company, and after a few checks, you will be able to get your account back. But this is no more true in web3 because you are responsible for your safety. That's the price of being your own master and owning your data. Thus, this is important, and it needs a shift to think about how you can protect yourself.",[11,2234,2235],{},"Now that we know that hot wallets store your wallet seed phrase \"encrypted\" in your hard drive, imagine that your computer gets compromised with a virus or malware. If this is the case, you will have to trust that the virus has not cracked your password (remember that you used something like secure1234). If they crack your password, you are done. Consider your wallet compromised and asap move all your assets to a new wallet.",[11,2237,2238],{},"The virus might not crack your password immediately, but it could be looking for your files and uploading them to a machine so it can try by brute force until they break it. Hence, in none of these cases will you be safe, and the best you can do is create a new wallet and transfer your assets. But wait, do I create a new wallet in the same way again? Wouldn't that mean that I will be repeating the same mistakes? The answer is YES. And this is why you need a hard or cold wallet.",[15,2240,2242],{"id":2241},"hard-wallets","Hard wallets",[11,2244,2245],{},"A hard wallet is just a piece of hardware that allows you to create a wallet but with a difference: the seed phrase is never stored in your devices: laptop or phone. It uses its own hardware to encrypt everything and never exposes that to the outside.",[11,2247,2248],{},"Hard wallets allow you to connect to them via USB or Bluetooth. The exciting part is that they have a protocol that allows you to use them with soft wallets like Metamask. The benefit? Your seed phrase is entirely secure as it never leaves the hardware. Think of it as a key to access your house.",[11,2250,2251],{},"Attaching your wallet to a physical object makes things more interesting. Unless you lose your key, you are safe. Plus, all these hard wallets have a pin of 8 numbers that, after three failed tries, will delete everything inside. Yes, you should never forget your pin, or you will be kicked out of your wallet by the device (you can still recover it because you have safely stored the 24 words for your wallet in a safe place, right? Go and check before moving forward!).",[11,2253,2254],{},"I hope that right now, you are starting to see the benefits of using a hard wallet. You can operate like before, but the seed phrase is secured inside. And now, if your computer or phone gets compromised, you are safe because the attacker does not have access to your physical device, and you know that the seed phrase was never stored on your devices, so you are safe.",[15,2256,2258],{"id":2257},"securing-your-nfts","Securing your NFTs",[11,2260,2261],{},"If you are like me, you will end up with two wallets, your hot wallet (installed in your phone and laptop) and a hard wallet. The hard wallet is where you will store all your valuable assets.",[11,2263,2264],{},"I use my soft wallet to mint, get airdrops, connect to other places, etc. If they are making an attack, I know that my soft wallet will be compromised but not my hard wallet because I only use it for storing tokens and NFTs. I will never connect it to the web, so it is 100% safe.",[11,2266,2267],{},"My current setup is simple. My main wallet is the one associated with teleyinex.eth, while my hard wallet is in vault.teleyinex.eth. While this is not necessary, you can link your ENS domain and subdomain to different wallets so you are \"safe\" sending tokens between them (always double-check everything pretty, please).",[11,2269,2270],{},"The ENS domain allows you to create as many subdomains as you want, so if you want to have a mnemonic, I recommend doing that.",[11,2272,2273],{},"If you plan to do the same, you should know that you might need to connect your hard wallet to ENS to set up the reverse domain lookup to your address. This will mean connecting it for this purpose and enabling blind signing in your wallet.",[11,2275,2276,2277,2282],{},"While this is not optimal, -ENS you should allow clear signing- you can do this the first time and then disable everything again. If you want to be 100% sure that you have not screwed up, you can go to ",[37,2278,2281],{"href":2279,"rel":2280},"http://revoke.cash",[41],"revoke.cash"," and check that your hard wallet has not granted permission to do anything. This should be the case because all you have done is sign a transaction on ENS.",[11,2284,2285],{},"Once you have this setup, you can finally start moving NFTs to your wallet.",[15,2287,2289],{"id":2288},"transferring-nfts-to-your-cold-wallet","Transferring NFTs to your cold wallet",[11,2291,2292],{},"This is pretty simple. Just connect with your soft wallet to Open Sea. Then, select the NFT you want to transfer, click on the transfer button and type in the ens or wallet address that should get the NFT.",[11,2294,2295,2298],{},[510,2296,2297],{},"BE CAREFUL. TRIPLE-CHECK THE ADDRESS THAT YOU HAVE NOT COMMITTED ANY TYPO."," If you make a mistake, the NFT will end up in a wallet you don't own, and you cannot recover it.",[11,2300,2301],{},"Try first with an NFT that you don't mind losing. Once you have checked that everything is okay, you can transfer your valuable assets to your hard wallet. As simple as that.",[11,2303,2304],{},"Opensea offers you the option of transferring several NFTs at once. While this is cool, I don't recommend it because you will have to grant access to all your tokens in your soft wallet. Is it safe? Yes. OpenSea is a respected player, but you give them full access to your assets. It might be the case that you have already done this because you have listed some NFTs, so you will not get that request from their side.",[11,2306,2307,2308,2311],{},"I have not sold any of my NFTs, so that´s disabled on my side, and I prefer to keep everything under my control ",[2309,2310],"d",{}," But it is up to you.",[15,2313,2315],{"id":2314},"leveling-the-game","Leveling the game",[11,2317,2318,2319,2324],{},"While transferring the NFTs is nice, one issue that will arise is that your hot wallet cannot be used anymore to confirm that you own an NFT within a Discord server (with Vulkan or ",[37,2320,2323],{"href":2321,"rel":2322},"http://Collab.land",[41],"Collab.land","), or to get airdrops as your NFT is on another wallet.",[11,2326,2327],{},"This is an issue, but \"it is easy to get it solved\". Note the double quotes.",[11,2329,2330,2331,554],{},"The solution is delegating your moved NFTs to your hard wallet on your hot wallet. How can you do that? Let me introduce you ",[37,2332,2335],{"href":2333,"rel":2334},"https://delegate.cash",[41],"delegate.cash",[11,2337,2338,2339,2342],{},"In ",[37,2340,2335],{"href":2333,"rel":2341},[41],", you have to connect your hard wallet and your hot wallet address, to delegate different actions to your hot wallet. In other words: it lets your hot wallet impersonate your cold wallet. As simple as that. The best part? It is a smart contract, so you and only you can modify that delegation, and you can do it on different levels:",[565,2344,2345,2348,2351],{},[568,2346,2347],{},"The full wallet,",[568,2349,2350],{},"a specific contract,",[568,2352,2353],{},"or a specific NFT.",[11,2355,2356,2357,2360,2361,2364,2365,2368],{},"What's the downside? Well, different tools and projects need to integrate ",[37,2358,2335],{"href":2333,"rel":2359},[41]," in their workflows, but this week Vulkan and ",[37,2362,2323],{"href":2321,"rel":2363},[41]," announced that they support officially ",[37,2366,2335],{"href":2333,"rel":2367},[41]," which makes it really cool because now you can authorize yourself in all the Discord servers without having to move your assets between your wallets.",[11,2370,2371,2372,2375],{},"The only downside is that ",[37,2373,2335],{"href":2333,"rel":2374},[41]," needs as ENS blind signing, which is not the best solution for a hard wallet, but that's life. Hopefully, more and more tools will support clear signing in the future so we can see what we sign.",[11,2377,2378],{},"And that's it. I hope you liked this post. If you did, please, share it or subscribe to my newsletter.",{"title":49,"searchDepth":130,"depth":130,"links":2380},[2381,2384,2385,2386,2387],{"id":2200,"depth":130,"text":2201,"children":2382},[2383],{"id":2222,"depth":135,"text":2223},{"id":2241,"depth":130,"text":2242},{"id":2257,"depth":130,"text":2258},{"id":2288,"depth":130,"text":2289},{"id":2314,"depth":130,"text":2315},"2023-02-12T00:00:00.000Z","A simple guide on how to protect your NFTs using hardware wallets","handling-your-nfts-collection-safely",{},"/blog/en/2023-02-12-handling-your-nfts-collection-safely",{"title":2186,"description":2389},"blog/en/2023-02-12-handling-your-nfts-collection-safely","web3, hardwallet, hotwallet, security","EC2zGTbtLgyD0fQki1dCbbbv8jZKZVE87MaEJop8lyo",{"id":2398,"title":2399,"author":6,"body":2400,"date":2628,"description":2629,"extension":140,"headline":141,"icon":2630,"icon_author":141,"icon_url":141,"layout":143,"location":141,"meta":2631,"meta_description":141,"navigation":145,"path":2632,"quote":141,"seo":2633,"slug":2630,"stem":2634,"tags":2635,"template":141,"__hash__":2636},"blog/blog/en/2023-01-27-my-first-year-in-web3.md","My first year in web3",{"type":8,"value":2401,"toc":2619},[2402,2405,2408,2412,2421,2425,2428,2433,2436,2439,2442,2445,2449,2458,2461,2470,2473,2476,2480,2488,2491,2500,2503,2506,2515,2524,2528,2531,2534,2543,2546,2555,2559,2562,2565,2579,2582,2585,2601,2604,2616],[11,2403,2404],{},"More or less, one year ago, I started to participate fully in the web3 world. In the beginning, I remember being quite skeptical about it, thinking it was a Ponzi scheme because all the information you could read pointed in that direction. Luckily I have a few friends that started earlier than me and talked to me about the good things this new space is bringing to the Internet.",[11,2406,2407],{},"When I started, everything revolved around energy consumption; while the truth is that Ethereum consumed a lot of energy, you could still participate by buying some NFTs and doing some transactions on Polygon or Palm without incurring those issues. But all those chains were fancy then, and it was not clear what they brought into the world compared to Ethereum (mainly because all the cool NFT projects were released on Ethereum).",[15,2409,2411],{"id":2410},"my-first-steps","My first steps",[11,2413,2414,2415,2420],{},"After talking with ",[37,2416,2419],{"href":2417,"rel":2418},"https://twitter.com/seanbonner",[41],"Sean Bonner"," I decided to start simple: a hot wallet with Metamask. That was easy. I created the wallet, imported it on my Android phone and on my Linux laptop, and was ready to go. Well, wait, not that simple: you need funds.",[29,2422,2424],{"id":2423},"buying-eth","Buying ETH",[11,2426,2427],{},"While I had a wallet, the next thing was to figure out how to get ETH into it. Let me tell you: it's not that easy. At that moment, all the news was saying that most of the crypto world was used to launder money, but in my experience, that was by far not true. Why? Because buying became \"a problem\".",[11,2429,2430],{},[47,2431],{"alt":49,"src":2432},"/img/blog/my-first-year-in-web3-1.jpg",[11,2434,2435],{},"You have several options to buy ETH: with a credit/debit card or by doing a bank wire transfer. While the first gets you the money \"instantly,\" the second can take up to several days (48 to 72 hours) to get processed. Credit/Debit cards charge you more, as you get the money in minutes, but with bank transfers, you get more ETH for the same price. The problem? You have to trust the company thinking that they will transfer you some Eth back once you send the money.",[11,2437,2438],{},"In my early steps, I used my card. The price was pretty high (remember when ETH was around 4k EUR?), so you could not get too much. The companies that offer this solution usually cap you at 500EUR, and you have to get lucky that the payment gets through because, in most cases, the card is declined. Plus, you have to send your national ID card, address, etc., to prove that you are a human and will not do any fishy stuff.",[11,2440,2441],{},"The bank transfer works the same, but the feeling of not getting the funds in your wallet is horrible, so I have done it only once to experience it. I've never lost money in these processes, but I can assure you that I have more failed transactions than anything else because my card was declined. I hope that at some point in the near future, my bank will offer me a solution to buy directly from them any crypto asset, as this will be easier for everyone, and everything will be clear for the authorities.",[11,2443,2444],{},"Once I had some ETH, it was time to start using it!",[29,2446,2448],{"id":2447},"my-first-transaction","My first transaction",[11,2450,2451,2452,2457],{},"If I'm not mistaken, my first purchase was my ",[37,2453,2456],{"href":2454,"rel":2455},"https://ens.domains/",[41],"ENS domain",". It worked well, but in this first transaction (tx), I learned the hard way about the gas fees: I paid a lot of them. Those were \"the good times\" when every collection was sold out, and tons of transactions were processed, making every single action very expensive. In any case, if I didn't try this first hand, I would never discover how this world worked, and more importantly: when gas fees were low.",[11,2459,2460],{},"Luckily I'm in Europe, so my mornings are usually when all US people are sleeping, so the gas fees are nice and low. Now with the bear market, I've managed to pay as low as 1 EUR in gas fees, which seemed impossible a year ago.",[11,2462,2463,2464,2469],{},"With my ENS domain, I also bought my Unstoppable domains name for Polygon because why not. At that moment, ENS had a lot of traction, but",[37,2465,2468],{"href":2466,"rel":2467},"https://unstoppabledomains.com/",[41]," Unstoppable domains"," were also making some noise, and they offered me a one-time payment for my Polygon wallet. The issue? I've never been able to use it anywhere.",[11,2471,2472],{},"At that moment, I was pretty new to web3, but when I purchased my Unstoppable Domain, I was confused because I could log in to their systems with my Gmail account. Now I can see that they were trying to make things easier, but I still think this was not the right move because you need first to experience how everything works in a web3 way.",[11,2474,2475],{},"Well, I had two web3 identities and was ready to buy my first NFT.",[29,2477,2479],{"id":2478},"my-first-nft-purchase","My first NFT purchase",[11,2481,2482,2483,554],{},"Most NFT projects were pretty expensive. At that moment, I could only pay something like 50EUR for an NFT, so I was browsing all the time Opensea looking for affordable NFTs. None of them were on Ethereum, but most of them were on Polygon. This is when I found my first project: ",[37,2484,2487],{"href":2485,"rel":2486},"https://opensea.io/collection/boredcatclub",[41],"Bored cat club",[11,2489,2490],{},"Well, easy peasy, right? Not that fast; the collection only accepted payments on WETH, so I had to learn how to buy that token with my ETH. Do you remember that I mentioned that gas fees were pretty high? Well, I paid a lot for that exchange, but I was here to figure out how everything worked, right? I got my WETH, and I bought my first NFT:",[11,2492,2493],{},[37,2494,2497],{"href":2495,"rel":2496},"https://opensea.io/assets/matic/0x2953399124f0cbb46d2cbacd8a89cf0599974963/46412420933513635359631007375911560292277814625555123512697263476961047478273",[41],[47,2498],{"alt":49,"src":2499},"/img/blog/my-first-year-in-web3-2.jpg",[11,2501,2502],{},"Then the obvious thing happened: you start identifying yourself with your new NFT because YOU OWN IT. It is yours. That's insane, and through this process, you start to understand why web3 will change everything.",[11,2504,2505],{},"Yes, you have to pay for all the transactions, but that's the cost of owning what you do. Everything is free in the rest of web2 platforms because you are the coin, you and your data.",[11,2507,2508,2509,2514],{},"While this happened, I discovered ",[37,2510,2513],{"href":2511,"rel":2512},"https://opensea.io/collection/lit-project-one",[41],"the first book minted on Ethereum",". This was released on December 2021 by the LIT community and marked the start of a wild trip. I thought this was really innovative, and I jumped in buying some $LIT, 1M $LIT to become a litizen and one of the genesis (or OGs) of the community.",[11,2516,2517,2518,2523],{},"Then, the rest is history. I was utterly hooked on this world with all the possibilities. A few days after buying this coin, I had the chance to get ",[37,2519,2522],{"href":2520,"rel":2521},"https://opensea.io/collection/degenerate-regenerate",[41],"an NFT by OBEY",". They sold out in minutes, and I've been a happy holder since then.",[29,2525,2527],{"id":2526},"more-nfts-please","More NFTs, please",[11,2529,2530],{},"Since then, I have jumped into many different NFT projects. Some have worked out, and others have failed. Then the bear market kicked in, but you know what they say: we build during the bear market, right?",[11,2532,2533],{},"I'm a computer engineer, and I love coding, so I started hacking on Solidity, web3.js frontend, and backend code to build different projects.",[11,2535,2536,2537,2542],{},"After working here and there, I helped the OBEY team to create and test ",[37,2538,2541],{"href":2539,"rel":2540},"https://opensea.io/collection/obey-make-art-not-war-ukraine",[41],"Make Art not War project",": an NFT created by Shepard with the Ukraine flag colors to support two NGOs. The project was a blast, and we managed to raise 28 ETH, around 40k EUR, from the community.",[11,2544,2545],{},"This project helped me to keep going, and Sean offered me the option to become part of the web3 team within the OBEY project. That was awesome! When I was a kid, I loved OBEY clothing, so this was like a dream come true: I was part of the crew and could work on cool web3 projects while learning.",[11,2547,2548,2549,2554],{},"And this is when Sean and I started cooking ",[37,2550,2553],{"href":2551,"rel":2552},"https://opensea.io/collection/dgnrgn-collected",[41],"DGN/RGN Collections"," (at that moment, we called them boxes).",[29,2556,2558],{"id":2557},"dgnrgn-collections-aka-boxes","DGN/RGN Collections (aka boxes)",[11,2560,2561],{},"This project was born because the original DGN/RGN has some pieces that can be bundled together, forming a puzzle. The official DGN/RGN collection had a competition to complete those puzzles by buying them, and Sheppard created specific artwork for them. How awesome is that?",[11,2563,2564],{},"While several wallets got their puzzles together, the truth is that you could not create the puzzle yourself, so we thought: what if we can bundle them in one unique NFT? If this is possible, we should, ideally, let the owner create different layouts, send the original NFTs to a new smart contract that will keep them safe, and mint a new one that will stick all the original NFTs creating a new one that will be transferred to her wallet. Nice right? We launched this long ago, and I still don't know any other project that does this. If you do, let me know, please.",[11,2566,2567,2568,1112,2573,2578],{},"I wrote all the code for this project: backend, frontend, and smart contract. I even did the design (following the previous guidelines from the DGN/RGN site). ",[37,2569,2572],{"href":2570,"rel":2571},"https://twitter.com/harper",[41],"Harper",[37,2574,2577],{"href":2575,"rel":2576},"https://twitter.com/jacobdehart",[41],"Jacob"," helped me debug the smart contract, fix issues, and launch it.",[11,2580,2581],{},"I was beyond excited. Launching web2 projects is fantastic, but web3 is on another level. If you fuck it up, you do it in the worst possible way, and there's no way to recover from it because you cannot undo anything on the code (yes, there're proxy contracts, but you still know what I'm talking about if you have released a smart contract with a bug).",[11,2583,2584],{},"Here you have a few of the most beautiful pieces that the community has created with this tool:",[11,2586,2587,2594],{},[37,2588,2591],{"href":2589,"rel":2590},"https://opensea.io/assets/ethereum/0x30c9334d28bc1401388d9954dc8425b49f5bd67d/25",[41],[47,2592],{"alt":49,"src":2593},"/img/blog/my-first-year-in-web3-3.jpg",[37,2595,2598],{"href":2596,"rel":2597},"https://opensea.io/assets/ethereum/0x30c9334d28bc1401388d9954dc8425b49f5bd67d/23",[41],[47,2599],{"alt":49,"src":2600},"/img/blog/my-first-year-in-web3-4.jpg",[11,2602,2603],{},"One of the cool things about this project is that when you create a collection, you can transfer it or sell it, and in the end, it is just another NFT. If you do that, the wallet that gets it becomes the owner of the collection, and if they decide to undo the collection the original DGN/RGN NFTs will be sent to the new owner, so you are saving gas fees as well :-)",[11,2605,2606,2607,2611,2612],{},"If you want to try the tool, go to ",[37,2608,2609],{"href":2609,"rel":2610},"https://nft.obeygiant.com/collections/",[41]," or browse the existing ones if you want to buy one directly: ",[37,2613,2614],{"href":2614,"rel":2615},"https://opensea.io/ObeyGiantDR/created",[41],[11,2617,2618],{},"If you have read it all, thanks a lot. This has been a long post. I aim to write more about my endeavors on web3 from now on, so subscribe if you want to hear more about what I do and learn about web3.",{"title":49,"searchDepth":130,"depth":130,"links":2620},[2621],{"id":2410,"depth":130,"text":2411,"children":2622},[2623,2624,2625,2626,2627],{"id":2423,"depth":135,"text":2424},{"id":2447,"depth":135,"text":2448},{"id":2478,"depth":135,"text":2479},{"id":2526,"depth":135,"text":2527},{"id":2557,"depth":135,"text":2558},"2023-01-27T00:00:00.000Z","My trip from just a mere observer to a web3 enthusiast","my-first-year-in-web3",{},"/blog/en/2023-01-27-my-first-year-in-web3",{"title":2399,"description":2629},"blog/en/2023-01-27-my-first-year-in-web3","coding, web3, nft, obey","xQiCEsFpg0U5GAqCycnhnQSXlZO3GzN9pdHftIeF-kI",{"id":2638,"title":2639,"author":6,"body":2640,"date":2868,"description":2869,"extension":140,"headline":141,"icon":2870,"icon_author":2871,"icon_url":2872,"layout":143,"location":141,"meta":2873,"meta_description":141,"navigation":145,"path":2874,"quote":2875,"seo":2876,"slug":2877,"stem":2878,"tags":141,"template":141,"__hash__":2879},"blog/blog/en/2020-11-22-simple-cms.md","A simple CMS with nuxt-content and Forestry.io",{"type":8,"value":2641,"toc":2860},[2642,2647,2650,2653,2656,2663,2666,2670,2673,2682,2685,2717,2726,2729,2732,2735,2738,2742,2745,2748,2751,2754,2758,2765,2774,2778,2781,2784,2788,2791,2794,2797,2802,2805,2810,2813,2818,2823,2826,2831,2834,2839,2842,2847,2850,2853],[2643,2644,2646],"h1",{"id":2645},"content-managers","Content Managers",[11,2648,2649],{},"In the past we used to use Wordpress, or even Drupal for making websites where you have tons of information. While these tools have been amazing, nowadays they seem too big for just creating a blog post,\nor even a site where you share your documentation.",[11,2651,2652],{},"The main issue to me with those services is that you need a database, you have to take care of them, and you have tons of options to deal with.",[11,2654,2655],{},"Then, something happened, Jekyll was born and that was the tool I used for a very long time to build sites: static sites. Creating sites using this framework was great. Why? Because you could handle everything\nwithout having to use a database and that was a killer feature. If you add on top of that you could deploy your site almost anywhere, because you didn't need to install a programming language like PHP or Ruby, Jekyll\ncreated for you the final HTML and JS that web browsers understand, so it was a killer feature to use.",[11,2657,2658,2659],{},"While Jekyll grew on popularity, tons of new frameworks appeared for creating new static sites: pelican (for Python lovers like me), mkdocs (again Python here), etc. But at the same time, the JAMStack community started to\ncreate awesome frameworks that allowed this flexibility but on top only of JS: ",[37,2660,2661],{"href":2661,"rel":2662},"https://jamstack.org/generators/",[41],[11,2664,2665],{},"I'll not cover all of them, because there are too many out there, but here I'm going to focus on one of my favorite frameworks: NuxtJS.",[15,2667,2669],{"id":2668},"nuxtjs-and-nuxt-content","NuxtJS and nuxt-content",[11,2671,2672],{},"NuxtJS is a very popular framework that allows you to write SSR sites using VueJS. The community around this framework is amazing, and you usually have tons of tools and libraries that will help you to achieve your goals really quick.",[11,2674,2675,2676,2681],{},"One of these libraries or modules is ",[37,2677,2680],{"href":2678,"rel":2679},"https://content.nuxtjs.org/",[41],"nuxt-content",". This module allows you to extend your NuxtJS application by transforming it into a headless CMS. All you have to do is write your content in a content/ directory and fetch your Markdown, JSON, YAML, XML and CSV files through a MongoDB like API. How cool is that?",[11,2683,2684],{},"It's core features are:",[565,2686,2687,2690,2693,2696,2699,2702,2705,2708,2711,2714],{},[568,2688,2689],{},"Blazing fast hot reload in development",[568,2691,2692],{},"Vue components in Markdown",[568,2694,2695],{},"Full-text search",[568,2697,2698],{},"Support static site generation with nuxt generate",[568,2700,2701],{},"Powerful QueryBuilder API (MongoDB like)",[568,2703,2704],{},"Syntax highlighting to code blocks in markdown files using PrismJS.",[568,2706,2707],{},"Table of contents generation",[568,2709,2710],{},"Handles Markdown, CSV, YAML, JSON(5), XML",[568,2712,2713],{},"Extend with custom parsers",[568,2715,2716],{},"Extend with hooks",[11,2718,2719,2720,2725],{},"Yes, you read it correctly my friend: it has full-text search within the framework. That's really cool, and you won't ",[37,2721,2724],{"href":2722,"rel":2723},"https://daniellombrana.es/blog/2019/02/20/fulltextsearchclient",[41],"need my hack of using Lunr.js to search"," like you can do in this site using a plain nuxt solution.",[11,2727,2728],{},"Thus, nuxt-content will work out of the box for your previous site if you already were using Jekyll or something similar, as all you have to do is copy that content into the content folder and fetch it. Boom! Done! Finito (well, you will have to write the page to get the content, but let me get there in a minute).",[11,2730,2731],{},"While this is really cool, the only issue, as with any previous solution was/is that you cannot usually involve your peers to write content for your site. Why? Because they will need to download your code, install everything, run it, and then write the blog post or content using a regular text editor (hello Neovim coders!) and obviously ask them to create a pull request, so you can review it, merge it and deploy it. At the end you usually will end up asking them to send you the article in a MSdoc format, and you will do the rest of the work.",[11,2733,2734],{},"If we now start thinking about adding media content to that article, well, that will be a nightmare. They will send you the images inside the document, so you will ask them to send the images on an email, they will forget one or two, and then you will end up quite frustrated. Sounds familiar?",[11,2736,2737],{},"The solution: Forestry.io",[15,2739,2741],{"id":2740},"forestry","Forestry",[11,2743,2744],{},"First of all, I'm not affiliated to them, and they've not paid me anything to write this blog post. Now that we're clear about this, I can tell you about Forestry.",[11,2746,2747],{},"Forestry is an editor, of your static site that gives you the power to define the front matter of the articles, and handle your media content within a friendly user interface.",[11,2749,2750],{},"What you do, after setting up an account with them, is to basically define where the content is saved in your Git project (the content folder that I mentioned before), and then you define the folder where you will be putting all your media content (as we use Nuxt we will be using the static folder, and within that folder a new one named images -this could be anything you want-).",[11,2752,2753],{},"That's it! Well, not actually. Forestry allows you to create teams, so this is where the fun starts: because you now can invite your team: marketing, UX, etc. to write/update/edit content within your site without having to tell them anything about how to install Node, write Markdown, or handle uploading media content to your site.",[15,2755,2757],{"id":2756},"a-simple-template-for-you-to-use","A simple template for you to use",[11,2759,2760,2761,554],{},"While I was testing nuxt-content and Forestry.io I decided to create a very simple template that you can use to start your own blog post, or site with these tools: ",[37,2762,2763],{"href":2763,"rel":2764},"https://github.com/teleyinex/simple-cms",[41],[11,2766,2767,2768,2773],{},"This is a very simple template. It uses the ",[37,2769,2772],{"href":2770,"rel":2771},"https://vuetifyjs.com/",[41],"Vuetify framework"," for the visual aspects of it, but you can use whatever you want.",[29,2775,2777],{"id":2776},"how-it-works","How it works",[11,2779,2780],{},"The index page shows a list of articles, while on the left side you will have a table of contents that will be updated based on where you are. If you are in an index page, with several articles, the sidebar will list your available articles. When you access one article, you will be having there the article table of contents. For this, I'm using the store so I can update it from anywhere and reflect the changes anywhere ;-)",[11,2782,2783],{},"Now, go and hack it! Enjoy it!!!",[29,2785,2787],{"id":2786},"setting-up-forestryio","Setting up Forestry.io",[11,2789,2790],{},"Once you have your project up and running, you only need to configure the Forestry tool to allow you to add/edit new contents. How you do that? Well, first you will have to configure the sidebar as they name it. There is where you will be able to setup the types of contents that you will be serving from your site.",[11,2792,2793],{},"As nuxt-content allows you to specify different \"collections\" that are basically folders where you put the content, you can have as many as you want (check their pricing page!).",[11,2795,2796],{},"In this template within the content folder we have the articles folder. Then, you will have to create that \"category\" in the sidebar:",[11,2798,2799],{},[47,2800],{"alt":49,"src":2801},"/img/blog/configure-directory.png",[11,2803,2804],{},"After that, you will be able to create articles using a template. As you will not have a template, you will have to create one from scratch. This is rather simple, the wizard will present you a set of fields:",[11,2806,2807],{},[47,2808],{"alt":49,"src":2809},"/img/blog/front-matter.png",[11,2811,2812],{},"For this template, we've 3 fields: title, description and language. Title and description are text fields, while language is a select where you can add some options, so the content creators don't make mistakes :-)",[11,2814,2815],{},[47,2816],{"alt":49,"src":2817},"/img/blog/title.png",[11,2819,2820],{},[47,2821],{"alt":49,"src":2822},"/img/blog/lang.png",[11,2824,2825],{},"Once you are done, the system will detect your 3 articles, and you will be able to view them directly in the Forestry.io site.",[11,2827,2828],{},[47,2829],{"alt":49,"src":2830},"/img/blog/articles.png",[11,2832,2833],{},"And then you can access one article:",[11,2835,2836],{},[47,2837],{"alt":49,"src":2838},"/img/blog/article.png",[11,2840,2841],{},"This one shows an image. For handling your media, all you have to do is configure it like this:",[11,2843,2844],{},[47,2845],{"alt":49,"src":2846},"/img/blog/media.png",[11,2848,2849],{},"And that's it. Now you can upload into your project, via Forestry any media file. This will be automatically commited to your Git project, and you will be able to reference it from your articles in a visual way. You actually have WYSWYG, so this is perfect.",[11,2851,2852],{},"Now all you have to do is deploy it to something like Vercel, or Github pages and you will be done! Enjoy your new CMS that doesn't need a DB at all!!!",[11,2854,2855,2856],{},"PS: the skull photo is from my Unsplash profile! Check it out: ",[37,2857,2858],{"href":2858,"rel":2859},"https://unsplash.com/@teleyinex",[41],{"title":49,"searchDepth":130,"depth":130,"links":2861},[2862,2863,2864],{"id":2668,"depth":130,"text":2669},{"id":2740,"depth":130,"text":2741},{"id":2756,"depth":130,"text":2757,"children":2865},[2866,2867],{"id":2776,"depth":135,"text":2777},{"id":2786,"depth":135,"text":2787},"2020-11-22T00:00:00.000Z","How to create a simple CMS with nuxt-content and Forestry.io","cms","Jess Bailey","https://unsplash.com/photos/q10VITrVYUM",{},"/blog/en/2020-11-22-simple-cms","Lorem ipsum dolor sit amet, consectetur adipisicing elit",{"title":2639,"description":2869},"simple-cms","blog/en/2020-11-22-simple-cms","TI3lAITp3DCgvHFHDmydeuCwkP6nM6itzFGUIuAvxf0",{"id":2881,"title":2882,"author":6,"body":2883,"date":3068,"description":3069,"extension":140,"headline":141,"icon":3070,"icon_author":3071,"icon_url":3072,"layout":143,"location":141,"meta":3073,"meta_description":141,"navigation":145,"path":3074,"quote":2875,"seo":3075,"slug":3076,"stem":3077,"tags":3078,"template":141,"__hash__":3079},"blog/blog/en/2019-01-18-python2-to-3.md","101 Migrating Python 2 to 3",{"type":8,"value":2884,"toc":3059},[2885,2888,2900,2906,2910,2913,2922,2925,2931,2934,2940,2944,2947,2950,2953,2959,2962,2968,2971,2977,2980,2984,2987,2990,2994,3000,3004,3007,3013,3017,3020,3026,3030,3033,3036,3039,3045,3048,3054],[11,2886,2887],{},"We've just started 2019, but hey, the clock is ticking, and we only have 11 months to port all our Python2.X code to version 3. Are you ready? In this blog post, we will share a few tips that we have learned while migrating our PYBOSSA code to python 3.",[2889,2890,2892],"div",{"style":2891},"width:100%;height:0;padding-bottom:75%;position:relative;",[2893,2894],"iframe",{"src":2895,"width":427,"height":427,"style":2896,"frameBorder":2897,"className":2898,"allowFullScreen":145},"https://giphy.com/embed/thNsW0HZ534DC","position:absolute","0",[2899],"giphy-embed",[11,2901,2902],{},[37,2903,2905],{"href":2904},"https://giphy.com/gifs/countdown-thNsW0HZ534DC","via GIPHY",[15,2907,2909],{"id":2908},"creating-a-virtual-environment","Creating a virtual environment",[11,2911,2912],{},"We always run our Python libraries within a virtual env. However, you don't create them in the same way. In Python 2, you do it like this:",[2914,2915,2920],"pre",{"className":2916,"code":2918,"language":2919},[2917],"language-text","virtualenv env\n","text",[1539,2921,2918],{"__ignoreMap":49},[11,2923,2924],{},"While for Python 3 you should do the following:",[2914,2926,2929],{"className":2927,"code":2928,"language":2919},[2917],"python3 -m venv env\n",[1539,2930,2928],{"__ignoreMap":49},[11,2932,2933],{},"Then you can activate it as usual:",[2914,2935,2938],{"className":2936,"code":2937,"language":2919},[2917],"source env/bin/activate\n",[1539,2939,2937],{"__ignoreMap":49},[2643,2941,2943],{"id":2942},"using-2to3-to-save-some-time","Using 2to3 to save some time",[11,2945,2946],{},"Every project varies in size and number of lines of code, but you, the developer want to be fast on this, right? Or at least not too painful.",[11,2948,2949],{},"Python has a beneficial tool that will help you to migrate your old code to the new version by only running a command line: 2to3.",[11,2951,2952],{},"This command is pretty simple. If you want to see the changes that it will do to your code, you just run it like this:",[2914,2954,2957],{"className":2955,"code":2956,"language":2919},[2917],"2to3 example.py\n",[1539,2958,2956],{"__ignoreMap":49},[11,2960,2961],{},"If you want to write the changes directly into your example.py file, pass a -w. Be sure to use git (or something similar so that you can check the differences):",[2914,2963,2966],{"className":2964,"code":2965,"language":2919},[2917],"2to3 -w example.py\n",[1539,2967,2965],{"__ignoreMap":49},[11,2969,2970],{},"And if you want, you can do something crazy like changing all files at once:",[2914,2972,2975],{"className":2973,"code":2974,"language":2919},[2917],"2to3 -w *.py\n",[1539,2976,2974],{"__ignoreMap":49},[11,2978,2979],{},"Then, check the damage ;-)",[15,2981,2983],{"id":2982},"strings-bytes-utf-8-aka-your-nightmare","Strings, Bytes, UTF-8, aka your nightmare",[11,2985,2986],{},"While migrating PYBOSSA to Python3 most of the issues on our side were related to UTF-8 and how we had the strings in Python 2.",[11,2988,2989],{},"The general advice is to check for the type of the strings, and based on that do whatever you need.",[29,2991,2993],{"id":2992},"bytes-to-strings","Bytes to Strings",[2914,2995,2998],{"className":2996,"code":2997,"language":2919},[2917],"if type(foo) == bytes:\n    bytes.decode('utf-8')\n",[1539,2999,2997],{"__ignoreMap":49},[29,3001,3003],{"id":3002},"strings-to-bytes","Strings to Bytes",[11,3005,3006],{},"You will have several places where your code will fail because now Python 3 expects Bytes instead of strings. For those cases, you can do the following:",[2914,3008,3011],{"className":3009,"code":3010,"language":2919},[2917],"if type(foo) == str:\n    bytes.encode('utf-8')\n",[1539,3012,3010],{"__ignoreMap":49},[29,3014,3016],{"id":3015},"stringio-and-bytesio","StringIO and BytesIO",[11,3018,3019],{},"You have probably used StringIO in your code. Well, it will not work probably in your migration. You will need to adapt it. Usually, based on the type of the text, you will have to use StringIO or BytesIO. Both will solve it for you. A typical case is like this:",[2914,3021,3024],{"className":3022,"code":3023,"language":2919},[2917],"if type(foo) == bytes:\n    data = BytesIO(foo)\nelse:\n    data = StringIO(foo)\n",[1539,3025,3023],{"__ignoreMap":49},[29,3027,3029],{"id":3028},"csv-and-utf-8","CSV and UTF-8",[11,3031,3032],{},"We used the old Python 2 CSV UTF-8 reader example given in the documentation. For Python 2 it works great, but when you try it in Python 3, everything goes to hell :-)",[11,3034,3035],{},"The solution? Use Pandas. Yes, Pandas. It will make your life so much easier.",[11,3037,3038],{},"Pandas will handle everything for you. All you have to do is replace your csv_reader with this:",[2914,3040,3043],{"className":3041,"code":3042,"language":2919},[2917],"import pandas as pd\ndf = pd.read_csv(yourfile)\n",[1539,3044,3042],{"__ignoreMap":49},[11,3046,3047],{},"If you then need to test this code, and you don't have a file, use the previous StringIO or BytesIO to do the magic. Then, load it, and you are done!",[2914,3049,3052],{"className":3050,"code":3051,"language":2919},[2917],"def do_something(csvfile):\n    return pandas.read_csv(csvfile)\n\ndef test_01():\n    fakefile = StringIO('foo,bar\\n,1,2')\n    df = do_something(fakefile)\n        # Check whatever you want\n",[1539,3053,3051],{"__ignoreMap":49},[11,3055,3056,3057],{},"And that's it. Nothing else ;-) Well, yes, put all your prints with () ",[2309,3058],{},{"title":49,"searchDepth":130,"depth":130,"links":3060},[3061,3062],{"id":2908,"depth":130,"text":2909},{"id":2982,"depth":130,"text":2983,"children":3063},[3064,3065,3066,3067],{"id":2992,"depth":135,"text":2993},{"id":3002,"depth":135,"text":3003},{"id":3015,"depth":135,"text":3016},{"id":3028,"depth":135,"text":3029},"2019-01-18T00:00:00.000Z","A few basic tips to migrate your Python 2 to 3","migration","Ethan Weil","https://unsplash.com/photos/IrI889hknhc",{},"/blog/en/2019-01-18-python2-to-3",{"title":2882,"description":3069},"python2-to-3","blog/en/2019-01-18-python2-to-3","python, pybossa, migration, backend","LGmlzxwKpuB5sWgHMzR_oY0Zl7fm54uQYGPI-ZUjdeQ",{"id":3081,"title":3082,"author":6,"body":3083,"date":3068,"description":3270,"extension":140,"headline":141,"icon":3271,"icon_author":3071,"icon_url":3272,"layout":143,"location":141,"meta":3273,"meta_description":141,"navigation":145,"path":3274,"quote":2875,"seo":3275,"slug":3276,"stem":3277,"tags":3278,"template":141,"__hash__":3279},"blog/blog/en/2019-01-25-jekyll2nuxtjs.md","Migrate your Jekyll's site to NuxtJS",{"type":8,"value":3084,"toc":3265},[3085,3088,3097,3116,3129,3132,3139,3142,3153,3160,3163,3168,3172,3181,3184,3192,3195,3202,3208,3211,3215,3218,3224,3227,3230,3233,3236,3242,3246,3253,3262],[11,3086,3087],{},"Static sites are becoming really popular nowadays. Basically, because you don't need to have a server, and there're plenty of free hosting services on the web: Netlify, Github Pages, Zeit now, etc.",[11,3089,3090,3091,3096],{},"You can actually choose from more than ",[37,3092,3095],{"href":3093,"rel":3094},"https://www.staticgen.com/",[41],"200 frameworks",". Actually, you should be able to find one that meets your preferences, because there's almost a framework for each programming language.",[11,3098,3099,3100,3105,3106,1112,3111,554],{},"The most popular one is ",[37,3101,3104],{"href":3102,"rel":3103},"https://www.staticgen.com/jekyll",[41],"Jekyll",". It has more than 36 thousand stars in Github, followed closely by ",[37,3107,3110],{"href":3108,"rel":3109},"https://www.staticgen.com/next",[41],"Next",[37,3112,3115],{"href":3113,"rel":3114},"https://www.staticgen.com/hugo",[41],"Hugo",[11,3117,3118,3119,1319,3123,3128],{},"As you can guess, I've been using Jekyll for a very long time. Actually, all my websites are built with it: ",[37,3120,3122],{"href":951,"rel":3121},[41],"Scifabric.com",[37,3124,3127],{"href":3125,"rel":3126},"https://pybossa.com",[41],"PYBOSSA"," and obviously my home page (where you are right now).",[11,3130,3131],{},"The simplicity of Jekyll is amazing. Anyone can jump automatically, and start building a site within minutes. However, if you are an experienced JS developer, or if you want to create a Progressive Web Application, Jekyll is not the best option. Which was my personal situation.",[11,3133,3134,3135,554],{},"Hence, what could I do? Well, I started coding with VueJS since its version 1.0, then, 2.0 and then I fall in love with ",[37,3136,623],{"href":3137,"rel":3138},"https://nuxtjs.org/",[41],[11,3140,3141],{},"NuxtJS is AWESOME because it handles for you tons of stuff that you don't want to deal with, and have a decent template to start with:",[565,3143,3144,3147,3150],{},[568,3145,3146],{},"Performance: it uses VueJS and NodeJS best practices, so you can get the best and minimal application for your site.",[568,3148,3149],{},"Modular: it has more than 50 modules that will save you tons of work. You can build a Progressive Web Application (PWA) without having to write a single line of code. How cool is that?",[568,3151,3152],{},"Enjoyable: probably one of the best features. As I said before, I'm in deep love with this framework and VueJS. It provides meaningful information, good docs, and a better community.",[11,3154,3155,3156,554],{},"My love with NuxtJS has been driving my late front-end development for Scifabric. Basically, we are using for every client, as we can build really quickly any PWA that will fit the client's needs. One example is our project for Greenpeace Spain: ",[37,3157,3158],{"href":3158,"rel":3159},"https://solarmaps.greenpeace.org",[41],[11,3161,3162],{},"As I worked more and more with NuxtJS, I was wondering how difficult would it be to migrate my home page to NuxtJS and leave behind Jekyll. Why? Because I've become used to Axios, Components, Stylus, and modern tools to build sites, so I wanted to do it for my own site.",[11,3164,3165,3166],{},"The only problem: my Jekyll site has several folders with Markdown files, that rely heavily on the front-matter of them to build the site. In any case, I started to search if this could be possible, and obviously, it is ",[2309,3167],{},[15,3169,3171],{"id":3170},"handling-markdown-in-nuxtjs","Handling Markdown in NuxtJS",[11,3173,3174,3175,3180],{},"There're plenty of solutions out there for importing and handling your Markdown files. For example, you can use the awesome ",[37,3176,3179],{"href":3177,"rel":3178},"https://www.npmjs.com/package/frontmatter-markdown-loader",[41],"Webpack Loader for Markdown"," to get your files imported into NuxtJS.",[11,3182,3183],{},"This was my first try. Using it. While in development mode all worked well, the problem came when I built the static site. The web browser's console was complaining that it was missing the webpack loader for the Markdown files, and therefore, my blog posts didn't show up.",[11,3185,3186,3187,554],{},"Then, I thought, what if I keep things even more simple. What if I can transform the Markdown files into JSON? I did a quick search in the npm registry and I found this amazing library: ",[37,3188,3191],{"href":3189,"rel":3190},"https://www.npmjs.com/package/markdown-to-json",[41],"markdown-to-json",[11,3193,3194],{},"This library was PERFECT. Why? Because you can pass a folder with all your Markdown files, and it will generate a JSON object with all your blog posts in there. The front-matter is parsed and you get it as JSON as well. As everything is JSON, you can request the data using HTTP requests, and you will have everything in place.",[11,3196,3197,3198,3201],{},"I tried with my current blog posts and everything worked like a charm. Thus, what I did was the following: in my NuxtJS project, I created a folder named ",[510,3199,3200],{},"content",". In this folder, I have my blog posts and projects sub-folders with all the Markdown files. Then, I can run a command like this to create the JSON file with all the information:",[2914,3203,3206],{"className":3204,"code":3205,"language":2919},[2917],"$ m2j -c content/blogposts/*.md -o static/blogposts.json\n",[1539,3207,3205],{"__ignoreMap":49},[11,3209,3210],{},"By placing the blogposts.json file in the /static folder, I can use within NuxtJS, Axios to get all the blog posts easily. The only problem is that when you are generating your static site, you need to actually generate all the routes for it.",[15,3212,3214],{"id":3213},"creating-routes-for-nuxtjs","Creating routes for NuxtJS",[11,3216,3217],{},"Hence, how do we handle this? Well, easily. We only need to modify our package.json file to add a few more build commands:",[2914,3219,3222],{"className":3220,"code":3221,"language":2919},[2917],"    \"dev\": \"yarn md2json && nuxt\",\n    \"build\": \"yarn md2json && nuxt build\",\n    \"md2json\": \"m2j -c content/blogposts/*.md -o static/blogposts.json\"\n\n",[1539,3223,3221],{"__ignoreMap":49},[11,3225,3226],{},"Thanks to this solution, when you run yarn dev (or npm run dev) your blog posts will be converted into JSON, and the site will be ready to work with it. The same approach is used for building the static site. This is wonderful because then you can use it with Zeit, Github Pages or Netlify to build it automatically for you.",[11,3228,3229],{},"With this solved, I only had to build my site. It was more or less easy, as I was already using webpack and components in JS for my Jekyll site. In most of the cases, I copied and paste chunks of code, and then adapted them to the NuxtJS world.",[11,3231,3232],{},"The result? This page. Which as you can see is amazingly fast (it's deployed on Zeit). If you are browsing the site from a phone on Android (or iOS) and you are using a modern web browser, you will see that you can install my site in your phone ;-)",[11,3234,3235],{},"Moreover, the audits are really cool. Check them out:",[11,3237,3238],{},[47,3239],{"alt":3240,"src":3241},"Audits from Google","/img/blog/audits-daniel.png",[15,3243,3245],{"id":3244},"a-template","A template",[11,3247,3248,3249,554],{},"As I was doing the migration of my site I realized that this could be really useful for others as well, so I've created a basic template that you can re-use. The code is available here: ",[37,3250,3251],{"href":3251,"rel":3252},"https://github.com/teleyinex/jekyll2nuxt",[41],[11,3254,3255,3256,3261],{},"This template uses ",[37,3257,3260],{"href":3258,"rel":3259},"http://vuetifyjs.com/",[41],"VuetifyJS"," so you can get a material design out of the box for your site. It has the PWA and Markdown modules enabled as well, so everything will work for you out of the box. You only have to copy your blog posts into the content folder and run yarn dev. As simple as that!",[11,3263,3264],{},"If you have read until here, THANKS a lot for your time 🙌. I would appreciate if you share this blog post within your Twitter (or Facebook) friends, so more people can know about it.",{"title":49,"searchDepth":130,"depth":130,"links":3266},[3267,3268,3269],{"id":3170,"depth":130,"text":3171},{"id":3213,"depth":130,"text":3214},{"id":3244,"depth":130,"text":3245},"Learn how you can migrate your static site to NuxtJS","moving","https://unsplash.com/photos/9Q7PqDxCZeQ?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText",{},"/blog/en/2019-01-25-jekyll2nuxtjs",{"title":3082,"description":3270},"jekyll2nuxtjs","blog/en/2019-01-25-jekyll2nuxtjs","frontend, vuejs, nuxtjs, migration, staticsite, jekyll","tQdPqxPRTgayA3EwVmy6QxyQL9Xj703-QlOA991W4oU",{"id":3281,"title":3282,"author":6,"body":3283,"date":3068,"description":3442,"extension":140,"headline":141,"icon":3443,"icon_author":3444,"icon_url":3445,"layout":143,"location":141,"meta":3446,"meta_description":141,"navigation":145,"path":3447,"quote":2875,"seo":3448,"slug":3449,"stem":3450,"tags":141,"template":141,"__hash__":3451},"blog/blog/en/2019-01-25-lambdawebscrapping.md","Visualizing The Air Quality With Lambda Functions",{"type":8,"value":3284,"toc":3434},[3285,3289,3297,3300,3303,3306,3310,3313,3316,3319,3322,3325,3329,3332,3338,3341,3344,3350,3353,3357,3360,3363,3366,3372,3375,3378,3387,3393,3396,3399,3403,3406,3409,3414,3421,3425,3428,3431],[2643,3286,3288],{"id":3287},"lambda-functions","Lambda functions",[11,3290,3291,3296],{},[37,3292,3295],{"href":3293,"rel":3294},"https://en.wikipedia.org/wiki/AWS_Lambda",[41],"Lambda"," functions have been with us since 2014.\nHowever, while I understand how they work, I didn't find a way to use them in a real case. Until this weekend 😜.",[11,3298,3299],{},"If this is the first time that you hear this term, a lambda function is a web\nservice, it could be Amazon, Zeit or Netlify, that will allow you to run a\nfunction (in your preferred programming language) when you access a given URL.",[11,3301,3302],{},"In theory, the advantages are that you don't have a real server running all the\ntime, and that they will only charge for each call to that URL, so it should be\n\"cheaper.\"",[11,3304,3305],{},"But, as it is serverless, you don't have access to a DB, and therefore you\ncannot do \"too many things.\" That's why I didn't see its use cases. Until I\nfigured out.",[15,3307,3309],{"id":3308},"building-apis-using-lambda-functions","Building APIs using lambda functions",[11,3311,3312],{},"Due to my job, I work a lot with data. Broadly speaking, I usually work with\nopen data, so, the data is publicly available, but generally, there's not an API\nfor them.",[11,3314,3315],{},"In those cases, they usually offer you a CSV, XML or similar file, that you will\nhave to download every single day (or every hour) to work with it. In other\nwords, a bit messy.",[11,3317,3318],{},"But, OK, yes, it works. But it's not the best. Especially if you want to make\nqueries, because in those cases you will have to build your own search\nfunctionality or store all the data in your preferred DB.",[11,3320,3321],{},"Obviously, all the previous comments depend on what you want to do with your\nproject. If you only want to show old data (or aggregated one), the CSV or XML\nis perfect. But if you're going to do something more dynamic, then, you have a\nproblem, and you will  have to hack a bit 😄",[11,3323,3324],{},"From this requirement, I found the answer to my question: what if we could use\nlambda functions to do scrapping of open data and return everything in JSON?\nThe answer: yes you can, and it works like a charm.",[15,3326,3328],{"id":3327},"an-api-for-madrids-air-quality-portal","An API for Madrid's air quality portal",[11,3330,3331],{},"I discovered this idea because some time ago, I was trying to see how the air\nquality data of Madrid, Spain was published. The result was a bit sad, as you\ncan have access to the CSV and XML that I mentioned before, an hour prediction\nper station, and a PDF. In other words, nothing really \"useful\" if you want to\nbuild something cool with your #jamstack. Something like a Progressive Web\nApplication.",[11,3333,3334],{},[47,3335],{"alt":3336,"src":3337},"pantallazo de la web del Ayuntamiento","/img/blog/aire1.png",[11,3339,3340],{},"The council's web page shows you the data, but obviously it's not responsive, it\nhas five tables (one within the other) to create the layout... 😱\n(somebody should talk to them about HTML5, flexbox, and grid).",[11,3342,3343],{},"So, I started to work on it. After checking the web, I found that in their forecast per hours, you can select a station and a date (or pollutant) to get the data in\na nice table. After opening the dev tools from Chrome, I found that this form\nsends the following information:",[11,3345,3346],{},[47,3347],{"alt":3348,"src":3349},"pantallazo del formulario","/img/blog/form.png",[11,3351,3352],{},"Easy peasy. I only needed to make the same request, passing the station ID and a\ngiven date. The web page will return me an HTML that I could parse.",[29,3354,3356],{"id":3355},"lambda-functions-in-zeit","Lambda functions in Zeit",[11,3358,3359],{},"My toolchain always involves Python and Js, so Zeit was a perfect option for\nme. Zeit allows you to create lambda functions for both languages, so it is\nperfect.",[11,3361,3362],{},"In my case, I chose Python and BeautifulSoup4 for doing the parsing.",[11,3364,3365],{},"The web page with the result has 5 tables (not a single div, OMG). I found the one that has the real data, and with that info I return this beautiful JSON:",[2914,3367,3370],{"className":3368,"code":3369,"language":2919},[2917],"{\n\"Dióxido de Azufre[µg/m³]\": [], // 24 items\n\"Dióxido de Nitrógeno[µg/m³]\": [], // 24 items\n\"Ozono[µg/m³]\": [\n22,\n32,\n36,\n41,\n52,\n50,\n46,\n46,\n44,\n-1,\n51,\n54,\n55,\n57,\n59,\n60,\n55,\n52,\n47,\n40,\n41,\n43,\n39,\n39\n],\n\"Hora\": [], // 24 items\n\"estacion\": \"Estación de Villaverde\",\n\"fecha\": \"10/02/2019\"\n}\n",[1539,3371,3369],{"__ignoreMap":49},[11,3373,3374],{},"Ready to be consumed by any JS library that can paint any beautiful chart. The API allows me to use any station from Madrid an any given date.",[11,3376,3377],{},"With this ready, all I had to do was to adapt my script to become a lambda\nfunction.",[11,3379,3380,3381,3386],{},"The documentation about how to do it in Zeit is a bit ",[37,3382,3385],{"href":3383,"rel":3384},"https://zeit.co/examples/python",[41],"scarce",". However, doing a bit of googling you will get what you need.\nWith only 47 lines of code, I have a lambda function that parses the air quality\nof Madrid in real time 😎:",[2914,3388,3391],{"className":3389,"code":3390,"language":2919},[2917],"from http.server import BaseHTTPRequestHandler\nimport requests\nimport json\nfrom bs4 import BeautifulSoup\nfrom urllib.parse import urlparse, parse_qs\n\n\nclass handler(BaseHTTPRequestHandler):\n\n    def do_GET(self):\n        self.send_response(200)\n        self.send_header('Content-type', 'application/json')\n        self.send_header('Access-Control-Allow-Origin', '*')\n        self.end_headers()\n        estacion = parse_qs(urlparse(self.path).query).get('estacion')[0]\n        date = parse_qs(urlparse(self.path).query).get('date')[0]\n        data = {'menu':  'consulta', 'smenu': 'reports', 'link': 'data',\n                'view': 'data', 'magnitud': '', 'estacion': int(estacion),\n                'date': date}\n        url = 'http://www.mambiente.munimadrid.es/sica/scripts/index.php?lang=es'\n        r = requests.post(url, data=data)\n        soup = BeautifulSoup(r.content, 'html.parser')\n        tables = soup.find_all('table')\n        table = tables[4]\n        meta = table.find_all(class_='hs')\n        headers = table.find_all(class_='hd')\n        tmp = dict()\n        data = table.find_all(class_='datos')\n        val = []\n        for i in range(len(headers)):\n            val.append(list())\n        for idx, d in enumerate(data):\n            k = idx % len(headers)\n            v = d.get_text()\n            if ((':' not in v) and ('-' not in v)):\n                v = float(v)\n            else:\n                if ('-' in v):\n                    v = -1.0\n            val[k].append(v)\n        for idx, h in enumerate(headers):\n            k = idx % len(headers)\n            v = h.get_text()\n            tmp[v] = val[k]\n        tmp['estacion'] = meta[0].get_text()\n        tmp['fecha'] = meta[1].get_text()\n        self.wfile.write(str(json.dumps(tmp)).encode())\n",[1539,3392,3390],{"__ignoreMap":49},[11,3394,3395],{},"Easy, simple and very clean. The best of all is that you can set any headers\nthat you want, so you can (you should actually) enable CORS so your frontend\nserver can use it.",[11,3397,3398],{},"Once you have done it, all you have to do is deploy it with one command: now.",[15,3400,3402],{"id":3401},"progressive-web-application","Progressive Web Application",[11,3404,3405],{},"At this point, the only remaining part was the frontend server. Thus, I use:\nNuxtJS and created a SPA that will be deployed as well in Zeit. The SPA is a\nPWA so you can install it on your phone.",[11,3407,3408],{},"For the UI toolkit, I'm using Vuetify and its Sparklines components. They are\nsuper cool, and you can create these amazing animations:",[425,3410,428,3411,434],{"width":427,"controls":145},[430,3412],{"src":3413,"type":433},"/vid/aire.mp4",[11,3415,3416,3417],{},"If you want to try the SPA go here:\n",[37,3418,3419],{"href":3419,"rel":3420},"https://aire.daniellombrana.es",[41],[15,3422,3424],{"id":3423},"final-thoughts","Final thoughts",[11,3426,3427],{},"I'm really surprised about how well everything works. Especially, knowing that I\nbuilt everything in 4 hours (I didn't try before lambda functions).",[11,3429,3430],{},"I love the idea that I can use this for doing really quick prototypes, that will\nsave me time and effort in setting up a server with its DB.",[11,3432,3433],{},"What do you think? Did you like it? Let me know on Twitter!",{"title":49,"searchDepth":130,"depth":130,"links":3435},[3436,3437,3440,3441],{"id":3308,"depth":130,"text":3309},{"id":3327,"depth":130,"text":3328,"children":3438},[3439],{"id":3355,"depth":135,"text":3356},{"id":3401,"depth":130,"text":3402},{"id":3423,"depth":130,"text":3424},"How to transform open data into APIs using lambda functions","pollution","Thomas Millot","https://unsplash.com/photos/q5jKHtV4hWc",{},"/blog/en/2019-01-25-lambdawebscrapping",{"title":3282,"description":3442},"lambdawebscrapping","blog/en/2019-01-25-lambdawebscrapping","KqflILBzDH9ecycLr4pgsau3siasw0zeHsEX491kneo",{"id":3453,"title":3454,"author":6,"body":3455,"date":3068,"description":3632,"extension":140,"headline":141,"icon":3529,"icon_author":3633,"icon_url":3634,"layout":143,"location":141,"meta":3635,"meta_description":141,"navigation":145,"path":3636,"quote":2875,"seo":3637,"slug":3638,"stem":3639,"tags":141,"template":141,"__hash__":3640},"blog/blog/en/2019-02-20-fulltextsearchclient.md","Full text search: a simple guide for your static site",{"type":8,"value":3456,"toc":3625},[3457,3461,3464,3471,3476,3491,3494,3498,3505,3510,3518,3521,3524,3547,3551,3558,3563,3566,3572,3575,3581,3591,3594,3597,3603,3606,3615,3619,3622],[2643,3458,3460],{"id":3459},"searching-in-your-static-site","Searching in your static site",[11,3462,3463],{},"As you already know,  static web pages are pretty popular nowadays. However you wil have a little\nissue: it's difficult to add a search engine within your site, as you don't have\na DB behind it.",[2889,3465,3467],{"style":3466},"width:100%;height:0;padding-bottom:73%;position:relative;",[2893,3468],{"src":3469,"width":427,"height":427,"style":2896,"frameBorder":2897,"className":3470,"allowFullScreen":145},"https://giphy.com/embed/l3q2PZSVUUEsajBIY",[2899],[11,3472,3473],{},[37,3474,2905],{"href":3475},"https://giphy.com/gifs/oscars-academy-awards-1952-l3q2PZSVUUEsajBIY",[11,3477,3478,3479,3484,3485,3490],{},"There're some solutions out there like ",[37,3480,3483],{"href":3481,"rel":3482},"https://www.algolia.com/",[41],"Algolia",", or specific servers like ",[37,3486,3489],{"href":3487,"rel":3488},"http://lucene.apache.org/solr/",[41],"Solr",".\nThe first is simple, but at the end you are giving your data to a third party.\nThe next option, Solr, is really cool, but well, we're setting up a serverless\nsolution, right? So we cannot use it 😄.",[11,3492,3493],{},"Thus, what solution do we have?",[15,3495,3497],{"id":3496},"lunrjs-a-bit-like-solr-but-much-smaller-and-not-as-bright","Lunr.JS a bit like Solr, but much smaller and not as bright",[2889,3499,3501],{"style":3500},"width:100%;height:0;padding-bottom:100%;position:relative;",[2893,3502],{"src":3503,"width":427,"height":427,"style":2896,"frameBorder":2897,"className":3504,"allowFullScreen":145},"https://giphy.com/embed/rZKXaQyfvZQv6",[2899],[11,3506,3507],{},[37,3508,2905],{"href":3509},"https://giphy.com/gifs/moon-cute-black-rZKXaQyfvZQv6",[11,3511,3512,3513],{},"While I was looking for a solution to this issue, I found this library ",[37,3514,3517],{"href":3515,"rel":3516},"https://lunrjs.com/",[41],"LunrJS",[11,3519,3520],{},"The library is pretty small, it has not dependencies, you can install it with\nyarn (or if y ou prefer with npm). You can index hundreds of documents without\nissues, and all you have to do is to specify what do you want to index, and what\nfield are you gonna use to identify the document.",[11,3522,3523],{},"If on top of that I'll tell you that it does stemming and it supports several\nlanguages, well, you would be thinking that this solution is 🔥",[11,3525,3526,3527,1319,3530,1112,3533,3536,3537,3540,3541,3543,3544,3546],{},"NOTE, from its website: \"Stemming is the process of reducing inflected or derived words to their base or stem form. For example, the stem of ",[247,3528,3529],{},"searching",[247,3531,3532],{},"searched",[247,3534,3535],{},"searchable"," should be ",[247,3538,3539],{},"search",". This has two benefits: firstly the number of tokens in the search index, and therefore its size, is significantly reduced, and in addition, it increases the recall when performing a search. A document containing the word ",[247,3542,3529],{}," is likely to be relevant to a query for ",[247,3545,3539],{},"\".",[29,3548,3550],{"id":3549},"integrating-lunrjs-in-nuxtjs","Integrating LunrJS in NuxtJS",[2889,3552,3554],{"style":3553},"width:100%;height:0;padding-bottom:42%;position:relative;",[2893,3555],{"src":3556,"width":427,"height":427,"style":2896,"frameBorder":2897,"className":3557,"allowFullScreen":145},"https://giphy.com/embed/AvMJCeu1EMmhG",[2899],[11,3559,3560],{},[37,3561,2905],{"href":3562},"https://giphy.com/gifs/reaction-this-is-the-end-breaks-AvMJCeu1EMmhG",[11,3564,3565],{},"The integration is pretty straightforward. All you have to do is importing the\nlibrary like this:",[2914,3567,3570],{"className":3568,"code":3569,"language":2919},[2917],"var lunr = require(\"lunr\")\nrequire('lunr-languages/lunr.stemmer.support')(lunr)\nrequire('lunr-languages/lunr.multi')(lunr)\nrequire('lunr-languages/lunr.es')(lunr)\n",[1539,3571,3569],{"__ignoreMap":49},[11,3573,3574],{},"Then, you can use your asyncData or created methods (depending on where are you\ngetting the data to get indexed) and you write something like this:",[2914,3576,3579],{"className":3577,"code":3578,"language":2919},[2917],"  created() {\n    const self = this\n    const idx = lunr(function() {\n      this.use(lunr.multiLanguage('en', 'es'))\n      this.ref('basename')\n      this.field('content')\n      self.blogposts.forEach(blog => this.add(blog), this)\n    })\n    this.$store.commit('setIdx', idx)\n  },\n",[1539,3580,3578],{"__ignoreMap":49},[11,3582,3583,3584,3587,3588,3590],{},"With those lines we are telling Lunr what is the unique identifier, in this case\nthe ",[247,3585,3586],{},"basename",". Then, we tell it what do we want to index, in this case\n",[247,3589,3200],{}," (which is our compiled Markdown from my blogposts). Finally, we pass\nall the blogposts to the index, and we move it to the store, so you can use it\nfrom any component. Simple?",[29,3592,3593],{"id":3529},"Searching",[11,3595,3596],{},"Now all you have to do is doing a search. For this task, you can write a method\nlike this:",[2914,3598,3601],{"className":3599,"code":3600,"language":2919},[2917],"search() {\n  const found = this.$store.state.idx.search(this.query)\n  this.$store.commit('setFound', found)\n}\n",[1539,3602,3600],{"__ignoreMap":49},[11,3604,3605],{},"With this method we get the results and we save them in the store.",[11,3607,3608,3609,3614],{},"NOTE: if you want to do searches while the user is typing, you can. The only\nthing you have to do is to not fire with every key stroke the search method, so\nyou should use ",[37,3610,3613],{"href":3611,"rel":3612},"https://lodash.com/docs/4.17.11#debounce",[41],"debounce"," from Lodash\nto throttle the calls.",[15,3616,3618],{"id":3617},"result","Result",[11,3620,3621],{},"The result of this blog post is that I've applied it to my blog site, and now\nyou can search within all the blog posts that I have written. As soon as you are\ntyping, the search method is called (via the debounce function) and the results\nget updated in real time. The search is reeeaaallly fast, because everything is\nin memory.",[11,3623,3624],{},"I love this solution because it's clean, fast an simple.",{"title":49,"searchDepth":130,"depth":130,"links":3626},[3627,3631],{"id":3496,"depth":130,"text":3497,"children":3628},[3629,3630],{"id":3549,"depth":135,"text":3550},{"id":3529,"depth":135,"text":3593},{"id":3617,"depth":130,"text":3618},"How to index your static site and make it searchable without a DB","Forest simon","https://unsplash.com/photos/-TX0ufDSCV4",{},"/blog/en/2019-02-20-fulltextsearchclient",{"title":3454,"description":3632},"fulltextsearchclient","blog/en/2019-02-20-fulltextsearchclient","1jUzL7uaj53pE2QwqthxZAvUg1q5Mf1pMg-3z5X77Co",{"id":3642,"title":3643,"author":6,"body":3644,"date":3788,"description":3789,"extension":140,"headline":141,"icon":3790,"icon_author":3791,"icon_url":3792,"layout":143,"location":141,"meta":3793,"meta_description":141,"navigation":145,"path":3794,"quote":2875,"seo":3795,"slug":3796,"stem":3797,"tags":3798,"template":141,"__hash__":3799},"blog/blog/en/2018-12-20-year-in-review.md","Year in review",{"type":8,"value":3645,"toc":3778},[3646,3649,3656,3661,3665,3668,3672,3675,3678,3684,3688,3691,3694,3697,3701,3704,3707,3711,3714,3717,3720,3727,3732,3735,3739,3745,3750,3765,3768,3771,3775],[11,3647,3648],{},"2018 is finishing, and I would like to reflect on the numbers that we have achieved this year working hard. Hey, after all, we want to prove to Santa that we were good kids over the year so we can enjoy this Christmas with wonderful toys (and the family, of course!).",[2889,3650,3652],{"style":3651},"width:100%;height:0;padding-bottom:56%;position:relative;",[2893,3653],{"src":3654,"width":427,"height":427,"style":2896,"frameBorder":2897,"className":3655,"allowFullScreen":145},"https://giphy.com/embed/3ofT5EtPNBpIjC8jTy",[2899],[11,3657,3658],{},[37,3659,2905],{"href":3660},"https://giphy.com/gifs/filmeditor-will-ferrell-elf-3ofT5EtPNBpIjC8jTy",[15,3662,3664],{"id":3663},"projects","Projects",[11,3666,3667],{},"This year we have launched several projects, but two of them are Solar maps, La memoria del Circo and a European Space Agency project.",[29,3669,3671],{"id":3670},"solar-maps","Solar maps",[11,3673,3674],{},"We worked with Greenpeace Spain to launch a crowdsourcing project where we ask people to measure the area of the Spanish public buildings. The goal? Put solar panels on those roofs and learn how much energy and CO2 we can save.",[11,3676,3677],{},"The project was launched in May, and as of today, more than 900 buildings have been completed, resulting in more than 820 thousand square meters to install solar panels. This measured area means that the Spanish government can save more than 230 million, yes MILLION, of Euros in 25 years, and 36 thousand tons of CO2. Not bad, right? Moreover, if we install these panels, it is like if we remove from the roads more than 284 thousand cars!!! Amazing.",[425,3679,428,3681],{"controls":145,"style":3680,"autoPlay":145},"max-width: 300px;",[430,3682],{"src":3683,"type":433},"/vid/greenpeace.mp4",[15,3685,3687],{"id":3686},"la-memoria-del-circo","La memoria del Circo",[11,3689,3690],{},"This project is so beautiful that we can only love it. PYBOSSA has been quite popular lately within the GLAM (Galleries, Libraries, Archives, and Museums) sector and this project is one of those that get your childhood back. Because who has not gone to a Circus? Older or younger, with the changes in it, we always have been in this magical place.",[11,3692,3693],{},"For these reasons, Factoría Cultural wanted to launch a crowdsourcing project where we could recover the history of the circus. Because the past is missing in private collections and almost no one can access it.",[11,3695,3696],{},"The project has started with a tiny and unique collection: the last performance in the mythical Spanish Circus PRICE.",[15,3698,3700],{"id":3699},"detecting-buried-archaeological-sites","Detecting buried archaeological sites",[11,3702,3703],{},"When we were contacted by ESA (European Space Agency) about using our PYBOSSA powered platform to detect buried archaeological sites we were amazed.",[11,3705,3706],{},"The project is cool. ESA is using aerial images to find archaeological structures beneath the ground in areas surrounding the city of Rome, Italy. And right now you should be asking yourself: how do they do it? Well, it turns out that crop marks in this area are usually of ancient Roman origin. They tend to have clear geometric patterns, revealing the foundations of buildings. Roman roads can be distinguished as very straight lines of parched vegetation (overlying ancient paving stones), with strips of greener vegetation on either side, where ditches used to be.",[47,3708],{"src":3709,"style":3710},"https://raw.githubusercontent.com/ESA-PhiLab/pybossa-eo-browser-imagery-microtasking/master/data/CropMarkExamples.png","width:100%;",[11,3712,3713],{},"How cool is that?!",[15,3715,3127],{"id":3716},"pybossa",[11,3718,3719],{},"We have worked hard in improving PYBOSSA, and we launched what we think it's the most prominent feature of the year: you can now capture data directly within PYBOSSA. Yes, you don't need EpiCollect+ or any other tool to capture videos, images, audio and geolocalize them.",[2889,3721,3723],{"style":3722},"width:100%;height:0;padding-bottom:57%;position:relative;",[2893,3724],{"src":3725,"width":427,"height":427,"style":2896,"frameBorder":2897,"className":3726,"allowFullScreen":145},"https://giphy.com/embed/WwCGttCAHbwMYsOnBz",[2899],[11,3728,3729],{},[37,3730,2905],{"href":3731},"https://giphy.com/gifs/WwCGttCAHbwMYsOnBz",[11,3733,3734],{},"PYBOSSA now allows you to build surveys and spice them with some videos of the area. You can ask users to read aloud some text on the street and save it, or well, use your imagination :-) This feature is fantastic because you can even get your Internet of Things (IoT) recording data that can be automatically sent to a PYBOSSA server so the crowd can analyze/validate it.",[15,3736,3738],{"id":3737},"numbers","Numbers",[2889,3740,3741],{"style":3651},[2893,3742],{"src":3743,"width":427,"height":427,"style":2896,"frameBorder":2897,"className":3744,"allowFullScreen":145},"https://giphy.com/embed/ccQ8MSKkjHE2c",[2899],[11,3746,3747],{},[37,3748,2905],{"href":3749},"https://giphy.com/gifs/adventure-time-math-ccQ8MSKkjHE2c",[11,3751,3752,3753,3758,3759,3764],{},"Regarding numbers this year, all our \"known\" PYBOSSA servers have saved more than 730 thousand classifications, analysis, transcriptions, geolocalization, validation of tasks. Not bad, as this is only from 12 servers, just from our clients. We know that there are many more PYBOSSA servers out there, so PYBOSSA is helping tons of people all over the world. For example, ",[37,3754,3757],{"href":3755,"rel":3756},"https://www.libcrowds.com/",[41],"LibCrowds"," from the British Library has more than 127 thousand contributions (since its creation), and ",[37,3760,3763],{"href":3761,"rel":3762},"https://burntheregister.com/",[41],"Burntheregister"," has around 9 thousand contributions.",[11,3766,3767],{},"We have written more than 218 thousand lines of frontend code. We use Vuejs, Nuxtjs to build Progressive Web Applications for our clients.",[11,3769,3770],{},"For PYBOSSA code we have added 4438 lines of code, removed 1246 and modified 142 files this year. Not bad at all.",[15,3772,3774],{"id":3773},"summary","Summary",[11,3776,3777],{},"Two thousand eighteen has been an excellent year, and we hope that 2019 will be even better! Merry Christmas and Happy New Year!!!",{"title":49,"searchDepth":130,"depth":130,"links":3779},[3780,3783,3784,3785,3786,3787],{"id":3663,"depth":130,"text":3664,"children":3781},[3782],{"id":3670,"depth":135,"text":3671},{"id":3686,"depth":130,"text":3687},{"id":3699,"depth":130,"text":3700},{"id":3716,"depth":130,"text":3127},{"id":3737,"depth":130,"text":3738},{"id":3773,"depth":130,"text":3774},"2018-12-20T00:00:00.000Z","What we have done this 2018","back","Jay Toor","https://unsplash.com/photos/PjABCLdM6DY",{},"/blog/en/2018-12-20-year-in-review",{"title":3643,"description":3789},"year-in-review-2018","blog/en/2018-12-20-year-in-review","yearinreview, pybossa, scifabric","IGhAyC4dythAF2IB7EsO-W4OcrkBrGvVL34z56ImyvU",{"id":3801,"title":3802,"author":141,"body":3803,"date":3873,"description":3874,"extension":140,"headline":141,"icon":3875,"icon_author":3876,"icon_url":3877,"layout":143,"location":141,"meta":3878,"meta_description":141,"navigation":145,"path":3879,"quote":2875,"seo":3880,"slug":3881,"stem":3882,"tags":3883,"template":141,"__hash__":3884},"blog/blog/en/2018-01-08-on-the-press.md","On the press",{"type":8,"value":3804,"toc":3871},[3805,3808,3817,3820,3837,3840],[11,3806,3807],{},"The end of 2018 was really good. The Spanish newspaper Expansion (about business and economy) and the National Spanish TV RTVE interviewed me\nto show our work as examples of innovatives ways of supporting cultural enterprises or\ninstitutions from all the world.",[11,3809,3810,3811,3816],{},"These interviews have been thanks to the support that I'm getting from ",[37,3812,3815],{"href":3813,"rel":3814},"http://factoriacultural.es/",[41],"Factoría Cultural",".\nThey are amazing, so if you have a project in your head, just talk to them, you will not regret it.",[11,3818,3819],{},"Here you have the interviews:",[565,3821,3822,3830],{},[568,3823,3824,3829],{},[37,3825,3828],{"href":3826,"rel":3827},"http://www.expansion.com/pymes/2017/12/13/5a294f9fe2704ee74d8b45b1.html",[41],"Expansión",", and",[568,3831,3832],{},[37,3833,3836],{"href":3834,"rel":3835},"https://www.rtve.es/alacarta/videos/fabrica-de-ideas/fdi-incuba/4327223/",[41],"La fábrica de ideas",[11,3838,3839],{},"The Spanish TV show, can be viewed here. Enjoy!",[2889,3841,3843,3844,3843,3850],{"style":3842},"width:100%;padding-top:64%;position:relative;border-bottom:1px solid #aaa;display:inline-block;background:#eee;background:rgba(255,255,255,0.9);","\n    ",[2893,3845],{"frameBorder":2897,"src":3846,"name":3847,"scrolling":3848,"style":3849,"allowFullScreen":145},"https://www.rtve.es/drmn/embed/video/4327223","Incuba: Factoría Cultural","no","width:100%;height:90%;position:absolute;left:0;top:0;overflow:hidden;",[2889,3851,3853,3854,3862,3863,3870],{"style":3852},"position:absolute;bottom:0;left:0;font-family:arial,helvetica,sans-serif;font-size:12px;line-height:1.833;display:inline-block;padding:5px 0 5px 10px;","\n        ",[224,3855,3857,3858,3853],{"style":3856},"float:left;margin-right:10px;","\n        \t",[47,3859],{"style":3860,"src":3861},"height:20px;width:auto;background: transparent;padding:0;margin:0;","https://img.rtve.es/css/rtve.commons/rtve.header.footer/i/logoRTVEes.png","\n       \t",[37,3864,3866,3867,3869],{"style":3865,"title":3847,"href":3834},"color:#333;font-weight:bold;","\n            ",[510,3868,3847],{},"\n\t\t","\n\t",{"title":49,"searchDepth":130,"depth":130,"links":3872},[],"2018-01-08T00:00:00.000Z","Press coverage about my work","press","Samule Sun","https://unsplash.com/photos/XJXWbfSo2f0",{},"/blog/en/2018-01-08-on-the-press",{"title":3802,"description":3874},"on-the-press","blog/en/2018-01-08-on-the-press","press, pybossa, scifabric, video, conference","zDeBA57238zzmA3_bR4VIrZRNAH3iDMJWab6_--Cy90",{"id":3886,"title":3887,"author":141,"body":3888,"date":5207,"description":5208,"extension":140,"headline":141,"icon":1539,"icon_author":5209,"icon_url":3877,"layout":143,"location":141,"meta":5210,"meta_description":141,"navigation":145,"path":5211,"quote":2875,"seo":5212,"slug":5213,"stem":5214,"tags":5215,"template":141,"__hash__":5216},"blog/blog/en/2017-10-13-jekyll-vuejs-bulma.md","Building static websites with Jekyll, VueJS & Bulma",{"type":8,"value":3889,"toc":5196},[3890,3893,3896,3902,3907,3911,3920,3923,3926,3933,4002,4005,4008,4181,4184,4187,4191,4194,4198,4825,4828,4831,4834,4837,5001,5004,5141,5144,5150,5154,5157,5163,5167,5179,5182,5186,5193],[11,3891,3892],{},"We love static websites. Why? Because they're fast. Really fast. Moreover, you don't have to take care of a database, and you like that a lot.",[11,3894,3895],{},"You are probably building your site already with Jekyll, and while this is cool, sometimes you want to add some magic into the mix to have some fancy JS frameworks like VueJS or React for developing cool stuff. Also, you got so used to Babel and Webpack that you don't know how to write JS code anymore without this toolchain. Hence, you have a question: can I still use my Jekyll site and add as toppings VueJS + Babel + Webpack? Yes, you can! Let me explain how. Let's begin the hacking!",[2889,3897,3898],{"style":3500},[2893,3899],{"src":3900,"width":427,"height":427,"style":2896,"frameBorder":2897,"className":3901,"allowFullScreen":145},"https://giphy.com/embed/JIX9t2j0ZTN9S",[2899],[11,3903,3904],{},[37,3905,2905],{"href":3906},"https://giphy.com/gifs/JIX9t2j0ZTN9S",[15,3908,3910],{"id":3909},"making-jekyll-speak-json","Making Jekyll speak JSON",[11,3912,3913,3914,3919],{},"As you will be using a framework like ",[37,3915,3918],{"href":3916,"rel":3917},"https://vuejs.org/",[41],"VueJS"," (we love love love love it so much, that from now on we will only talk about this framework), we need to instruct Jekyll to serve our content as JSON.",[11,3921,3922],{},"There are several options for serving your content as JSON, but one that we like a lot is using the _data folder to store inside of it YAML (or JSON directly) that will be transformed into JSON in the HTML page that your VueJS app will be rendered.",[11,3924,3925],{},"Wait, yes, you read that we will be writing content in YAML to transform it into JSON and then load it into VueJS. Why so much trouble? Well, because we want to allow non-coders to be able to add or edit content quickly, and YAML is simple on that (in other words, less curly braces ;-)).",[11,3927,3928,3929,3932],{},"Thus, go to your _data folder and create a file named ",[510,3930,3931],{},"mydata.yml",". This file could have something like this:",[2914,3934,3938],{"className":3935,"code":3936,"language":3937,"meta":49,"style":49},"language-yaml shiki shiki-themes catppuccin-latte catppuccin-mocha","- title: How crowdsourcing can help beat cancer\n  person: profile.jpg\n  cover: logo.png\n  person_name: John Doe\n  person_position: Digital Solutions Architect\n","yaml",[1539,3939,3940,3960,3970,3980,3991],{"__ignoreMap":49},[224,3941,3944,3948,3952,3956],{"class":3942,"line":3943},"line",1,[224,3945,3947],{"class":3946},"sxyLT","-",[224,3949,3951],{"class":3950},"sS0zD"," title",[224,3953,3955],{"class":3954},"sjJjI",":",[224,3957,3959],{"class":3958},"sgueU"," How crowdsourcing can help beat cancer\n",[224,3961,3962,3965,3967],{"class":3942,"line":130},[224,3963,3964],{"class":3950},"  person",[224,3966,3955],{"class":3954},[224,3968,3969],{"class":3958}," profile.jpg\n",[224,3971,3972,3975,3977],{"class":3942,"line":135},[224,3973,3974],{"class":3950},"  cover",[224,3976,3955],{"class":3954},[224,3978,3979],{"class":3958}," logo.png\n",[224,3981,3983,3986,3988],{"class":3942,"line":3982},4,[224,3984,3985],{"class":3950},"  person_name",[224,3987,3955],{"class":3954},[224,3989,3990],{"class":3958}," John Doe\n",[224,3992,3994,3997,3999],{"class":3942,"line":3993},5,[224,3995,3996],{"class":3950},"  person_position",[224,3998,3955],{"class":3954},[224,4000,4001],{"class":3958}," Digital Solutions Architect\n",[11,4003,4004],{},"Then go to your Jekyll folder where you will be rendering your VueJS app. Let's see you want to build a hello world URL, so go to the folder helloworld and edit a file named index.html.",[11,4006,4007],{},"This file will have the front matter as any other Jekyll file, but you will have to modify it to render your VueJS app:",[2914,4009,4013],{"className":4010,"code":4011,"language":4012,"meta":49,"style":49},"language-html shiki shiki-themes catppuccin-latte catppuccin-mocha","---\nlayout: default\ntitle: Hello World\ndescription: Jekyll and Vuejs\n---\n\u003Csection id=\"vuejs\" class=\"section\">\n    \u003CApp>\u003C/App>\n\u003C/section>\n\u003Cscript>\nwindow.mydata = {{ site.data.mydata | jsonify }};\n\u003C/script>\n\u003Cscript src=\"/assets/js/myvuejs.min.js\">\u003C/script>\n","html",[1539,4014,4015,4021,4026,4031,4036,4040,4070,4086,4096,4106,4143,4155],{"__ignoreMap":49},[224,4016,4017],{"class":3942,"line":3943},[224,4018,4020],{"class":4019},"s0aCy","---\n",[224,4022,4023],{"class":3942,"line":130},[224,4024,4025],{"class":4019},"layout: default\n",[224,4027,4028],{"class":3942,"line":135},[224,4029,4030],{"class":4019},"title: Hello World\n",[224,4032,4033],{"class":3942,"line":3982},[224,4034,4035],{"class":4019},"description: Jekyll and Vuejs\n",[224,4037,4038],{"class":3942,"line":3993},[224,4039,4020],{"class":4019},[224,4041,4043,4046,4049,4053,4056,4059,4062,4064,4067],{"class":3942,"line":4042},6,[224,4044,4045],{"class":3954},"\u003C",[224,4047,4048],{"class":3950},"section",[224,4050,4052],{"class":4051},"sObzt"," id",[224,4054,4055],{"class":3954},"=",[224,4057,4058],{"class":3958},"\"vuejs\"",[224,4060,4061],{"class":4051}," class",[224,4063,4055],{"class":3954},[224,4065,4066],{"class":3958},"\"section\"",[224,4068,4069],{"class":3954},">\n",[224,4071,4073,4076,4079,4082,4084],{"class":3942,"line":4072},7,[224,4074,4075],{"class":3954},"    \u003C",[224,4077,4078],{"class":3950},"App",[224,4080,4081],{"class":3954},">\u003C/",[224,4083,4078],{"class":3950},[224,4085,4069],{"class":3954},[224,4087,4089,4092,4094],{"class":3942,"line":4088},8,[224,4090,4091],{"class":3954},"\u003C/",[224,4093,4048],{"class":3950},[224,4095,4069],{"class":3954},[224,4097,4099,4101,4104],{"class":3942,"line":4098},9,[224,4100,4045],{"class":3954},[224,4102,4103],{"class":3950},"script",[224,4105,4069],{"class":3954},[224,4107,4109,4112,4114,4117,4119,4122,4125,4127,4130,4132,4134,4137,4140],{"class":3942,"line":4108},10,[224,4110,4111],{"class":4019},"window",[224,4113,554],{"class":3954},[224,4115,4116],{"class":4019},"mydata ",[224,4118,4055],{"class":3954},[224,4120,4121],{"class":3946}," {{",[224,4123,4124],{"class":4019}," site",[224,4126,554],{"class":3954},[224,4128,4129],{"class":4019},"data",[224,4131,554],{"class":3954},[224,4133,4116],{"class":4019},[224,4135,4136],{"class":3954},"|",[224,4138,4139],{"class":4019}," jsonify ",[224,4141,4142],{"class":3946},"}};\n",[224,4144,4146,4148,4151,4153],{"class":3942,"line":4145},11,[224,4147,4045],{"class":4019},[224,4149,4150],{"class":3954},"/",[224,4152,4103],{"class":3950},[224,4154,4069],{"class":3954},[224,4156,4158,4160,4162,4165,4167,4170,4173,4175,4177,4179],{"class":3942,"line":4157},12,[224,4159,4045],{"class":3954},[224,4161,4103],{"class":3950},[224,4163,4164],{"class":4051}," src",[224,4166,4055],{"class":3954},[224,4168,4169],{"class":3958},"\"/assets/js/myvuejs.min.js\"",[224,4171,4172],{"class":3954},">",[224,4174,4045],{"class":4019},[224,4176,4150],{"class":3954},[224,4178,4103],{"class":3950},[224,4180,4069],{"class":3954},[11,4182,4183],{},"That's all! We provide the DOM for mounting the VueJS app. Then, we create a script section where we can load our mydata.yaml as a JSON object, and below it our minified version of our VueJS app (thanks Webpack!).",[11,4185,4186],{},"Obviously, you will need to compile webpack and Jekyll commands to build everything correctly. As both command support a --watch flag, you can run both of them in parallel and forget about running the commands by hand while you develop your excellent new site.",[15,4188,4190],{"id":4189},"vuejs-bulma-css-and-webpack","VueJS, Bulma CSS, and Webpack",[11,4192,4193],{},"Well, this has been easy, right? But, how do we adequately integrate our webpack toolchain into the site as well? We just instruct webpack to do it properly.",[29,4195,4197],{"id":4196},"webpack","Webpack",[2914,4199,4203],{"className":4200,"code":4201,"language":4202,"meta":49,"style":49},"language-javascript shiki shiki-themes catppuccin-latte catppuccin-mocha","// webpack.config.js\nvar htmlWebpackPlugin = require('html-webpack-plugin');\nvar webpack = require(\"webpack\");\nmodule.exports = {\n  // entry point of our application\n  entry: './helloworld.js',\n  // where to place the compiled bundle\n  output: {\n    path: '../',\n    publicPath: '../',\n    filename: 'helloworld.min.js'\n  },\n  module: {\n    // `loaders` is an array of loaders to use.\n    // here we are only configuring vue-loader\n    loaders: [\n      {\n        test: /\\.vue$/, // a regex for matching all files that end in `.vue`\n        loader: 'vue-loader'   // loader to use for matched files\n      },\n      {\n        test: /\\.js$/,\n        loader: 'babel-loader',\n        exclude: /node_modules/\n      },\n      {\n      test: /\\.[sa|sc|c]ss$/,\n      loader: \"style!css!sass\"\n      }, {\n        test: /\\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/,\n        loader: 'file-loader?outputPath=../img/search/&publicPath=../img/search/'\n      }\n    ],\n    noParse: /dist\\/ol.js/,\n  },\nvue: {\n  loaders: {\n    scss: 'style!css!sass'\n  }},\n\n  resolve: {\n    alias: {\n      'vue$': 'vue/dist/vue.common.js'\n    }\n  },\n  plugins: [\n    new webpack.optimize.DedupePlugin(),\n    new webpack.optimize.UglifyJsPlugin({minimize: true})\n  ]\n\n}\n","javascript",[1539,4204,4205,4211,4238,4258,4275,4280,4293,4298,4307,4319,4330,4340,4345,4355,4361,4367,4378,4384,4410,4424,4430,4435,4453,4465,4482,4487,4492,4520,4531,4539,4597,4607,4613,4621,4648,4653,4662,4672,4683,4689,4695,4705,4715,4726,4732,4737,4747,4772,4808,4814,4819],{"__ignoreMap":49},[224,4206,4207],{"class":3942,"line":3943},[224,4208,4210],{"class":4209},"som-u","// webpack.config.js\n",[224,4212,4213,4217,4220,4222,4226,4229,4232,4235],{"class":3942,"line":130},[224,4214,4216],{"class":4215},"sAS4m","var",[224,4218,4219],{"class":4019}," htmlWebpackPlugin ",[224,4221,4055],{"class":3954},[224,4223,4225],{"class":4224},"sMmZK"," require",[224,4227,4228],{"class":4019},"(",[224,4230,4231],{"class":3958},"'html-webpack-plugin'",[224,4233,4234],{"class":4019},")",[224,4236,4237],{"class":3946},";\n",[224,4239,4240,4242,4245,4247,4249,4251,4254,4256],{"class":3942,"line":135},[224,4241,4216],{"class":4215},[224,4243,4244],{"class":4019}," webpack ",[224,4246,4055],{"class":3954},[224,4248,4225],{"class":4224},[224,4250,4228],{"class":4019},[224,4252,4253],{"class":3958},"\"webpack\"",[224,4255,4234],{"class":4019},[224,4257,4237],{"class":3946},[224,4259,4260,4264,4266,4269,4272],{"class":3942,"line":3982},[224,4261,4263],{"class":4262},"sUlWy","module",[224,4265,554],{"class":3954},[224,4267,4268],{"class":4262},"exports",[224,4270,4271],{"class":3954}," =",[224,4273,4274],{"class":3946}," {\n",[224,4276,4277],{"class":3942,"line":3993},[224,4278,4279],{"class":4209},"  // entry point of our application\n",[224,4281,4282,4285,4287,4290],{"class":3942,"line":4042},[224,4283,4284],{"class":4019},"  entry",[224,4286,3955],{"class":3954},[224,4288,4289],{"class":3958}," './helloworld.js'",[224,4291,4292],{"class":3946},",\n",[224,4294,4295],{"class":3942,"line":4072},[224,4296,4297],{"class":4209},"  // where to place the compiled bundle\n",[224,4299,4300,4303,4305],{"class":3942,"line":4088},[224,4301,4302],{"class":4019},"  output",[224,4304,3955],{"class":3954},[224,4306,4274],{"class":3946},[224,4308,4309,4312,4314,4317],{"class":3942,"line":4098},[224,4310,4311],{"class":4019},"    path",[224,4313,3955],{"class":3954},[224,4315,4316],{"class":3958}," '../'",[224,4318,4292],{"class":3946},[224,4320,4321,4324,4326,4328],{"class":3942,"line":4108},[224,4322,4323],{"class":4019},"    publicPath",[224,4325,3955],{"class":3954},[224,4327,4316],{"class":3958},[224,4329,4292],{"class":3946},[224,4331,4332,4335,4337],{"class":3942,"line":4145},[224,4333,4334],{"class":4019},"    filename",[224,4336,3955],{"class":3954},[224,4338,4339],{"class":3958}," 'helloworld.min.js'\n",[224,4341,4342],{"class":3942,"line":4157},[224,4343,4344],{"class":3946},"  },\n",[224,4346,4348,4351,4353],{"class":3942,"line":4347},13,[224,4349,4350],{"class":4019},"  module",[224,4352,3955],{"class":3954},[224,4354,4274],{"class":3946},[224,4356,4358],{"class":3942,"line":4357},14,[224,4359,4360],{"class":4209},"    // `loaders` is an array of loaders to use.\n",[224,4362,4364],{"class":3942,"line":4363},15,[224,4365,4366],{"class":4209},"    // here we are only configuring vue-loader\n",[224,4368,4370,4373,4375],{"class":3942,"line":4369},16,[224,4371,4372],{"class":4019},"    loaders",[224,4374,3955],{"class":3954},[224,4376,4377],{"class":4019}," [\n",[224,4379,4381],{"class":3942,"line":4380},17,[224,4382,4383],{"class":3946},"      {\n",[224,4385,4387,4390,4392,4396,4399,4402,4404,4407],{"class":3942,"line":4386},18,[224,4388,4389],{"class":4019},"        test",[224,4391,3955],{"class":3954},[224,4393,4395],{"class":4394},"sNVtu"," /\\.",[224,4397,4398],{"class":3958},"vue",[224,4400,4401],{"class":4215},"$",[224,4403,4150],{"class":4394},[224,4405,4406],{"class":3946},",",[224,4408,4409],{"class":4209}," // a regex for matching all files that end in `.vue`\n",[224,4411,4413,4416,4418,4421],{"class":3942,"line":4412},19,[224,4414,4415],{"class":4019},"        loader",[224,4417,3955],{"class":3954},[224,4419,4420],{"class":3958}," 'vue-loader'",[224,4422,4423],{"class":4209},"   // loader to use for matched files\n",[224,4425,4427],{"class":3942,"line":4426},20,[224,4428,4429],{"class":3946},"      },\n",[224,4431,4433],{"class":3942,"line":4432},21,[224,4434,4383],{"class":3946},[224,4436,4438,4440,4442,4444,4447,4449,4451],{"class":3942,"line":4437},22,[224,4439,4389],{"class":4019},[224,4441,3955],{"class":3954},[224,4443,4395],{"class":4394},[224,4445,4446],{"class":3958},"js",[224,4448,4401],{"class":4215},[224,4450,4150],{"class":4394},[224,4452,4292],{"class":3946},[224,4454,4456,4458,4460,4463],{"class":3942,"line":4455},23,[224,4457,4415],{"class":4019},[224,4459,3955],{"class":3954},[224,4461,4462],{"class":3958}," 'babel-loader'",[224,4464,4292],{"class":3946},[224,4466,4468,4471,4473,4476,4479],{"class":3942,"line":4467},24,[224,4469,4470],{"class":4019},"        exclude",[224,4472,3955],{"class":3954},[224,4474,4475],{"class":4394}," /",[224,4477,4478],{"class":3958},"node_modules",[224,4480,4481],{"class":4394},"/\n",[224,4483,4485],{"class":3942,"line":4484},25,[224,4486,4429],{"class":3946},[224,4488,4490],{"class":3942,"line":4489},26,[224,4491,4383],{"class":3946},[224,4493,4495,4498,4500,4502,4505,4508,4511,4514,4516,4518],{"class":3942,"line":4494},27,[224,4496,4497],{"class":4019},"      test",[224,4499,3955],{"class":3954},[224,4501,4395],{"class":4394},[224,4503,4504],{"class":4051},"[",[224,4506,4507],{"class":3958},"sa|sc|c",[224,4509,4510],{"class":4051},"]",[224,4512,4513],{"class":3958},"ss",[224,4515,4401],{"class":4215},[224,4517,4150],{"class":4394},[224,4519,4292],{"class":3946},[224,4521,4523,4526,4528],{"class":3942,"line":4522},28,[224,4524,4525],{"class":4019},"      loader",[224,4527,3955],{"class":3954},[224,4529,4530],{"class":3958}," \"style!css!sass\"\n",[224,4532,4534,4537],{"class":3942,"line":4533},29,[224,4535,4536],{"class":3946},"      },",[224,4538,4274],{"class":3946},[224,4540,4542,4544,4546,4548,4551,4553,4556,4558,4561,4563,4566,4568,4571,4573,4576,4578,4581,4583,4586,4588,4591,4593,4595],{"class":3942,"line":4541},30,[224,4543,4389],{"class":4019},[224,4545,3955],{"class":3954},[224,4547,4395],{"class":4394},[224,4549,4550],{"class":3958},"(png",[224,4552,4136],{"class":3954},[224,4554,4555],{"class":3958},"jpg",[224,4557,4136],{"class":3954},[224,4559,4560],{"class":3958},"jpeg",[224,4562,4136],{"class":3954},[224,4564,4565],{"class":3958},"gif",[224,4567,4136],{"class":3954},[224,4569,4570],{"class":3958},"svg",[224,4572,4136],{"class":3954},[224,4574,4575],{"class":3958},"woff",[224,4577,4136],{"class":3954},[224,4579,4580],{"class":3958},"woff2",[224,4582,4136],{"class":3954},[224,4584,4585],{"class":3958},"ttf",[224,4587,4136],{"class":3954},[224,4589,4590],{"class":3958},"eot)",[224,4592,4401],{"class":4215},[224,4594,4150],{"class":4394},[224,4596,4292],{"class":3946},[224,4598,4600,4602,4604],{"class":3942,"line":4599},31,[224,4601,4415],{"class":4019},[224,4603,3955],{"class":3954},[224,4605,4606],{"class":3958}," 'file-loader?outputPath=../img/search/&publicPath=../img/search/'\n",[224,4608,4610],{"class":3942,"line":4609},32,[224,4611,4612],{"class":3946},"      }\n",[224,4614,4616,4619],{"class":3942,"line":4615},33,[224,4617,4618],{"class":4019},"    ]",[224,4620,4292],{"class":3946},[224,4622,4624,4627,4629,4631,4634,4637,4640,4642,4644,4646],{"class":3942,"line":4623},34,[224,4625,4626],{"class":4019},"    noParse",[224,4628,3955],{"class":3954},[224,4630,4475],{"class":4394},[224,4632,4633],{"class":3958},"dist",[224,4635,4636],{"class":4394},"\\/",[224,4638,4639],{"class":3958},"ol",[224,4641,554],{"class":4394},[224,4643,4446],{"class":3958},[224,4645,4150],{"class":4394},[224,4647,4292],{"class":3946},[224,4649,4651],{"class":3942,"line":4650},35,[224,4652,4344],{"class":3946},[224,4654,4656,4658,4660],{"class":3942,"line":4655},36,[224,4657,4398],{"class":4019},[224,4659,3955],{"class":3954},[224,4661,4274],{"class":3946},[224,4663,4665,4668,4670],{"class":3942,"line":4664},37,[224,4666,4667],{"class":4019},"  loaders",[224,4669,3955],{"class":3954},[224,4671,4274],{"class":3946},[224,4673,4675,4678,4680],{"class":3942,"line":4674},38,[224,4676,4677],{"class":4019},"    scss",[224,4679,3955],{"class":3954},[224,4681,4682],{"class":3958}," 'style!css!sass'\n",[224,4684,4686],{"class":3942,"line":4685},39,[224,4687,4688],{"class":3946},"  }},\n",[224,4690,4692],{"class":3942,"line":4691},40,[224,4693,4694],{"emptyLinePlaceholder":145},"\n",[224,4696,4698,4701,4703],{"class":3942,"line":4697},41,[224,4699,4700],{"class":4019},"  resolve",[224,4702,3955],{"class":3954},[224,4704,4274],{"class":3946},[224,4706,4708,4711,4713],{"class":3942,"line":4707},42,[224,4709,4710],{"class":4019},"    alias",[224,4712,3955],{"class":3954},[224,4714,4274],{"class":3946},[224,4716,4718,4721,4723],{"class":3942,"line":4717},43,[224,4719,4720],{"class":3958},"      'vue$'",[224,4722,3955],{"class":3954},[224,4724,4725],{"class":3958}," 'vue/dist/vue.common.js'\n",[224,4727,4729],{"class":3942,"line":4728},44,[224,4730,4731],{"class":3946},"    }\n",[224,4733,4735],{"class":3942,"line":4734},45,[224,4736,4344],{"class":3946},[224,4738,4740,4743,4745],{"class":3942,"line":4739},46,[224,4741,4742],{"class":4019},"  plugins",[224,4744,3955],{"class":3954},[224,4746,4377],{"class":4019},[224,4748,4750,4754,4757,4759,4762,4764,4767,4770],{"class":3942,"line":4749},47,[224,4751,4753],{"class":4752},"suuHZ","    new",[224,4755,4756],{"class":4019}," webpack",[224,4758,554],{"class":3954},[224,4760,4761],{"class":4019},"optimize",[224,4763,554],{"class":3954},[224,4765,4766],{"class":4224},"DedupePlugin",[224,4768,4769],{"class":4019},"()",[224,4771,4292],{"class":3946},[224,4773,4775,4777,4779,4781,4783,4785,4788,4790,4793,4796,4798,4802,4805],{"class":3942,"line":4774},48,[224,4776,4753],{"class":4752},[224,4778,4756],{"class":4019},[224,4780,554],{"class":3954},[224,4782,4761],{"class":4019},[224,4784,554],{"class":3954},[224,4786,4787],{"class":4224},"UglifyJsPlugin",[224,4789,4228],{"class":4019},[224,4791,4792],{"class":3946},"{",[224,4794,4795],{"class":4019},"minimize",[224,4797,3955],{"class":3954},[224,4799,4801],{"class":4800},"st0oN"," true",[224,4803,4804],{"class":3946},"}",[224,4806,4807],{"class":4019},")\n",[224,4809,4811],{"class":3942,"line":4810},49,[224,4812,4813],{"class":4019},"  ]\n",[224,4815,4817],{"class":3942,"line":4816},50,[224,4818,4694],{"emptyLinePlaceholder":145},[224,4820,4822],{"class":3942,"line":4821},51,[224,4823,4824],{"class":3946},"}\n",[11,4826,4827],{},"NOTE: adapt the paths to your specific needs. These are just examples, so feel free to modify them to whatever you like.",[11,4829,4830],{},"As you can see, we're telling webpack to compile our code, minimize it and put it in the right place that we want. Now, you can jump into your VueJS app.",[29,4832,3918],{"id":4833},"vuejs",[11,4835,4836],{},"We only use VueJS components. Thus, our example will be using a component that will render our data. The first element that we have to add is our entry point: helloworld.js",[2914,4838,4840],{"className":4200,"code":4839,"language":4202,"meta":49,"style":49},"import Vue from \"vue\"\nimport App from \"./components/App.vue\"\n\n\nVue.config.debug = true\nVue.config.devtools = true\n\nvar app = new Vue({\n    data() {\n        return {foo: 'all'}\n    },\n    el: '#vuejs',\n    components: { App },\n})\n",[1539,4841,4842,4856,4868,4872,4876,4896,4913,4917,4937,4946,4964,4969,4981,4995],{"__ignoreMap":49},[224,4843,4844,4847,4850,4853],{"class":3942,"line":3943},[224,4845,4846],{"class":4215},"import",[224,4848,4849],{"class":4019}," Vue ",[224,4851,4852],{"class":4215},"from",[224,4854,4855],{"class":3958}," \"vue\"\n",[224,4857,4858,4860,4863,4865],{"class":3942,"line":130},[224,4859,4846],{"class":4215},[224,4861,4862],{"class":4019}," App ",[224,4864,4852],{"class":4215},[224,4866,4867],{"class":3958}," \"./components/App.vue\"\n",[224,4869,4870],{"class":3942,"line":135},[224,4871,4694],{"emptyLinePlaceholder":145},[224,4873,4874],{"class":3942,"line":3982},[224,4875,4694],{"emptyLinePlaceholder":145},[224,4877,4878,4881,4883,4886,4888,4891,4893],{"class":3942,"line":3993},[224,4879,4880],{"class":4019},"Vue",[224,4882,554],{"class":3954},[224,4884,4885],{"class":4019},"config",[224,4887,554],{"class":3954},[224,4889,4890],{"class":4019},"debug ",[224,4892,4055],{"class":3954},[224,4894,4895],{"class":4800}," true\n",[224,4897,4898,4900,4902,4904,4906,4909,4911],{"class":3942,"line":4042},[224,4899,4880],{"class":4019},[224,4901,554],{"class":3954},[224,4903,4885],{"class":4019},[224,4905,554],{"class":3954},[224,4907,4908],{"class":4019},"devtools ",[224,4910,4055],{"class":3954},[224,4912,4895],{"class":4800},[224,4914,4915],{"class":3942,"line":4072},[224,4916,4694],{"emptyLinePlaceholder":145},[224,4918,4919,4921,4924,4926,4929,4932,4934],{"class":3942,"line":4088},[224,4920,4216],{"class":4215},[224,4922,4923],{"class":4019}," app ",[224,4925,4055],{"class":3954},[224,4927,4928],{"class":4752}," new",[224,4930,4931],{"class":4224}," Vue",[224,4933,4228],{"class":4019},[224,4935,4936],{"class":3946},"{\n",[224,4938,4939,4942,4944],{"class":3942,"line":4098},[224,4940,4941],{"class":4224},"    data",[224,4943,4769],{"class":3946},[224,4945,4274],{"class":3946},[224,4947,4948,4951,4954,4957,4959,4962],{"class":3942,"line":4108},[224,4949,4950],{"class":4215},"        return",[224,4952,4953],{"class":3946}," {",[224,4955,4956],{"class":4019},"foo",[224,4958,3955],{"class":3954},[224,4960,4961],{"class":3958}," 'all'",[224,4963,4824],{"class":3946},[224,4965,4966],{"class":3942,"line":4145},[224,4967,4968],{"class":3946},"    },\n",[224,4970,4971,4974,4976,4979],{"class":3942,"line":4157},[224,4972,4973],{"class":4019},"    el",[224,4975,3955],{"class":3954},[224,4977,4978],{"class":3958}," '#vuejs'",[224,4980,4292],{"class":3946},[224,4982,4983,4986,4988,4990,4992],{"class":3942,"line":4347},[224,4984,4985],{"class":4019},"    components",[224,4987,3955],{"class":3954},[224,4989,4953],{"class":3946},[224,4991,4862],{"class":4019},[224,4993,4994],{"class":3946},"},\n",[224,4996,4997,4999],{"class":3942,"line":4357},[224,4998,4804],{"class":3946},[224,5000,4807],{"class":4019},[11,5002,5003],{},"Then, create a components folder and create a file named App.vue:",[2914,5005,5007],{"className":4200,"code":5006,"language":4202,"meta":49,"style":49},"\u003Ctemplate>\n    \u003Ch1 v-for=\"datum in mydata\">{{datum.title}}\u003C/h1>\n\u003C/template>\n\u003Cscript>\nexport default {\n   data() {\n      return {mydata: window.mydata}\n},\n// your stuff\n}\n\u003C/script>\n\u003Cstyle>\n\u003C/style>\n",[1539,5008,5009,5018,5049,5057,5065,5072,5082,5103,5107,5112,5116,5124,5133],{"__ignoreMap":49},[224,5010,5011,5013,5016],{"class":3942,"line":3943},[224,5012,4045],{"class":3954},[224,5014,5015],{"class":3950},"template",[224,5017,4069],{"class":3954},[224,5019,5020,5022,5024,5027,5029,5032,5034,5037,5040,5043,5045,5047],{"class":3942,"line":130},[224,5021,4075],{"class":3954},[224,5023,2643],{"class":3950},[224,5025,5026],{"class":4051}," v-for",[224,5028,4055],{"class":3954},[224,5030,5031],{"class":3958},"\"datum in mydata\"",[224,5033,4172],{"class":3954},[224,5035,5036],{"class":3946},"{{",[224,5038,5039],{"class":4019},"datum.title",[224,5041,5042],{"class":3946},"}}",[224,5044,4091],{"class":3954},[224,5046,2643],{"class":3950},[224,5048,4069],{"class":3954},[224,5050,5051,5053,5055],{"class":3942,"line":135},[224,5052,4091],{"class":3954},[224,5054,5015],{"class":3950},[224,5056,4069],{"class":3954},[224,5058,5059,5061,5063],{"class":3942,"line":3982},[224,5060,4045],{"class":3954},[224,5062,4103],{"class":3950},[224,5064,4069],{"class":3954},[224,5066,5067,5070],{"class":3942,"line":3993},[224,5068,5069],{"class":4019},"export default ",[224,5071,4936],{"class":3946},[224,5073,5074,5077,5080],{"class":3942,"line":4042},[224,5075,5076],{"class":4224},"   data",[224,5078,5079],{"class":4019},"() ",[224,5081,4936],{"class":3946},[224,5083,5084,5087,5089,5092,5094,5097,5099,5101],{"class":3942,"line":4072},[224,5085,5086],{"class":4019},"      return ",[224,5088,4792],{"class":3946},[224,5090,5091],{"class":4019},"mydata",[224,5093,3955],{"class":3946},[224,5095,5096],{"class":4019}," window",[224,5098,554],{"class":3954},[224,5100,5091],{"class":4019},[224,5102,4824],{"class":3946},[224,5104,5105],{"class":3942,"line":4088},[224,5106,4994],{"class":3946},[224,5108,5109],{"class":3942,"line":4098},[224,5110,5111],{"class":4209},"// your stuff\n",[224,5113,5114],{"class":3942,"line":4108},[224,5115,4824],{"class":3946},[224,5117,5118,5120,5122],{"class":3942,"line":4145},[224,5119,4091],{"class":3954},[224,5121,4103],{"class":3950},[224,5123,4069],{"class":3954},[224,5125,5126,5128,5131],{"class":3942,"line":4157},[224,5127,4045],{"class":3954},[224,5129,5130],{"class":3950},"style",[224,5132,4069],{"class":3954},[224,5134,5135,5137,5139],{"class":3942,"line":4347},[224,5136,4091],{"class":3954},[224,5138,5130],{"class":3950},[224,5140,4069],{"class":3954},[11,5142,5143],{},"Done! Now you are loading your data created in mydata.yml file into your VueJS app. Now you are free to do whatever you want, as you are in the field of VueJS. Enjoy!",[11,5145,5146,5149],{},[510,5147,5148],{},"NOTE",": Jekyll sometimes does not recompile the _data folder, so you will need to re-run it to be sure that your data is updated.",[29,5151,5153],{"id":5152},"bulma-and-buefy","Bulma and Buefy",[11,5155,5156],{},"We use SaSS to style our Jekyll sites; I guess you do it too. If this is the case, you don't want to have separate sass folders to build your website and your VueJS apps. You can solve it by instructing your VueJS to re-use the Bulma CSS framework. How? Like this:",[2914,5158,5161],{"className":5159,"code":5160,"language":2919},[2917],"\u003Cstyle lang=\"scss\">\n@import \"../../../_sass/_scifabric.scss\";\n@import \"~buefy/src/scss/buefy\";\n\n// your SCSS\n\u003C/style>\n",[1539,5162,5160],{"__ignoreMap":49},[15,5164,5166],{"id":5165},"cavebeats","Cavebeats",[11,5168,5169,5170,5173,5174,5178],{},"While this is an excellent ",[510,5171,5172],{},"hack"," it's not the best solution. It would be much much better to use only a static website generator built with Node.JS or just something like ",[37,5175,5177],{"href":3137,"rel":5176},[41],"nuxt.js",", but we needed to re-use our Jekyll infrastructure and therefore the hack.",[11,5180,5181],{},"In any case, this hack has space for improvement. The most noticeable one would be to not include the CSS from Jekyll where we only use VueJS to avoid downloading the same stuff twice. If you like it, let us know and share this article with your colleagues and friends!",[29,5183,5185],{"id":5184},"final-notes","Final notes",[11,5187,5188,5189,5192],{},"This was originally posted in our ",[37,5190,953],{"href":951,"rel":5191},[41]," site.",[5130,5194,5195],{},"html pre.shiki code .sxyLT, html code.shiki .sxyLT{--shiki-default:#7C7F93;--shiki-dark:#9399B2}html pre.shiki code .sS0zD, html code.shiki .sS0zD{--shiki-default:#1E66F5;--shiki-dark:#89B4FA}html pre.shiki code .sjJjI, html code.shiki .sjJjI{--shiki-default:#179299;--shiki-dark:#94E2D5}html pre.shiki code .sgueU, html code.shiki .sgueU{--shiki-default:#40A02B;--shiki-dark:#A6E3A1}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s0aCy, html code.shiki .s0aCy{--shiki-default:#4C4F69;--shiki-dark:#CDD6F4}html pre.shiki code .sObzt, html code.shiki .sObzt{--shiki-default:#DF8E1D;--shiki-dark:#F9E2AF}html pre.shiki code .som-u, html code.shiki .som-u{--shiki-default:#7C7F93;--shiki-default-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic}html pre.shiki code .sAS4m, html code.shiki .sAS4m{--shiki-default:#8839EF;--shiki-dark:#CBA6F7}html pre.shiki code .sMmZK, html code.shiki .sMmZK{--shiki-default:#1E66F5;--shiki-default-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic}html pre.shiki code .sUlWy, html code.shiki .sUlWy{--shiki-default:#8839EF;--shiki-default-font-style:italic;--shiki-dark:#CBA6F7;--shiki-dark-font-style:italic}html pre.shiki code .sNVtu, html code.shiki .sNVtu{--shiki-default:#EA76CB;--shiki-dark:#F5C2E7}html pre.shiki code .suuHZ, html code.shiki .suuHZ{--shiki-default:#8839EF;--shiki-default-font-weight:bold;--shiki-dark:#CBA6F7;--shiki-dark-font-weight:bold}html pre.shiki code .st0oN, html code.shiki .st0oN{--shiki-default:#FE640B;--shiki-dark:#FAB387}",{"title":49,"searchDepth":130,"depth":130,"links":5197},[5198,5199,5204],{"id":3909,"depth":130,"text":3910},{"id":4189,"depth":130,"text":4190,"children":5200},[5201,5202,5203],{"id":4196,"depth":135,"text":4197},{"id":4833,"depth":135,"text":3918},{"id":5152,"depth":135,"text":5153},{"id":5165,"depth":130,"text":5166,"children":5205},[5206],{"id":5184,"depth":135,"text":5185},"2017-10-13T00:00:00.000Z","Hacking with Jekyll, VueJS & Bulma","Luca Bravo",{},"/blog/en/2017-10-13-jekyll-vuejs-bulma",{"title":3887,"description":5208},"jekyll-vuejs-bulma","blog/en/2017-10-13-jekyll-vuejs-bulma","jekyll, hacking, vuejs, bulma, frontend","75hny1ifNeKgGfJkGc1BaUSPw5tkIGtYSv6BAattz5U",{"id":5218,"title":5219,"author":141,"body":5220,"date":5796,"description":5797,"extension":140,"headline":5798,"icon":5799,"icon_author":5800,"icon_url":5801,"layout":143,"location":141,"meta":5802,"meta_description":5798,"navigation":145,"path":5803,"quote":141,"seo":5804,"slug":5805,"stem":5806,"tags":5807,"template":141,"__hash__":5808},"blog/blog/en/2016-02-09-atomic-force-microscope.md","The DIY atomic force microscope",{"type":8,"value":5221,"toc":5788},[5222,5231,5247,5258,5268,5271,5275,5278,5303,5306,5321,5327,5336,5343,5349,5356,5363,5368,5375,5379,5382,5391,5411,5432,5438,5441,5462,5471,5477,5484,5528,5532,5541,5544,5547,5550,5559,5591,5599,5608,5611,5615,5618,5621,5630,5633,5636,5639,5643,5652,5668,5676,5685,5694,5702,5711,5729,5738,5761,5765,5768,5771,5774,5777,5785],[11,5223,5224,5225,5230],{},"Here's a question: what image would you choose to represent 'science'? If you search 'science' in ",[37,5226,5229],{"href":5227,"rel":5228},"https://www.google.com/search?q=science&biw=1535&bih=764&source=lnms&tbm=isch&sa=X&ved=0ahUKEwio_bbKoO3KAhVIVxQKHbgjCGkQ_AUIBygC",[41],"Google Images",",\nyou'll see a fair few images of microscopes. The microscope is a tool that people widely associate with science and research. But how did this happen? Why did the microscope become so popular?",[11,5232,5233,5234,5242,5243,5246],{},"Well, it became popular thanks to Robert Hooke's book ",[37,5235,5238,5241],{"href":5236,"rel":5237},"https://en.wikipedia.org/wiki/Micrographia",[41],[510,5239,5240],{},"Micro","graphia (1665)",".\nThis book marked a milestone in scientific history. It showed the science community how to use microscopes to analyze and study the ",[510,5244,5245],{},"micro"," world, with hand made drawings of cells, fleas and insects.",[11,5248,5249,5250,5253,5254,5257],{},"Now, 351 years later, we might be experiencing another profound turning point in science. And I've though of a title for the associated book: ",[510,5251,5252],{},"Nano","graphia!\nThe popularization of low cost, do-it-yourself atomic force microscopes will allow us to explore the ",[510,5255,5256],{},"nano"," world. But, how did we get here? How old is the microscope? Let's start... from the beginning.",[2889,5259,3843,5263],{"className":5260},[5261,5262],"embed-responsive","embed-responsive-16by9",[2893,5264],{"src":5265,"width":427,"height":5266,"frameBorder":2897,"className":5267,"allowFullScreen":145},"https://giphy.com/embed/1unWthRtNnzkA","auto",[2899],[11,5269,5270],{},"Indeed! It's a long story, but worth it. Bear with me.",[15,5272,5274],{"id":5273},"the-early-years-of-the-microscope","The early years of the microscope",[11,5276,5277],{},"Evidence suggests that the first compound microscope was built in the Netherlands in 1620. Almost 400 years ago!",[11,5279,5280,5281,5286,5287,5292,5293,5296,5297,5302],{},"But at this point, the microscope didn't have a name. Huh!\nWe had to wait another 5 years before it was named.\nIn 1625 ",[37,5282,5285],{"href":5283,"rel":5284},"https://en.wikipedia.org/wiki/Giovanni_Faber",[41],"Giovanni Faber"," – a fellow of the ",[37,5288,5291],{"href":5289,"rel":5290},"https://en.wikipedia.org/wiki/Accademia_dei_Lincei",[41],"Lincean Academy"," - coined the name ",[247,5294,5295],{},"microscope",", after ",[37,5298,5301],{"href":5299,"rel":5300},"https://en.wikipedia.org/wiki/Galileo_Galilei",[41],"Galileo Galilei"," presented it one year before.\nThe name comes from the Greek words μικρόν (micron) meaning \"small\", and σκοπεῖν (skopein) meaning \"to look at\".",[11,5304,5305],{},"So we know when it was named, but when did it become a popular instrument? Well, guess what, another 40 years elapsed before the microscope becomes a popular tool used in science.",[11,5307,5308,5309,5314,5315,5320],{},"As noted, in 1665 ",[37,5310,5313],{"href":5311,"rel":5312},"https://en.wikipedia.org/wiki/Robert_Hooke",[41],"Robert Hooke"," published ",[37,5316,5319],{"href":5317,"rel":5318},"https://ia800504.us.archive.org/5/items/mobot31753000817897/mobot31753000817897.pdf",[41],"Micrographia (PDF)"," – a book that inspired the use of microscopes for scientific exploration. The details and quality of his hand made drawings of insects and plant cells (engraved in copper plates) popularized his work. Check out the following images!",[11,5322,5323],{},[47,5324],{"alt":5325,"src":5326},"Hooke's microscope","/img/blog/Hooke-microscope.png",[11,5328,5331,5332,554],{"className":5329},[5330],"post-caption","Hooke's microscope, from an engraving in Micrographia. Photo by ",[37,5333,5335],{"href":5334},"https://en.wikipedia.org/wiki/Robert_Hooke#/media/File:Hooke-microscope.png","Wikipedia",[11,5337,5338,5339,5342],{},"The engravings were very detailed, but ",[247,5340,5341],{},"the most awesome feature was that you could unfold them, making them larger than the book itself, reinforcing the tremendous power of the microscope",". For example, see this flea:",[11,5344,5345],{},[47,5346],{"alt":5347,"src":5348},"Cork cells","/img/blog/HookeFlea01.jpg",[11,5350,5352,5353,554],{"className":5351},[5330],"Hooke's drawing of a flea. Photo by ",[37,5354,5335],{"href":5355},"https://en.wikipedia.org/wiki/Robert_Hooke#/media/File:HookeFlea01.jpg",[11,5357,5358,5359,5362],{},"While these achievements are amazing, you might better know Hooke as the person who coined the term ",[247,5360,5361],{},"cell",", as the small structures he observed in a cork sample reminded him of honeycomb cells.",[11,5364,5365],{},[47,5366],{"alt":5347,"src":5367},"/img/blog/cork.jpg",[11,5369,5371,5372,554],{"className":5370},[5330],"Cell structure of Cork by Hooke. Photo by ",[37,5373,5335],{"href":5374},"https://en.wikipedia.org/wiki/Robert_Hooke#/media/File:RobertHookeMicrographia1665.jpg",[15,5376,5378],{"id":5377},"the-microscope-becomes-a-scientific-tool","The microscope becomes a scientific tool",[11,5380,5381],{},"We know when the microscope was invented, when it was named and when it became popular. Now, it's time to learn about its impact in the scientific world (and TV shows!).",[2889,5383,3843,5385],{"className":5384},[5261,5262],[2893,5386],{"src":5387,"width":5388,"height":5389,"frameBorder":2897,"className":5390,"allowFullScreen":145},"https://giphy.com/embed/Fbyam9ZAJ3J1m",480,270,[2899],[11,5392,5393,5394,5399,5400,5405,5406,554],{},"In the years after Hooke's publication, the microscope was widely used in Italy, the Netherlands and England. The greatest contribution in this period came from ",[37,5395,5398],{"href":5396,"rel":5397},"https://en.wikipedia.org/wiki/Antonie_van_Leeuwenhoek",[41],"Antonie van Leeuwenhoek"," who\nhas been credited with the discoverery of red blood cells and, consequently, helping to popularize ",[37,5401,5404],{"href":5402,"rel":5403},"https://en.wikipedia.org/wiki/Microscopy",[41],"microscopy"," as a technique. On 1676,\nVan Leeuwenhoek reported ",[37,5407,5410],{"href":5408,"rel":5409},"https://en.wikipedia.org/wiki/Microorganism#History_of_microorganisms.27_discovery",[41],"the discovery of micro-organisms",[11,5412,5413,5420,5421,1112,5426,5431],{},[510,5414,5415],{},[37,5416,5419],{"href":5417,"rel":5418},"http://www.med-ed.virginia.edu/courses/cell/resources/blooddisc.htm",[41],"Side note",":  In truth, Van Leeuwenhoek was not the first person to describe \"red particles\" in blood. However, his observations were more detailed and numerous than his predecessors (",[37,5422,5425],{"href":5423,"rel":5424},"https://en.wikipedia.org/wiki/Marcello_Malpighi",[41],"Malpighi",[37,5427,5430],{"href":5428,"rel":5429},"https://en.wikipedia.org/wiki/Jan_Swammerdam",[41],"Swammerdam",").",[11,5433,5434,5435,554],{},"While microscopes became widely used, they faced a problem: ",[247,5436,5437],{},"how to light the samples",[11,5439,5440],{},"Lighting is key in microscopy in order to see the sample properly, so it was not  until electric lamps were available as light sources that new advances and  discoveries were made.",[11,5442,5443,5444,5449,5450,5455,5456,5461],{},"After improving the lighting, scientists started to question the limits of this technology. What's the smallest thing that you can see with it? To answer this question ",[37,5445,5448],{"href":5446,"rel":5447},"https://en.wikipedia.org/wiki/August_K%C3%B6hler",[41],"August Köhler"," developed the ",[37,5451,5454],{"href":5452,"rel":5453},"https://en.wikipedia.org/wiki/K%C3%B6hler_illumination",[41],"Köhler illumination"," principle, which is central to achieving the theoretical ",[37,5457,5460],{"href":5458,"rel":5459},"https://en.wikipedia.org/wiki/Microscopy#Limitations",[41],"limits of light microscopy",".  This was 1893.",[11,5463,5464,5465,5470],{},"Knowing microscopy's limits, the pursuit of further knowledge pushed scientists to use electrons instead of light, and electromagnets in the  place of glass lenses, creating the first electron microscope: the ",[37,5466,5469],{"href":5467,"rel":5468},"https://en.wikipedia.org/wiki/Transmission_electron_microscopy",[41],"transmission electron microscope",". This was 1931.",[11,5472,5473],{},[47,5474],{"alt":5475,"src":5476},"Polio virus image","/img/blog/polio.png",[11,5478,5480,5481,554],{"className":5479},[5330],"A TEM image of the polio virus. The polio virus is 30 nm in size. Photo by ",[37,5482,5335],{"href":5483},"https://en.wikipedia.org/wiki/Transmission_electron_microscopy#/media/File:Polio_EM_PHIL_1875_lores.PNG",[11,5485,5486,5487,554,5492,5495,5496,5501,5502,1112,5507,5512,5513,1112,5518,5523,5524,5527],{},"Other researchers tried different techniques. For example, in the 1980s some scientists started the development of the first ",[37,5488,5491],{"href":5489,"rel":5490},"https://en.wikipedia.org/wiki/Scanning_probe_microscopy",[41],"scanning probe microscopes",[5493,5494],"br",{},"\nThe first one was the ",[37,5497,5500],{"href":5498,"rel":5499},"https://en.wikipedia.org/wiki/Scanning_tunneling_microscope",[41],"scanning tunneling microscope"," developed by ",[37,5503,5506],{"href":5504,"rel":5505},"https://en.wikipedia.org/wiki/Gerd_Binnig",[41],"Gerd Binning",[37,5508,5511],{"href":5509,"rel":5510},"https://en.wikipedia.org/wiki/Heinrich_Rohrer",[41],"Heinrich Rohrer"," (1981). Five years later Gerd Binning, ",[37,5514,5517],{"href":5515,"rel":5516},"https://en.wikipedia.org/wiki/Calvin_Quate",[41],"Quate",[37,5519,5522],{"href":5520,"rel":5521},"https://en.wikipedia.org/wiki/Christoph_Gerber",[41],"Gerber"," invented the ",[510,5525,5526],{},"atomic force microscope"," (AFM).",[15,5529,5531],{"id":5530},"atomic-force-microscope-afm","Atomic Force Microscope (AFM)",[11,5533,5534,5535,5540],{},"The AFM is a big step forward because it improves the quality of the images and  gives us access to the nano world. An optical microscope is limited by the wavelength of light it can detect. This is called the",[37,5536,5539],{"href":5537,"rel":5538},"https://en.wikipedia.org/wiki/Diffraction-limited_system",[41],"Abbe limit",", which is around 250 nm (0.25 μm).",[11,5542,5543],{},"While this resolution allows us to see most biological cells (1 μm to 100 μm), it fails if you try to study viruses (100 nm), proteins (10 nm) or less complex molecules (1 nm). On the other hand, the AFM has a demonstrated resolution in the order of fractions of a nanometer, more than 1000 times better than the optical diffraction (Abbe) limit.",[11,5545,5546],{},"While these microscopes are amazing, they're really expensive too. One will set you back around 300,000 USD.",[11,5548,5549],{},"This basically becomes a huge problem to educators, well, to anyone, as not many Institutions often do not have the cash to buy this research tool.",[2889,5551,5554],{"className":5552},[5261,5553],"embed-responsive-4by3",[2893,5555],{"src":5556,"width":5388,"height":5557,"frameBorder":2897,"className":5558,"allowFullScreen":145},"https://giphy.com/embed/5u0uZecUZlUsM",327,[2899],[11,5560,5561,5562,5567,5568,5572,5573,5578,5579,5584,5585,5590],{},"With this problem in mind, in 2015 the ",[37,5563,5566],{"href":5564,"rel":5565},"http://www.legofoundation.com/",[41],"LEGO Foundation"," sponsored a summer school program to develop an affordable do-it-yourself (DIY) atomic force microscope suitable for use in schools by children. The ",[37,5569,3617],{"href":5570,"rel":5571},"https://www.nature.com/nnano/journal/v10/n5/full/nnano.2015.95.html",[41]," has been an ",[37,5574,5577],{"href":5575,"rel":5576},"http://openafm.com/",[41],"open source AFM"," that children can build using LEGO pieces, Arduino, 3D printable parts and local components.\nAt the same time, ",[37,5580,5583],{"href":5581,"rel":5582},"http://www.phys.sinica.edu.tw/directory_user_en.php?id_key=94&eng=T",[41],"Edwin Hwu"," and his team (who are also developing an open AFM) licensed a low cost closed-source version, ",[37,5586,5589],{"href":5587,"rel":5588},"http://www.stromlinet-nano.com/",[41],"the Strømlingo DIY AFM",", which costs 98% less than the ones available on the market.\nThese big savings make AFM affordable, enabling institutions to buy cheap AFM microscopes that their students can build themselves. Moreover, this building process only takes a few hours and the kids can start operating it in a matter of minutes.",[2889,5592,5594],{"className":5593},[5261,5553],[2893,5595],{"src":5596,"width":5388,"height":5597,"frameBorder":2897,"className":5598,"allowFullScreen":145},"https://giphy.com/embed/LgwoVr7YgUkrC",342,[2899],[11,5600,5601,5602,5607],{},"Due to this success, students will be able to see nano structures that would otherwise be impossible to view with a regular microscope, such as particles with an ",[37,5603,5606],{"href":5604,"rel":5605},"http://www3.epa.gov/pmdesignations/faq.htm",[41],"aerodynamic diameter of 2.5 micrometers or less"," (known as PM 2.5). Why are these particles particularly important? Well, because they're among the most harmful for human health as they are small enough to penetrate deeply in the lungs and may even cross into the blood. Scary, right?",[11,5609,5610],{},"Edwin and his students have shown how affordable nanoscopes can be used to analyze and take samples of these particles and, indeed,  schools all over the world have participated in his projects.",[15,5612,5614],{"id":5613},"nanographia-the-drawings-of-pm-25","Nanographia, the drawings of PM 2.5",[11,5616,5617],{},"As Robert Hooke's book Micrographia popularized microscopes, the low cost DIY nanoscope will enable kids and anyone with interest in this field to write the next book that will popularize this new type of microscope. If Micrographia was a milestone due to new discoveries in the micro world, affordable do-it-yourself nanoscopes will help to write the book that will make history again: Nanographia.",[11,5619,5620],{},"The book will describe how you can build the nanoscope and how you can use it for studying  PM 2.5 particles. Instead of drawings, the book will feature photos showing the discoveries. As you can see, Nanographia will help to spread the word about this technology, as Hooke did almost 400 years ago.",[11,5622,5623,5624,5629],{},"As with any other scientific publication, there will be a subject to be studied: the PM2.5 particles. A chapter might explain what PM2.5 particles are, as well as how you can make ",[37,5625,5628],{"href":5626,"rel":5627},"https://en.wikipedia.org/wiki/Microscope_slide",[41],"microscope sample slides"," by cutting up DVD ROMs and placing them outside for at least 10 minutes.",[11,5631,5632],{},"Why are we going to use DVDs? Because the distance between the tracks in a DVD are known (740 nanometers) and we can see them with the AFM.",[11,5634,5635],{},"The next chapter will be about the analysis. Once you have the samples, it will describe how you can analyze them by hand: calibrating the samples and measuring the area covered by the candidate PM2.5 particles.",[11,5637,5638],{},"Incredible right? As we discovered this story, we wanted to contribute a few chapters for the book. One about crowdsourcing as we think it would be amazing for the crowd to analyze samples (following the citizen science approach of this project), and a second one running workshops about the project where you can learn, build the nanoscope, and analyze the samples with the crowd.",[15,5640,5642],{"id":5641},"scifabrics-chapters-for-nanographia","SciFabric's chapters for Nanographia",[11,5644,5645,5646,5651],{},"Our desire to contribute to this book became a reality when  Edwin and his team contacted us to use our citizen science ",[37,5647,5650],{"href":5648,"rel":5649},"https://web.archive.org/web/2019/http://crowdcrafting.org",[41],"Crowdcrafting","  platform for analyzing the samples with the crowd.",[11,5653,5654,5655,554,5660,5662,5663,554],{},"This first chapter will be about citizen science, and it will describe what is ",[37,5656,5659],{"href":5657,"rel":5658},"https://scifabric.com/blog/2016/01/27/crowdsourcing-vs-crowdfunding.html",[41],"crowdsourcing and citizen science",[5493,5661],{},"\nIt will explain the project where anyone can analyze samples, including links to the  ",[37,5664,5667],{"href":5665,"rel":5666},"https://web.archive.org/web/2019/http://crowdcrafting.org/project/lego2nano/",[41],"prototype",[11,5669,5670,5671,5675],{},"Also, there will be a sub-section where we will describe the ",[37,5672,5674],{"href":3125,"rel":5673},[41],"tools that we use for building the prototype",", so others can replicate it (like science does!).",[11,5677,5678,5679,5684],{},"The next chapter will be about citizen science workshops, as ",[37,5680,5683],{"href":5681,"rel":5682},"https://scifabric.com/crowdsourcing/#education",[41],"we offer them to students and teachers"," as a new way to discover science and learn by doing. The chapter will include a new course on how you can build the nanoscope, use its technology and learn the citizen science approach.",[11,5686,5687,5688,5693],{},"In November 2015 we wrote the first draft. We proposed that ",[37,5689,5692],{"href":5690,"rel":5691},"https://medialab-prado.es/",[41],"Medialab-Prado"," (Madrid, Spain) organize an event like this, and they accepted.",[2889,5695,5697],{"className":5696},[5261,5262],[2893,5698],{"src":5699,"width":5388,"height":5700,"frameBorder":2897,"className":5701,"allowFullScreen":145},"https://giphy.com/embed/11sBLVxNs7v6WA",216,[2899],[11,5703,5704,5705,5710],{},"The workshop became popular and Spanish national TV show ",[37,5706,5709],{"href":5707,"rel":5708},"https://www.rtve.es/television/la-aventura-del-saber/",[41],"La aventura del saber"," (the adventure of knowing) interviewed us, showing how we built the microscope and analyzed some of the samples (it starts at minute 14:00, only in Spanish):",[2889,5712,5714,5718],{"className":5713},[5261,5262],[2893,5715],{"frameBorder":2897,"src":5716,"name":5717,"scrolling":3848,"style":3849},"https://www.rtve.es/drmn/embed/video/3468356","La aventura del saber - 02/02/16",[2889,5719,5720,1592,5724],{"style":3852},[224,5721,5722],{"style":3856},[47,5723],{"style":3860,"src":3861},[37,5725,5727],{"style":3865,"title":5717,"href":5726},"https://www.rtve.es/alacarta/videos/la-aventura-del-saber/aventura-del-saber-02-02-16/3468356/",[510,5728,5717],{},[11,5730,5731,5732,5737],{},"Due to the success of the workshop, we were invited by ",[37,5733,5736],{"href":5734,"rel":5735},"https://medialab-prado.es/article/festilab-1-ano-en-un-dia",[41],"Medialab-Prado to share what we built at their open day event",". In the following video you can see me talking about the project (in Spanish):",[2889,5739,5741,5746],{"className":5740},[5261,5262],[2893,5742],{"src":5743,"width":5744,"height":5745,"frameBorder":2897,"webkitallowfullscreen":49,"mozallowfullscreen":49,"allowFullScreen":145},"https://player.vimeo.com/video/154714664",500,281,[11,5747,5748,5752,5753,5756,5757,554],{},[37,5749,5751],{"href":5750},"https://vimeo.com/154714664","Microscópio de fuerza atómica"," from ",[37,5754,5692],{"href":5755},"https://vimeo.com/medprado"," on ",[37,5758,5760],{"href":5759},"https://vimeo.com","Vimeo",[15,5762,5764],{"id":5763},"the-final-chapter","The final chapter",[11,5766,5767],{},"We've seen the evolution of microscopes and how human pursuit of knowledge has got  us here today. Nowadays we can build nanoscopes at home and explore the nano world in a few hours. The possibilities are endless, but are nanoscopes the new edition of Micrographia? Are nanoscopes making history?",[11,5769,5770],{},"Well, I would say it's early to know, but the truth is that it has lots of potential.",[11,5772,5773],{},"I can barely imagine how kids will be building and using this tool trying to understand what lies in the nano world, and the best part is that we're exploring it together!",[11,5775,5776],{},"By the way: High Five! You are awesome! You just read until here, so cool!",[2889,5778,5780],{"className":5779},[5261,5262],[2893,5781],{"src":5782,"width":5388,"height":5783,"frameBorder":2897,"className":5784,"allowFullScreen":145},"https://giphy.com/embed/CDMz3fckRXXDG",269,[2899],[11,5786,5787],{},"Now, get away from your laptop, tablet or phone and enjoy a beer, coffee, whatever you like. It's been a long read and you deserve it!",{"title":49,"searchDepth":130,"depth":130,"links":5789},[5790,5791,5792,5793,5794,5795],{"id":5273,"depth":130,"text":5274},{"id":5377,"depth":130,"text":5378},{"id":5530,"depth":130,"text":5531},{"id":5613,"depth":130,"text":5614},{"id":5641,"depth":130,"text":5642},{"id":5763,"depth":130,"text":5764},"2016-02-09T00:00:00.000Z","Here's a question: what image would you choose to represent 'science'? If you search 'science' in Google Images,\nyou'll see a fair few images of microscopes. The microscope is a tool that people widely associate with science and research. But how did this happen? Why did the microscope become so popular?","Build an atomic force microscope in less than 2 hours!","cottoncell","Project-128","https://www.flickr.com/photos/project-128/11612131236/",{},"/blog/en/2016-02-09-atomic-force-microscope",{"title":5219,"description":5797},"atomic-force-microscope","blog/en/2016-02-09-atomic-force-microscope","Crowdcrafting, thesis, phd, hardware, maker","qGGy_ivu4NXA2weGirYZLc-3yJNXmscoKSSAU3c7XIY",{"id":5810,"title":3643,"author":6,"body":5811,"date":6312,"description":6313,"extension":140,"headline":141,"icon":6314,"icon_author":6315,"icon_url":6316,"layout":143,"location":141,"meta":6317,"meta_description":141,"navigation":145,"path":6318,"quote":2875,"seo":6319,"slug":6320,"stem":6321,"tags":6322,"template":141,"__hash__":6323},"blog/blog/en/2015-12-22-year-in-review.md",{"type":8,"value":5812,"toc":6291},[5813,5816,5819,5836,5849,5853,5856,5867,5879,5886,5899,5903,5924,5937,5940,5944,5947,5955,5968,5972,5979,5983,5990,5998,6015,6018,6022,6025,6036,6040,6049,6053,6061,6064,6089,6093,6101,6104,6112,6116,6128,6148,6156,6160,6169,6175,6179,6198,6210,6213,6217,6226,6234,6243,6247,6261,6270,6277,6281,6288],[11,5814,5815],{},"Wow, another year is almost over! Time flies and, like everyone else, we love to\nreflect on our achievements over the past 12 months...",[15,5817,5818],{"id":3716},"PyBossa",[11,5820,5821,5822,1319,5828,5831,5832,5835],{},"As you know, or at least should know ",[5823,5824],"i",{"className":5825},[5826,5827],"twa","twa-smile",[37,5829,5818],{"href":3125,"rel":5830},[41]," is the king of our products.\nIt lets you ",[247,5833,5834],{},"build your own research platform"," in just a few easy steps. This year, we've\nintroduced some cool new features so you'll be able to do more\nwith less hacking. (Don't worry developers, we've created amazing tools for\nyou too... read on!)",[2889,5837,428,5839,5844,428],{"className":5838},[5261,5262],[2893,5840],{"className":5841,"src":5843,"frameBorder":2897,"allowFullScreen":145},[5842],"embed-responsive-item","https://giphy.com/embed/oKVs1VY0MKfvO",[11,5845,5846],{},[37,5847],{"href":5848},"https://giphy.com/gifs/nervous-indiana-jones-waiting-oKVs1VY0MKfvO",[29,5850,5852],{"id":5851},"third-party-integrations","Third Party Integrations",[11,5854,5855],{},"We know that data can be stored in different places. We've therefore introduced three new integrations\nto PyBossa:",[565,5857,5858,5861,5864],{},[568,5859,5860],{},"Flickr",[568,5862,5863],{},"Dropbox",[568,5865,5866],{},"Twitter",[11,5868,5869,5872,5873,5878],{},[510,5870,5871],{},"You can now import any album from Flickr",", or log in with your Flickr account and select the album\nyou want to import. As simple as that. This feature is pretty handy for galleries, libraries, archives\nand museums (GLAM) as they usually have tons of pictures on ",[37,5874,5877],{"href":5875,"rel":5876},"https://www.flickr.com/commons/",[41],"Flickr commons",". Thus, if you\nhave photos in Flickr already, import them with a click or upload new photos to it. Flickr gives 1TB of space\nfor free!",[11,5880,5881,5882,5885],{},"Well, if you think Flickr is handy, what about our Dropbox integration? Yes, ",[510,5883,5884],{},"you can import any\npicture, audio file, PDF or video file from your own Dropbox account",". As many people use Dropbox to store their\ndata sets, we thought: what about integrating it into PyBossa? And voilà, here you have it! Another\nintegration that allows you to easily select your own data sets from a file viewer.",[11,5887,5888,5889,5892,5893,5898],{},"In December, we've also added a Twitter importer. Were you looking for ",[510,5890,5891],{},"sentiment analysis using Twitter hashtags","? You've found it!\nYou only have to type the query that you want to import, and PyBossa will do the hard work for you. We've created ",[37,5894,5897],{"href":5895,"rel":5896},"https://github.com/PyBossa/project-twitter-templates",[41],"two templates","\nso you can conduct sentiment analysis in under 10 minutes!",[29,5900,5902],{"id":5901},"auto-importers","Auto importers",[11,5904,5905,5906,5909,5910,5915,5916,5919,5920,5923],{},"While these integrations are cool, we realized that lots of projects are updated ",[247,5907,5908],{},"by hand"," when\nnew data becomes available. For instance, when you used our ",[37,5911,5914],{"href":5912,"rel":5913},"https://five.epicollect.net/",[41],"EpiCollect+"," integration\nto capture data with phones, you ",[247,5917,5918],{},"had"," to manually import the project again from time-to-time to capture\nthe new entries. It was simple, but you had to remember to do it. Thus, we decided to automate it,\nand so the ",[510,5921,5922],{},"auto importers"," were born.",[2889,5925,428,5927,5932,428],{"className":5926},[5261,5262],[2893,5928],{"className":5929,"src":5930,"width":5388,"height":5931,"frameBorder":2897,"allowFullScreen":145},[5842],"https://giphy.com/embed/YXpp9YxWhyWBy",360,[11,5933,5934],{},[37,5935],{"href":5936},"https://giphy.com/gifs/angry-king-burger-YXpp9YxWhyWBy",[11,5938,5939],{},"Auto importers let you transfer data directly into your PyBossa project without having to do it\nmanually. This feature allows you to push data to your projects while you can do other\nstuff, such as enjoy a cup of tea and check your emails. PyBossa will notify you when the new data\nhas been added. Enjoy!",[29,5941,5943],{"id":5942},"mailchimp","Mailchimp",[11,5945,5946],{},"The integrations discussed so far benefit you: the project owner. But what about your community? Well, don't worry,\nwe've got them covered too.",[11,5948,5949,5950,5954],{},"We know that your community wants to get connected, get the latest news about your\ncrowdsourcing platform, and keep up-to-date on what you have achieved etc. So we've integrated PyBossa\nwith ",[37,5951,5943],{"href":5952,"rel":5953},"http://mailchimp.com/",[41],". The integration asks new users whether they want to\nsubscribe to your newsletter at registration. Simple but effective. Now you have no excuse for not communicating to your community, right?",[2889,5956,428,5958,5963,428],{"className":5957},[5261,5553],[2893,5959],{"className":5960,"src":5961,"width":5388,"height":5962,"frameBorder":2897,"allowFullScreen":145},[5842],"https://giphy.com/embed/XB6pGqvOfJqY8",368,[11,5964,5965],{},[37,5966],{"href":5967},"https://giphy.com/gifs/dancing-happy-jimmy-fallon-XB6pGqvOfJqY8",[29,5969,5971],{"id":5970},"administrators-dashboard","Administrator's dashboard",[11,5973,5974,5975,5978],{},"With this approach in mind, we also wanted you to have\nmore insight about what's going on in the platform. Hence, ",[510,5976,5977],{},"we've developed a dashboard for administrators","\nwhere you can check the number of registered users in your site in the last week,\nfind out when new projects are created, published and updated, and when new versions of PyBossa are released,\nas well as view a live feed of what's going on the platform.",[29,5980,5982],{"id":5981},"for-da-geeks","For da geeks!",[11,5984,5985,5986,5989],{},"Finally (I told you we've not forgotten about the developers), ",[510,5987,5988],{},"we've developed a plugin\nsystem in PyBossa",". This feature allows you to actually extend what PyBossa can do.",[11,5991,5992,5993,5997],{},"For example, the British Library and their PyBossa-powered platform ",[37,5994,3757],{"href":5995,"rel":5996},"https://github.com/LibCrowds/Z3950-pybossa-plugin",[41]," have\ncreated two cool plugins:",[565,5999,6000,6008],{},[568,6001,6002,6007],{},[37,6003,6006],{"href":6004,"rel":6005},"https://github.com/LibCrowds/discourse-pybossa-plugin",[41],"Discourse integration",": now you can have your own forum in PyBossa.",[568,6009,6010,6014],{},[37,6011,6013],{"href":5995,"rel":6012},[41],"Z39.50 integration",": if your institution uses this protocol, you can easily integrate it.",[11,6016,6017],{},"Not bad for a year's work, right? Then, go and grab the latest version!",[15,6019,6021],{"id":6020},"be-your-own-research-platform","Be your own research platform",[11,6023,6024],{},"This year four institutions have chosen PyBossa as their solution to become their\nown crowdsourcing research platform (and we're so happy and proud about it).",[2889,6026,428,6028,6031,428],{"className":6027},[5261,5262],[2893,6029],{"className":6030,"src":5387,"width":5388,"height":5389,"frameBorder":2897,"allowFullScreen":145},[5842],[11,6032,6033],{},[37,6034],{"href":6035},"https://giphy.com/gifs/time-school-chemistry-Fbyam9ZAJ3J1m",[29,6037,6039],{"id":6038},"national-library-of-israel","National Library of Israel",[11,6041,6042,6043,6048],{},"The National Library contacted us this year to showcase what they have achieved with\ntheir PyBossa-powered platform ",[37,6044,6047],{"href":6045,"rel":6046},"http://nlics.org",[41],"nlics.org",". Their goal is to improve\ntheir metadata by asking contributors to tag, transcribe and answer questions\nrelating to historical Israeli documents.",[29,6050,6052],{"id":6051},"the-guardian","The Guardian",[11,6054,6055,6060],{},[37,6056,6059],{"href":6057,"rel":6058},"https://www.theguardian.com/australia-news/datablog/2015/mar/09/why-were-crowdsourcing-the-nsw-pecuniary-interests-register-faq",[41],"The guardian","\nnewspaper wanted to bring more transparency to New South Wales' (Australia)\npecuniary interests. They used PyBossa to make the first crowdsourcing\nproject of its kind.",[11,6062,6063],{},"In New South Wales politicians are required to declare details of gifts, investments,\nbusiness interests, and other items that could influence their decisions in parliament. They do this in the pecuniary interests register. However, half of New South Wales\npecuniary interests register has never been available to view online by the public, and the\nother half is hard to find. All of the declarations are only available as scanned\nPDFs, sometimes handwritten, which makes it difficult to properly scrutinise the register.",[11,6065,6066,6067,6072,6073,6078,6079,6084,6085,6088],{},"The solution? Use PyBossa to transform human readable documents into machine readable documents,\npublishing a ",[37,6068,6071],{"href":6069,"rel":6070},"https://www.theguardian.com/global/datablog/ng-interactive/2015/mar/27/search-the-nsw-register-of-pecuniary-interests-to-see-what-politicians-have-declared",[41],"search interface"," and a ",[37,6074,6077],{"href":6075,"rel":6076},"https://github.com/nickjevershed/pecuniaryinterests/blob/master/data.json",[41],"data set in GitHub",", as well as a nice ",[37,6080,6083],{"href":6081,"rel":6082},"https://www.theguardian.com/australia-news/2015/mar/27/exclusive-nsw-liberal-mps-failed-to-declare-financial-interests-on-register",[41],"article about this\ninvestigation",", where the journalists explains that their research ",[247,6086,6087],{},"forced New South Wales fair trading minister and the Liberal party’s whip to correct their pecuniary interest disclosures",". Amazing!",[29,6090,6092],{"id":6091},"the-british-library","The British Library",[11,6094,6095,6096,6100],{},"The British Library joined the PyBossa club with their ",[37,6097,3757],{"href":6098,"rel":6099},"http://libcrowds.com/",[41]," platform.\nAs with the National Library of Israel, they have several projects where they use PyBossa\nto ask volunteers to transcribe text from printed card catalogues into electronic records\nin order to make them available to a worldwide audience.",[11,6102,6103],{},"The project is initially focused on the library's Asian and African collections,\nparticularly the Chinese and Indian catalogues. Data identified, transcribed or\ntranslated as part of the project will be freely accessible from the\nBritish Library's Explore catalogue.",[11,6105,6106,6107,554],{},"You can find the ",[37,6108,6111],{"href":6109,"rel":6110},"http://www.libcrowds.com/blog/6",[41],"first results of the project in their blog",[29,6113,6115],{"id":6114},"university-of-heidelberg","University of Heidelberg",[11,6117,863,6118,1112,6122,6127],{},[37,6119,6115],{"href":6120,"rel":6121},"http://www.heidelberg.edu/",[41],[37,6123,6126],{"href":6124,"rel":6125},"https://disastermappers.wordpress.com/",[41],"Disaster Mappers"," have used our PyBossa technology to create two amazing projects.",[11,6129,863,6130,6135,6136,6141,6142,6147],{},[37,6131,6134],{"href":6132,"rel":6133},"http://crowdmap.geog.uni-heidelberg.de/app/missing_maps_follow_up/",[41],"first project"," supports the ",[37,6137,6140],{"href":6138,"rel":6139},"http://www.missingmaps.org/",[41],"Missing Maps Project"," by classifying\nBing aerial imagery. Volunteers were asked to assess whether there are human\nsettlements or major roads in the satellite imagery, ",[37,6143,6146],{"href":6144,"rel":6145},"http://umap.openstreetmap.fr/es/map/missing-maps-south-kivu-region-human-settlements-a_53739#9/-2.9842/28.9970",[41],"building the first data set"," for the\nanalyzed areas.",[11,6149,863,6150,6155],{},[37,6151,6154],{"href":6152,"rel":6153},"http://crowdmap.geog.uni-heidelberg.de/app/shelter_dynamics/",[41],"second project"," monitors the temporal and spatial dynamics of camps of\ninternally displaced persons (IDP) using satellite imagery to provide credible and\nup-to-date information from the Nepal Earthquake.",[15,6157,6159],{"id":6158},"events","Events",[11,6161,6162,6163,6168],{},"This year we have participated in several conferences, workshops and symposiums. We were at\n",[37,6164,6167],{"href":6165,"rel":6166},"http://live.empodera.org/",[41],"EmpoderaLIVE"," and we helped present the results of Micropasts: a PyBossa\npowered project by the British Museum and University College of London.",[11,6170,6171],{},[47,6172],{"alt":6173,"src":6174},"Spear head 3D printed thanks to PyBossa","/img/blog/spear.jpg",[11,6176,6178],{"className":6177},[5330],"Spear head 3D printed built thanks to PyBossa powered photomasking projects at Micropasts.",[11,6180,6181,6182,6187,6188,6191,6192,6197],{},"At ",[37,6183,6186],{"href":6184,"rel":6185},"http://zincshower.com/",[41],"Zincshower"," we won the award for ",[510,6189,6190],{},"Best startup of the event",". The prize was to go to\n",[37,6193,6196],{"href":6194,"rel":6195},"http://sonarplusd.com/",[41],"Sonar+D",", a very cool event where we had the opportunity to learn about the latest trends in\nelectronic music, as well as hang out with some of amazing start-ups.",[2889,6199,428,6201,6205,428],{"className":6200},[5261,5553],[2893,6202],{"className":6203,"src":6204,"width":5388,"height":5931,"frameBorder":2897,"allowFullScreen":145},[5842],"https://giphy.com/embed/26tPghhb310muUkEw",[11,6206,6207],{},[37,6208],{"href":6209},"https://giphy.com/gifs/90s-retro-commercials-26tPghhb310muUkEw",[15,6211,5650],{"id":6212},"crowdcrafting",[29,6214,6216],{"id":6215},"new-jazzy-projects","New jazzy projects",[11,6218,6219,6220,6225],{},"Crowdcrafting has also seen some amazing projects this year. Like ",[37,6221,6224],{"href":6222,"rel":6223},"https://web.archive.org/web/2019/http://crowdcrafting.org/project/landfill/",[41],"Landfill Hunter",", where the researcher\nwants to increase awareness of landfill sites, as well as contribute data to help better understand landfills and bring that information into the public domain.",[11,6227,863,6228,6233],{},[37,6229,6232],{"href":6230,"rel":6231},"https://web.archive.org/web/2019/http://crowdcrafting.org/project/Illegal_Parking/",[41],"European Illegal Parking"," project wants to rank European cities in order of the level of illegal parking observed on their streets.\nHopefully, this ranking will raise awareness of the problem in Europe and put pressure on national and local institutions to pursue more effective measures to tackle the problem. Awesome, right?",[11,6235,6236,6237,6242],{},"Finally, ",[37,6238,6241],{"href":6239,"rel":6240},"https://web.archive.org/web/2019/http://crowdcrafting.org/project/localpunebudget/",[41],"Localizing Pune's Budget",".\nThis project is trying to analyze and evaluate the ward-level infrastructure and public spending for Pune.\nOut of 9,614 budget items listed in the annual budget book for 2015-16,\nabout 1,997 do not have any ward number or whole-city marking alloted.\nIt would be great if you could assign the proper ward numbers to these works:\nso they then can have a more accurate picture about the investment made in various areas of Pune.",[29,6244,6246],{"id":6245},"the-stats","The stats",[11,6248,6249,6250,6253,6254,6257,6258,554],{},"If we're to reveal our ",[510,6251,6252],{},"vanity checks",", we can say that ",[510,6255,6256],{},"people have uploaded more than 200K tasks to Crowdcrafting",", and close to\n",[510,6259,6260],{},"half a million answers have been submitted by volunteers from all over the world",[11,6262,6263,6266,6267,554],{},[510,6264,6265],{},"2000 new users joined us this year",", while almost ",[510,6268,6269],{},"4000 anonymous people participated in a project",[11,6271,6272,6273,6276],{},"More than ",[510,6274,6275],{},"600 projects were created"," and there will no doubt be lots of new ones in 2016.",[15,6278,6280],{"id":6279},"looking-ahead","Looking ahead...",[11,6282,6283,6284,5431],{},"While this year has been amazing, we think that 2016 will be even cooler with new additions to PyBossa (like a new\nimporter for Youtube videos) as well as some secret stuff that we cannot share yet (yes, I'm trying to build anticipation\nso you'll check the blog next year ",[5823,6285],{"className":6286},[5826,6287],"twa-wink",[11,6289,6290],{},"Merry Christmas and Happy 2016!",{"title":49,"searchDepth":130,"depth":130,"links":6292},[6293,6300,6306,6307,6311],{"id":3716,"depth":130,"text":5818,"children":6294},[6295,6296,6297,6298,6299],{"id":5851,"depth":135,"text":5852},{"id":5901,"depth":135,"text":5902},{"id":5942,"depth":135,"text":5943},{"id":5970,"depth":135,"text":5971},{"id":5981,"depth":135,"text":5982},{"id":6020,"depth":130,"text":6021,"children":6301},[6302,6303,6304,6305],{"id":6038,"depth":135,"text":6039},{"id":6051,"depth":135,"text":6052},{"id":6091,"depth":135,"text":6092},{"id":6114,"depth":135,"text":6115},{"id":6158,"depth":130,"text":6159},{"id":6212,"depth":130,"text":5650,"children":6308},[6309,6310],{"id":6215,"depth":135,"text":6216},{"id":6245,"depth":135,"text":6246},{"id":6279,"depth":130,"text":6280},"2015-12-22T00:00:00.000Z","2015 has been an incredible year for team SciFabric.","road","Dustin Graffke","https://www.flickr.com/photos/onepointfour/21478226510/",{},"/blog/en/2015-12-22-year-in-review",{"title":3643,"description":6313},"year-in-review","blog/en/2015-12-22-year-in-review","yearinreview","VF0oZLCskgnXIaAFhYoY17p7Dlqp4Zkl8OmbL4b0HKA",{"id":6325,"title":6326,"author":141,"body":6327,"date":6668,"description":49,"extension":140,"headline":6669,"icon":6670,"icon_author":6671,"icon_url":6672,"layout":143,"location":6673,"meta":6674,"meta_description":6685,"navigation":145,"path":6686,"quote":141,"seo":6687,"slug":6688,"stem":6689,"tags":6690,"template":6691,"__hash__":6692},"blog/blog/en/2015-08-12-17k-users.md","17000 Volunteers Contribute to a PhD",{"type":8,"value":6328,"toc":6663},[6329,6338,6341,6348,6355,6363,6366,6381,6384,6388,6400,6407,6415,6421,6426,6429,6432,6446,6449,6458,6481,6484,6497,6501,6504,6507,6544,6548,6557,6580,6582,6606,6609,6616,6620,6623,6626,6629,6632,6644,6647,6656],[6330,6331,6332],"blockquote",{},[11,6333,6334,6337],{},[510,6335,6336],{},"Note:"," This post references Crowdcrafting, a citizen science platform that was discontinued in 2019. Links to Crowdcrafting now point to archived versions via the Internet Archive.",[11,6339,6340],{},"Doing a PhD is laborious, hard, demanding, exhausting... Your thesis is usually the\nresult of blood, sweat and tears. And you are usually alone. Well, what woud you say\nif I tell you that a researcher got helped by more than 17 thousand volunteers?",[11,6342,6343,6344,6347],{},"Yes, you've read it right: more than 17 thousand people have helped Alejandro Sánchez to do his\nresearch, publishing his thesis as a result and getting the best possible mark: ",[247,6345,6346],{},"cum laude",". Amazing, right?",[11,6349,6350,6351,6354],{},"But how this happened? How did he managed to involve such a big crowd? I mean, most people\nthink science is boring, tedious, ",[247,6352,6353],{},"difficult",", add here your adjective... However, this\nguy managed to get 17 thousand people from all over the world to help him on:",[2889,6356,6358],{"className":6357},[5261,5262],[2893,6359],{"src":6360,"width":5388,"height":5389,"frameBorder":2897,"style":6361,"className":6362,"webkitallowfullscreen":49,"mozallowfullscreen":49,"allowFullScreen":145},"https://giphy.com/embed/fqIBaMWI7m7O8","max-width: 100%",[2899],[11,6364,6365],{},"Best part? They did it because they wanted to help. No money involved! Just pure kindness.",[11,6367,6368,6369,6372,6373,6376,6377,6380],{},"In other words, ",[247,6370,6371],{},"the unexpected happened",", and thanks to ",[247,6374,6375],{},"sharing"," his work and also ",[247,6378,6379],{},"asking for help"," for his research -studying light pollution on cities- he managed to achieve the\nunconceivable: involving more than 17 thousand people on scientific research.",[11,6382,6383],{},"How this started? Well, let's start from the beginning.",[15,6385,6387],{"id":6386},"the-beginning-laying-down-the-ideas","The beginning: laying down the ideas",[11,6389,6390,6391,6396,6397,554],{},"This adventure started in 2014, in London, UK. I was participating at the ",[37,6392,6395],{"href":6393,"rel":6394},"https://web.archive.org/web/2014/http://cybersciencesummit.org/",[41],"Citizen Cyberscience Summit","\nand Alejandro was there because someone told him to learn more about ",[37,6398,5650],{"href":5648,"rel":6399},[41],[11,6401,6402,6403,6406],{},"At the summit there was a workshop where scientists and hackers joined forces to\ncreate new ",[247,6404,6405],{},"citizen science"," projects. Wait, let me explain first what's citizen\nscience so we can enjoy the trip later on (like this kid, I promise).",[2889,6408,6410],{"className":6409},[5261,5262],[2893,6411],{"src":6412,"width":5388,"height":6413,"frameBorder":2897,"style":6361,"className":6414,"webkitallowfullscreen":49,"mozallowfullscreen":49,"allowFullScreen":145},"https://giphy.com/embed/nMjnOuMRUBeW4",404,[2899],[11,6416,6417,6420],{},[510,6418,6419],{},"Citizen science"," is the active contribution of people who are not professional scientists to science. It provides volunteers with the opportunity to contribute intellectually to the research of others, to share resources or tools at their disposal, or even to start their own research projects. Volunteers provide real value to ongoing research while they themselves acquire a better understanding of the scientific method.",[11,6422,6368,6423,6425],{},[510,6424,6405],{}," opens the doors of laboratories and makes science accessible to all. It facilitates a direct conversation between scientists and enthusiasts who wish to contribute to scientific endeavor.",[11,6427,6428],{},"Now, with this idea in our minds let's get back to Alejandro's research.",[11,6430,6431],{},"At this workshop Alejandro told me that he was studying light pollution on cities. He and his team realized\nthat the astronauts from the International Space Station take pictures of the earth with a\nregular camera. Those pictures are then saved in a big archive. However, there are some issues:",[565,6433,6434,6437,6440,6443],{},[568,6435,6436],{},"The pictures could be from cities at night or day.",[568,6438,6439],{},"They take selfies too (who doesn't?)",[568,6441,6442],{},"The moon, stars and Aurora Borealis are also pretty, so they photograph them too.",[568,6444,6445],{},"The archive does not have any order or filter, everything is mixed in there.",[11,6447,6448],{},"In summary, he needs pictures at night of cities (sharp and without clouds) but the archive\nis a mess. The archive has too many different photos and possible scenarios that algorithms cannot help\nhim to classify them (or at a later stage geolocate them). However, you and me are pretty good\nat identifying cities at night with a glimpse, so we decided to create a prototype in Crowdcrafting.",[11,6450,6451,6452,6457],{},"The first project was ",[37,6453,6456],{"href":6454,"rel":6455},"https://web.archive.org/web/2019/http://crowdcrafting.org/project/darkskies/",[41],"Dark Skies",". We had the first\nprototype in a few hours and we basically asked people to help us to classify the pictures\nin different categories:",[565,6459,6460,6463,6466,6469,6472,6475,6478],{},[568,6461,6462],{},"City at night",[568,6464,6465],{},"Aurora Borealis",[568,6467,6468],{},"Stars",[568,6470,6471],{},"None of these",[568,6473,6474],{},"Black",[568,6476,6477],{},"Astronaut",[568,6479,6480],{},"I don't know",[11,6482,6483],{},"The project was simple and fun. I remember enjoying a lot classifying beautiful\npictures from the ISS. It make me feel I was an astronaut, and I loved that feeling so\nwe share it with our friends and colleagues.",[11,6485,6486,6487,1112,6492],{},"We really believed on the project, specially Alejandro, so he invited me to meet his PhD advisor and his\ncolleagues. We met and studied how we could improve it. As a result two new projects were born in the next months: ",[37,6488,6491],{"href":6489,"rel":6490},"https://web.archive.org/web/2019/http://crowdcrafting.org/project/LostAtNight/",[41],"Lost at night",[37,6493,6496],{"href":6494,"rel":6495},"https://web.archive.org/web/2019/http://crowdcrafting.org/project/nightcitiesiss/",[41],"Night Cities ISS",[15,6498,6500],{"id":6499},"the-small-announcement-that-became-huge","The small announcement that became huge",[11,6502,6503],{},"After a lot of work, Alejandro thought that the projects were good enough to send\nthem to NASA and ESA. Alejandro wrote a press release and share with them what we\nwere doing.",[11,6505,6506],{},"In the beginning we thought that they will ignore us, but something happened. It started\nlike a tremble. With a tweet:",[6330,6508,6513,6539,6540],{"className":6509,"lang":6511,"align":6512},[6510],"twitter-tweet","es","center",[11,6514,6515,6519,6520,6524,6525,6529,6530,6534,6535],{},[37,6516,6518],{"href":6517},"https://twitter.com/hashtag/Citizenscience?src=hash","#Citizenscience"," at work RT ",[37,6521,6523],{"href":6522},"https://twitter.com/teleyinex","@teleyinex",": ",[37,6526,6528],{"href":6527},"https://twitter.com/esa","@esa"," thanks to your help on Twitter ",[37,6531,6533],{"href":6532},"https://twitter.com/cities4tnight","@cities4tnight"," has 3000 tasks classified in ",[37,6536,6538],{"href":6537},"https://twitter.com/crowdcrafting","@crowdcrafting","— ESA (@esa) ",[37,6541,6543],{"href":6542},"https://twitter.com/esa/status/487228335018475521","julio 10, 2014",[4103,6545],{"async":145,"src":6546,"charSet":6547},"https://platform.twitter.com/widgets.js","utf-8",[11,6549,6550,6551,6556],{},"Then, almost one month later ",[37,6552,6555],{"href":6553,"rel":6554},"https://www.nasa.gov/mission_pages/station/research/news/crowdsourcing_night_images",[41],"NASA wrote a full article about the project"," and tweeted about it:",[6330,6558,6560,6575,6576],{"className":6559,"lang":6511,"align":6512},[6510],[11,6561,6562,6563,6566,6567,1592,6571],{},"Space station sharper images of Earth at night crowdsourced for science: ",[37,6564,6565],{"href":6565},"http://t.co/bHBiLwvZSv","   ",[37,6568,6570],{"href":6569},"https://twitter.com/hashtag/ISS?src=hash","#ISS",[37,6572,6574],{"href":6573},"http://t.co/bL9LymQ6cq","pic.twitter.com/bL9LymQ6cq","— NASA (@NASA) ",[37,6577,6579],{"href":6578},"https://twitter.com/NASA/status/499963958552711168","agosto 14, 2014",[4103,6581],{"async":145,"src":6546,"charSet":6547},[11,6583,6584,6585,1319,6590,1319,6595,1319,6600,6605],{},"That was the spark, as since that moment everything exploded! The project was covered internationally by the press. Media like ",[37,6586,6589],{"href":6587,"rel":6588},"http://video.foxnews.com/v/3742323090001/nasa-asks-for-help-tracking-locations-in-iss-photos/?#sp=show-clips",[41],"Fox TV",[37,6591,6594],{"href":6592,"rel":6593},"https://gizmodo.com/nasa-wants-you-to-sift-through-its-astronauts-photos-1623753892",[41],"Gizmodo",[37,6596,6599],{"href":6597,"rel":6598},"https://edition.cnn.com/2014/08/17/tech/nasa-earth-images-help-needed/index.html?hpt=hp_t2",[41],"CNN",[37,6601,6604],{"href":6602,"rel":6603},"https://pybossa.com/press/",[41],"..."," share the project and invited people to help.",[11,6607,6608],{},"Thanks to this coverage, in just one month we were able to classify more than 100 thousand images. One day Crowdcrafting servers stored more than 1.5 answers per second! We were like this:",[2889,6610,6612],{"className":6611},[5261,5262],[2893,6613],{"src":6614,"width":5388,"height":5389,"frameBorder":2897,"style":6361,"className":6615,"webkitallowfullscreen":49,"mozallowfullscreen":49,"allowFullScreen":145},"https://giphy.com/embed/gmhJbyiaeqoX6",[2899],[15,6617,6619],{"id":6618},"the-calm-after-the-storm","The calm after the storm",[11,6621,6622],{},"As with any press coverage after a few weeks everything went back to normal. However,\nlots of people kept coming and helping the projects from Alejandro.",[11,6624,6625],{},"Over a year we kept fixing bugs, adding new tasks, answering questions from volunteers, sharing progress,\netc. In July Alejandro defended his thesis with all this work. Amazing!",[11,6627,6628],{},"From my side I'm so happy and proud about it for two reasons. First, while the thesis\nhas been presented, the projects keeps going.",[11,6630,6631],{},"At the time of this writing\nthe Dark Skies project has classified almost 700 images in the last 15 days. Amazing!",[11,6633,6634,6635,6639,6640,6643],{},"The other two projects have less activity, as those projects are more complicated.\n",[37,6636,6638],{"href":6489,"rel":6637},[41],"Lost at Night"," has located more than 200\nphotos on a map, and ",[37,6641,6496],{"href":6494,"rel":6642},[41]," has\ngeo-referenced almost 25 pictures.",[11,6645,6646],{},"Secondly, because this is the very first thesis that uses PYBOSSA and Crowdcrafting\nfor doing open research. I'm impressed and I think this is just the beginning for many\nmore researchers doing their research on the open inviting society to take part on it.",[11,6648,6649,6650,6655],{},"The future? Well, Alejandro has launched a ",[37,6651,6654],{"href":6652,"rel":6653},"https://www.kickstarter.com/projects/1550160587/cities-at-night",[41],"Kickstarter"," campaign to get financial support\nto keep running the research his doing. If he gets the financial support more data will\nbe analyzed, new results will be produced and it will help to keep running Crowdcrafting\nand PYBOSSA. Thus, if you like the project help Alejandro to build the most beautiful\natlas of earth at night!",[2889,6657,6659],{"className":6658},[5261,5262],[2893,6660],{"src":6661,"width":5388,"height":5389,"frameBorder":2897,"className":6662,"allowFullScreen":145},"https://giphy.com/embed/xTiTnlmaAy5VZFAqFq",[2899],{"title":49,"searchDepth":130,"depth":130,"links":6664},[6665,6666,6667],{"id":6386,"depth":130,"text":6387},{"id":6499,"depth":130,"text":6500},{"id":6618,"depth":130,"text":6619},"2015-08-12T00:00:00.000Z","You have to take risks. We will only understand the miracle of life fully when we allow the unexpected to happen.\u003Cbr/> Paulo Coelho","together","Lennart Tange","https://www.flickr.com/photos/lennartt/9537775212/","Madrid, Spain",{"excerpt":6675},{"type":8,"value":6676},[6677,6683],[6330,6678,6679],{},[11,6680,6681,6337],{},[510,6682,6336],{},[11,6684,6340],{},"You have to take risks. We will only understand the miracle of life fully when we allow the unexpected to happen. Paulo Coelho","/blog/en/2015-08-12-17k-users",{"title":6326,"description":49},"17k-users","blog/en/2015-08-12-17k-users","Crowdcrafting, thesis, phd","entry","tpr5UX4SUZsd0lq6x1bnaEecKK6Rw14QnrmlCNXhu0U",{"id":6694,"title":6695,"author":141,"body":6696,"date":7278,"description":7279,"extension":140,"headline":7280,"icon":7281,"icon_author":7282,"icon_url":7283,"layout":143,"location":6673,"meta":7284,"meta_description":7280,"navigation":145,"path":7295,"quote":141,"seo":7296,"slug":7297,"stem":7298,"tags":7299,"template":6691,"__hash__":7300},"blog/blog/en/2015-07-01-the-art-of-graceful-reloading.md","The Art of Graceful Reloading",{"type":8,"value":6697,"toc":7271},[6698,6711,6723,6741,6745,6752,6757,6762,6765,6768,6804,6807,6830,6833,6840,6844,6847,6850,6853,6856,6860,6863,7126,7129,7132,7143,7146,7160,7163,7166,7169,7201,7205,7212,7215,7218,7221,7238,7241,7244,7247,7254,7257,7260,7268],[11,6699,6700,6701,6706,6707,6710],{},"The holy grail of web developers is to do deployments without interrupting your users.\nIn this blog post I explain how we have achieved it using ",[37,6702,6705],{"href":6703,"rel":6704},"https://uwsgi-docs.readthedocs.io/en/latest/articles/TheArtOfGracefulReloading.html#zerg-mode",[41],"uWSGI Zerg Mode"," for our\n",[37,6708,5650],{"href":5648,"rel":6709},[41]," servers.",[11,6712,6713,6714,6719,6720,554],{},"In a previous post I've already said that I love ",[37,6715,6718],{"href":6716,"rel":6717},"https://uwsgi-docs.readthedocs.io/",[41],"uWSGI",".\nThe main reason? You can do lots of nice tricks in your stack without having to add other\nlayers to it, like for example: ",[510,6721,6722],{},"graceful reloading",[11,6724,6725,6726,6730,6731,6735,6736,554],{},"The documentation from uWSGI is really great, and it covers most of the cases for graceful\nreloading, however due to our current ",[37,6727,6729],{"href":6728},"/blog/2015/02/10/infrastructure","stack"," and our ",[37,6732,6734],{"href":6733},"/blog/2015/02/25/autodeployments","auto deployments solution","\nwe needed something that integrated well with the so called: ",[37,6737,6740],{"href":6738,"rel":6739},"https://uwsgi-docs.readthedocs.io/en/latest/articles/TheArtOfGracefulReloading.html#the-zerg-dance-pausing-instances",[41],"Zerg dance",[15,6742,6744],{"id":6743},"zerg-mode","Zerg Mode",[11,6746,6747,6748,3955],{},"The Zerg mode is a nice feature from uWSGI that allows you to run your web application passing\nfile descriptors over Unix sockets. As stated on the ",[37,6749,6751],{"href":6703,"rel":6750},[41],"official docs",[11,6753,6754],{},[247,6755,6756],{},"Zerg mode works by making use of the venerable “fd passing over Unix sockets” technique.",[11,6758,6759],{},[247,6760,6761],{},"Basically, an external process (the zerg server/pool) binds to the various sockets required by your app. Your uWSGI instance, instead of binding by itself, asks the zerg server/pool to pass it the file descriptor. This means multiple unrelated instances can ask for the same file descriptors and work together.",[11,6763,6764],{},"This is really great, as you only need to enable a Zerg server and then you are ready to use it.",[11,6766,6767],{},"As we use Supervisor, configuring uWSGI to run as a Zerg server is really simple:",[2914,6769,6773],{"className":6770,"code":6771,"language":6772,"meta":49,"style":49},"language-bash shiki shiki-themes catppuccin-latte catppuccin-mocha","[uwsgi]\nmaster = true\nzerg-pool = /tmp/zerg_pool_1:/tmp/zerg_master.sock\n","bash",[1539,6774,6775,6785,6794],{"__ignoreMap":49},[224,6776,6777,6779,6782],{"class":3942,"line":3943},[224,6778,4504],{"class":3946},[224,6780,6781],{"class":4019},"uwsgi",[224,6783,6784],{"class":3946},"]\n",[224,6786,6787,6790,6792],{"class":3942,"line":130},[224,6788,6789],{"class":4224},"master",[224,6791,4271],{"class":3958},[224,6793,4895],{"class":4800},[224,6795,6796,6799,6801],{"class":3942,"line":135},[224,6797,6798],{"class":4224},"zerg-pool",[224,6800,4271],{"class":3958},[224,6802,6803],{"class":3958}," /tmp/zerg_pool_1:/tmp/zerg_master.sock\n",[11,6805,6806],{},"Then, you configure your web application to use the zerg server:",[2914,6808,6810],{"className":6770,"code":6809,"language":6772,"meta":49,"style":49},"[uwsgi]\nzerg = /tmp/zerg_master.sock\n",[1539,6811,6812,6820],{"__ignoreMap":49},[224,6813,6814,6816,6818],{"class":3942,"line":3943},[224,6815,4504],{"class":3946},[224,6817,6781],{"class":4019},[224,6819,6784],{"class":3946},[224,6821,6822,6825,6827],{"class":3942,"line":130},[224,6823,6824],{"class":4224},"zerg",[224,6826,4271],{"class":3958},[224,6828,6829],{"class":3958}," /tmp/zerg_master.sock\n",[11,6831,6832],{},"And you are done! That will configure your server to run in Zerg mode. However,\nwe can configure it to handle reloading in a more useful way: keeping a binary copy of\nthe previous running instance, pausing it, and deploying the new code on a new Zerg.\nThis is known as Zerg Dance, so let's dance!",[2889,6834,6836],{"className":6835},[5261,5262],[2893,6837],{"src":6838,"width":5388,"height":5389,"frameBorder":2897,"style":6361,"className":6839,"webkitallowfullscreen":49,"mozallowfullscreen":49,"allowFullScreen":145},"https://giphy.com/embed/GFBME4lzPVwxW",[2899],[15,6841,6843],{"id":6842},"zerg-dance","Zerg Dance",[11,6845,6846],{},"With the Zerg dance we'll be able to do deployments while the users keep using your\nweb application, as the Zerg server will be always handling those requests properly.",[11,6848,6849],{},"The neat trick from uWSGI is that it will handle those requests pausing them, so the user\nthinks it's getting slower, while the new deployment is taking place. As soon as the new\ndeployment is running it moves the \"paused request\" to the new code and keeps the old copy\nin case you broke something. Nice, right?",[11,6851,6852],{},"To achieve this situation all you have to do is use 3 different FIFOs in uWSGI. Why?\nBecause uWSGI can have as many master FIFOs as you want allowing you to pause zerg servers\nand move between them. This feature allows us to keep a binary copy of previously deployed code\non the server, that you can pause/resume and use it when something goes wrong.",[11,6854,6855],{},"This is really fast. The only issue is that you'll need more memory on your server, but I\nthink it's worthy as you'll be able to rollback a deployment with just two commands (we'll see\nthat in a moment).",[29,6857,6859],{"id":6858},"configuring-the-3-fifos","Configuring the 3 FIFOs",[11,6861,6862],{},"The documentation has a really good example. All you have to do is to add 3 FIFOs to\nyour web application uWSGI config file:",[2914,6864,6866],{"className":6770,"code":6865,"language":6772,"meta":49,"style":49},"[uwsgi]\n; fifo '0'\nmaster-fifo = /var/run/new.fifo\n; fifo '1'\nmaster-fifo = /var/run/running.fifo\n; fifo '2'\nmaster-fifo = /var/run/sleeping.fifo\n; attach to zerg\nzerg = /var/run/pool1\n; other options ...\n\n; hooks\n\n; destroy the currently sleeping instance\nif-exists = /var/run/sleeping.fifo\n  hook-accepting1-once = writefifo:/var/run/sleeping.fifo Q\nendif =\n; force the currently running instance to became sleeping (slot 2) and place it in pause mode\nif-exists = /var/run/running.fifo\n  hook-accepting1-once = writefifo:/var/run/running.fifo 2p\nendif =\n; force this instance to became the running one (slot 1)\nhook-accepting1-once = writefifo:/var/run/new.fifo 1\n",[1539,6867,6868,6876,6887,6897,6906,6915,6924,6933,6946,6955,6968,6972,6979,6983,7002,7007,7020,7028,7061,7066,7078,7084,7113],{"__ignoreMap":49},[224,6869,6870,6872,6874],{"class":3942,"line":3943},[224,6871,4504],{"class":3946},[224,6873,6781],{"class":4019},[224,6875,6784],{"class":3946},[224,6877,6878,6881,6884],{"class":3942,"line":130},[224,6879,6880],{"class":3946},";",[224,6882,6883],{"class":4224}," fifo",[224,6885,6886],{"class":3958}," '0'\n",[224,6888,6889,6892,6894],{"class":3942,"line":135},[224,6890,6891],{"class":4224},"master-fifo",[224,6893,4271],{"class":3958},[224,6895,6896],{"class":3958}," /var/run/new.fifo\n",[224,6898,6899,6901,6903],{"class":3942,"line":3982},[224,6900,6880],{"class":3946},[224,6902,6883],{"class":4224},[224,6904,6905],{"class":3958}," '1'\n",[224,6907,6908,6910,6912],{"class":3942,"line":3993},[224,6909,6891],{"class":4224},[224,6911,4271],{"class":3958},[224,6913,6914],{"class":3958}," /var/run/running.fifo\n",[224,6916,6917,6919,6921],{"class":3942,"line":4042},[224,6918,6880],{"class":3946},[224,6920,6883],{"class":4224},[224,6922,6923],{"class":3958}," '2'\n",[224,6925,6926,6928,6930],{"class":3942,"line":4072},[224,6927,6891],{"class":4224},[224,6929,4271],{"class":3958},[224,6931,6932],{"class":3958}," /var/run/sleeping.fifo\n",[224,6934,6935,6937,6940,6943],{"class":3942,"line":4088},[224,6936,6880],{"class":3946},[224,6938,6939],{"class":4224}," attach",[224,6941,6942],{"class":3958}," to",[224,6944,6945],{"class":3958}," zerg\n",[224,6947,6948,6950,6952],{"class":3942,"line":4098},[224,6949,6824],{"class":4224},[224,6951,4271],{"class":3958},[224,6953,6954],{"class":3958}," /var/run/pool1\n",[224,6956,6957,6959,6962,6965],{"class":3942,"line":4108},[224,6958,6880],{"class":3946},[224,6960,6961],{"class":4224}," other",[224,6963,6964],{"class":3958}," options",[224,6966,6967],{"class":3958}," ...\n",[224,6969,6970],{"class":3942,"line":4145},[224,6971,4694],{"emptyLinePlaceholder":145},[224,6973,6974,6976],{"class":3942,"line":4157},[224,6975,6880],{"class":3946},[224,6977,6978],{"class":4224}," hooks\n",[224,6980,6981],{"class":3942,"line":4347},[224,6982,4694],{"emptyLinePlaceholder":145},[224,6984,6985,6987,6990,6993,6996,6999],{"class":3942,"line":4357},[224,6986,6880],{"class":3946},[224,6988,6989],{"class":4224}," destroy",[224,6991,6992],{"class":3958}," the",[224,6994,6995],{"class":3958}," currently",[224,6997,6998],{"class":3958}," sleeping",[224,7000,7001],{"class":3958}," instance\n",[224,7003,7004],{"class":3942,"line":4363},[224,7005,7006],{"class":4019},"if-exists = /var/run/sleeping.fifo\n",[224,7008,7009,7012,7014,7017],{"class":3942,"line":4369},[224,7010,7011],{"class":4224},"  hook-accepting1-once",[224,7013,4271],{"class":3958},[224,7015,7016],{"class":3958}," writefifo:/var/run/sleeping.fifo",[224,7018,7019],{"class":3958}," Q\n",[224,7021,7022,7025],{"class":3942,"line":4380},[224,7023,7024],{"class":4224},"endif",[224,7026,7027],{"class":3958}," =\n",[224,7029,7030,7032,7035,7037,7039,7042,7045,7047,7050,7052,7055,7058],{"class":3942,"line":4386},[224,7031,6880],{"class":3946},[224,7033,7034],{"class":4224}," force",[224,7036,6992],{"class":3958},[224,7038,6995],{"class":3958},[224,7040,7041],{"class":3958}," running",[224,7043,7044],{"class":3958}," instance",[224,7046,6942],{"class":3958},[224,7048,7049],{"class":3958}," became",[224,7051,6998],{"class":3958},[224,7053,7054],{"class":4019}," (slot ",[224,7056,7057],{"class":4800},"2",[224,7059,7060],{"class":4019},") and place it in pause mode\n",[224,7062,7063],{"class":3942,"line":4412},[224,7064,7065],{"class":4019},"if-exists = /var/run/running.fifo\n",[224,7067,7068,7070,7072,7075],{"class":3942,"line":4426},[224,7069,7011],{"class":4224},[224,7071,4271],{"class":3958},[224,7073,7074],{"class":3958}," writefifo:/var/run/running.fifo",[224,7076,7077],{"class":3958}," 2p\n",[224,7079,7080,7082],{"class":3942,"line":4432},[224,7081,7024],{"class":4224},[224,7083,7027],{"class":3958},[224,7085,7086,7088,7090,7093,7095,7097,7099,7101,7103,7106,7108,7111],{"class":3942,"line":4437},[224,7087,6880],{"class":3946},[224,7089,7034],{"class":4224},[224,7091,7092],{"class":3958}," this",[224,7094,7044],{"class":3958},[224,7096,6942],{"class":3958},[224,7098,7049],{"class":3958},[224,7100,6992],{"class":3958},[224,7102,7041],{"class":3958},[224,7104,7105],{"class":3958}," one",[224,7107,7054],{"class":4019},[224,7109,7110],{"class":4800},"1",[224,7112,4807],{"class":4019},[224,7114,7115,7118,7120,7123],{"class":3942,"line":4455},[224,7116,7117],{"class":4224},"hook-accepting1-once",[224,7119,4271],{"class":3958},[224,7121,7122],{"class":3958}," writefifo:/var/run/new.fifo",[224,7124,7125],{"class":4800}," 1\n",[11,7127,7128],{},"After the FIFOs there is a section where we declare some hooks. These hooks will handle\nautomatically which FIFO has to be used in case of a server is started again.",[11,7130,7131],{},"The usual work flow will be the following:",[565,7133,7134,7137,7140],{},[568,7135,7136],{},"You start the server.",[568,7138,7139],{},"There is not sleeping or running fifo, so those conditions fail",[568,7141,7142],{},"Therefore, once the server is ready to accept requests (thanks to hook-accepting1-once) it moves the server from the new.fifo to running.fifo",[11,7144,7145],{},"Right now you've a server running as before. Imagine now you have to change something in the config\nor you have a new deployment. You do the changes, and start a new server with the same uWSGI config\nfile. This will happen:",[565,7147,7148,7151,7154,7157],{},[568,7149,7150],{},"You start the second server.",[568,7152,7153],{},"There is not sleeping fifo, so this condition fails",[568,7155,7156],{},"There is a running fifo, so this condition is met. Thus, the previous server is moved to the sleeping fifo and its paused when the new server is ready to accept requests.",[568,7158,7159],{},"Finally, once the server is ready to accept requests t moves the server from the new.fifo to running.fifo.",[11,7161,7162],{},"At this moment we've two servers: one running (the new one with your new code or config changes) and the old one\nwich is paused consuming only some memory.",[11,7164,7165],{},"Imagine now you realize that you have a bug in your new deployed code. How do you recover from this situation? Simple!",[11,7167,7168],{},"You just pause the new server and unpause the previous one. How do you do it? Like this:",[2914,7170,7172],{"className":6770,"code":7171,"language":6772,"meta":49,"style":49},"echo 1p > /tmp/running.fifo\necho 2p > /tmp/sleeping.fifo\n",[1539,7173,7174,7189],{"__ignoreMap":49},[224,7175,7176,7180,7183,7186],{"class":3942,"line":3943},[224,7177,7179],{"class":7178},"s-0VM","echo",[224,7181,7182],{"class":3958}," 1p",[224,7184,7185],{"class":3954}," >",[224,7187,7188],{"class":3958}," /tmp/running.fifo\n",[224,7190,7191,7193,7196,7198],{"class":3942,"line":130},[224,7192,7179],{"class":7178},[224,7194,7195],{"class":3958}," 2p",[224,7197,7185],{"class":3954},[224,7199,7200],{"class":3958}," /tmp/sleeping.fifo\n",[15,7202,7204],{"id":7203},"our-setup","Our setup",[11,7206,7207,7208,7211],{},"With our ",[37,7209,7210],{"href":6733},"auto deployments"," solution, we needed to find a simple way to integrate\nthis feature with supervisor. In the previous example you do the deployment manually,\nbut we want to have everything automated.",[11,7213,7214],{},"How we have achieved this? Simple! Using two PYBOSSA servers within Supervisor.",[11,7216,7217],{},"We have the default PYBOSSA server, and another one named pybossabak in Supervisor.",[11,7219,7220],{},"When a new deployment is done, the auto deployments solution boots the pybossa Backup server\njust to have a copy of the running state of the server. Then, it gets all the new changes,\napplies patches, etc. and restarts the default server. This procedure triggers the following:",[565,7222,7223,7226,7229,7232,7235],{},[568,7224,7225],{},"Start backup server: this moves the current running PYBOSSA server to the pause fifo, so we've a copy of it.",[568,7227,7228],{},"The backup server accepts the requests, so users don't see anything wrong.",[568,7230,7231],{},"Autodeployments applies changes to the source code, updates libraries, etc.",[568,7233,7234],{},"Then, it restarts the default PYBOSSA server (note: for supervisor the paused PYBOSSA server is running).",[568,7236,7237],{},"This restart moves the previous backup server to the pause fifo (it has the old code running), and boots the new code into production.",[11,7239,7240],{},"If something goes wrong with the new changes, all we have to do is pause the current server and resume the previous one.",[11,7242,7243],{},"This is done by hand, as we want to have control over this specific issue, but overall we are always covered\nwhen doing deployments automatically. We only have to click in the Merge Button of Github to do a deployment\nand we know a backup binary copy is hold on memory in case that we commit an error.",[11,7245,7246],{},"Moreover, the whole process of having uWSGI moving the requests of users from one server to another is great!",[11,7248,7249,7250,7253],{},"We've seen some users getting a 502, but that's because they ask for a request when the file descriptor is being\nmoved to the new server. Obviously, this is not 100% bullet proof, but much better than showing to ",[247,7251,7252],{},"all"," your users\na maintenance page while you do the upgrade.",[11,7255,7256],{},"We've been using this new work flow for a few weeks now, and all our production deployments\nare done automatically. Since we adopted this approach we've not have any issues, and we are more\nfocused only on developing more code. We employ less time handling deployments, which is great!",[11,7258,7259],{},"In summary: if you are using uWSGI, use the Zerg Dance, and enjoy the dance!",[2889,7261,7263],{"className":7262},[5261,5262],[2893,7264],{"src":7265,"width":5388,"height":7266,"frameBorder":2897,"style":6361,"className":7267,"webkitallowfullscreen":49,"mozallowfullscreen":49,"allowFullScreen":145},"https://giphy.com/embed/2tDQZuljhwHTi",182,[2899],[5130,7269,7270],{},"html pre.shiki code .sxyLT, html code.shiki .sxyLT{--shiki-default:#7C7F93;--shiki-dark:#9399B2}html pre.shiki code .s0aCy, html code.shiki .s0aCy{--shiki-default:#4C4F69;--shiki-dark:#CDD6F4}html pre.shiki code .sMmZK, html code.shiki .sMmZK{--shiki-default:#1E66F5;--shiki-default-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic}html pre.shiki code .sgueU, html code.shiki .sgueU{--shiki-default:#40A02B;--shiki-dark:#A6E3A1}html pre.shiki code .st0oN, html code.shiki .st0oN{--shiki-default:#FE640B;--shiki-dark:#FAB387}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s-0VM, html code.shiki .s-0VM{--shiki-default:#D20F39;--shiki-default-font-style:italic;--shiki-dark:#F38BA8;--shiki-dark-font-style:italic}html pre.shiki code .sjJjI, html code.shiki .sjJjI{--shiki-default:#179299;--shiki-dark:#94E2D5}",{"title":49,"searchDepth":130,"depth":130,"links":7272},[7273,7274,7277],{"id":6743,"depth":130,"text":6744},{"id":6842,"depth":130,"text":6843,"children":7275},[7276],{"id":6858,"depth":135,"text":6859},{"id":7203,"depth":130,"text":7204},"2015-07-01T00:00:00.000Z","The holy grail of web developers is to do deployments without interrupting your users.\nIn this blog post I explain how we have achieved it using uWSGI Zerg Mode for our\nCrowdcrafting servers.","Reloading your server without your users noticing it","loop","Leo Prieto","https://www.flickr.com/photos/leoprieto/582310541/",{"excerpt":7285},{"type":8,"value":7286},[7287],[11,7288,6700,7289,6706,7292,6710],{},[37,7290,6705],{"href":6703,"rel":7291},[41],[37,7293,5650],{"href":5648,"rel":7294},[41],"/blog/en/2015-07-01-the-art-of-graceful-reloading",{"title":6695,"description":7279},"the-art-of-graceful-reloading","blog/en/2015-07-01-the-art-of-graceful-reloading","Crowdcrafting, architecture, infrastructure","DC5c8txVeTR-UW8Y4nbFV_3BJ4V3hXvuGZdHtLqhGkQ",{"id":7302,"title":7303,"author":141,"body":7304,"date":7541,"description":7308,"extension":140,"headline":7542,"icon":7543,"icon_author":7544,"icon_url":7545,"layout":143,"location":6673,"meta":7546,"meta_description":49,"navigation":145,"path":7547,"quote":141,"seo":7548,"slug":7549,"stem":7550,"tags":7551,"template":6691,"__hash__":7552},"blog/blog/en/2015-06-08-translating-pybossa.md","Auto-translating PYBOSSA using PYBOSSA",{"type":8,"value":7305,"toc":7536},[7306,7309,7312,7316,7319,7334,7341,7350,7354,7361,7368,7376,7379,7382,7386,7394,7403,7409,7412,7415,7419,7422,7425,7455,7458,7488,7491,7503,7506,7510,7517,7519,7522,7525,7533],[11,7307,7308],{},"How do you translate properly your product into different languages? More importantly, how do you do it involving your own community?",[11,7310,7311],{},"The answer is easy: using a crowdsourcing solution like PYBOSSA.",[2643,7313,7315],{"id":7314},"translating-pybossa-using-pybossa","Translating PYBOSSA using PYBOSSA",[11,7317,7318],{},"Since the creation of PYBOSSA, I've translated it to Spanish. Other languages, like French, were added by a volunteer. However, these translations usually\nget outdated as PYBOSSA was updated with new strings. These solo efforts, usually end up in a translation that's not updated, and you end up with a mix of translated strings.",[11,7320,7321,7322,7327,7328,7333],{},"For these reasons we decided to eat our own dog food, and I created a ",[37,7323,7326],{"href":7324,"rel":7325},"https://web.archive.org/web/2019/http://crowdcrafting.org/project/pybossaitalian",[41],"crowdsourcing\nproject"," to translate PYBOSSA using PYBOSSA. Why? Because PYBOSSA uses the open\nstandard ",[37,7329,7332],{"href":7330,"rel":7331},"https://www.gnu.org/software/gettext/",[41],"Gettext"," for its translations, and each string could become a task in a\nPYBOSSA project.",[11,7335,7336,7337,7340],{},"Also ",[510,7338,7339],{},"I loved the idea that anyone, even without an account, can help in the translation.","\nThe current platforms usually need an account to just translate a few strings, and that's usually too much\nfor users who want to see the product they use in their own language. Obviously some\npeople will add fake translations, but that's not an issue as the crowd will help to clean the bad ones\nand keep the best one.",[11,7342,7343,7344,7349],{},"As I started working on it, I realized this could be very useful not only for me and PYBOSSA\nbut also to anyone using the Gettext technology in their projects. Thus, I created a PYBOSSA template\n",[37,7345,7348],{"href":7346,"rel":7347},"https://github.com/PYBOSSA/app-translations",[41],"project"," that anyone can re-use and adapt today to translate their own projects.",[2643,7351,7353],{"id":7352},"the-translation-template-project","The Translation Template Project",[11,7355,7356,7357,7360],{},"The template can be used in any PYBOSSA server, so if you don't have one, don't\nhesitate and go to ",[37,7358,5650],{"href":5648,"rel":7359},[41]," to create an account and\nstart using it.",[11,7362,863,7363,7367],{},[37,7364,7366],{"href":7346,"rel":7365},[41]," translation template "," is very simple. It has been designed to have two phases:",[565,7369,7370,7373],{},[568,7371,7372],{},"The Translation: 3 people translate the same string.",[568,7374,7375],{},"The Voting: 5 people vote for the best translation of the 3 translations.",[11,7377,7378],{},"The most voted, it's the one that it's going to be used as the final translated one.",[11,7380,7381],{},"As you can see the community of your project would be involved in translating but also\nin selecting the best translation for them. This will ensure that your audience will\nhave a better understanding about the text you write, leading to better results in engagement.",[15,7383,7385],{"id":7384},"_1-the-translation-phase","1. The Translation phase",[11,7387,7388,7389,7393],{},"The first thing you need to do is to download the template. Then, install the required\ntools (see the ",[37,7390,7392],{"href":7346,"rel":7391},[41],"README"," file for more information), and you will be ready to start translating\nyour project.",[11,7395,7396,7397,7402],{},"Then, all you have to do is get your PO file (it's a text file with the string\nto get translated from for example English to Spanish). Once you have it, you will pass it\nto ",[37,7398,7401],{"href":7399,"rel":7400},"https://github.com/PYBOSSA/pbs",[41],"PBS"," -our PYBOSSA command line tool- that will\nconvert untranslated strings to tasks for your PYBOSSA project:",[2914,7404,7407],{"className":7405,"code":7406,"language":2919},[2917],"pbs add_tasks --task-file=messages.pot --tasks-type=po --redundancy=3\n",[1539,7408,7406],{"__ignoreMap":49},[11,7410,7411],{},"This will add the untranslated strings as tasks to your PYBOSSA project. Each string will be shown to 3 different people, so you get\n3 translation for your own project. You can increase or reduce it as much as you want. It's up to you to decide.",[11,7413,7414],{},"When all the strings have been translated, you can move to the next phase if you want: the voting phase.",[15,7416,7418],{"id":7417},"_2-the-voting-phase","2. The Voting phase",[11,7420,7421],{},"In this phase, the 3 previous translations will be shown to people and they'll select\nthe best one for them. The most voted one will be the final translation for that string.",[11,7423,7424],{},"How do you move from one phase to the next one? As simple as this. First we create the voting project:",[2914,7426,7428],{"className":6770,"code":7427,"language":6772,"meta":49,"style":49},"pbs --project project_voting.json create_project\npbs --project project_voting.json update_project\n",[1539,7429,7430,7444],{"__ignoreMap":49},[224,7431,7432,7435,7438,7441],{"class":3942,"line":3943},[224,7433,7434],{"class":4224},"pbs",[224,7436,7437],{"class":3958}," --project",[224,7439,7440],{"class":3958}," project_voting.json",[224,7442,7443],{"class":3958}," create_project\n",[224,7445,7446,7448,7450,7452],{"class":3942,"line":130},[224,7447,7434],{"class":4224},[224,7449,7437],{"class":3958},[224,7451,7440],{"class":3958},[224,7453,7454],{"class":3958}," update_project\n",[11,7456,7457],{},"Secondly, we get the translated strings and pass them to the new voting project:",[2914,7459,7461],{"className":6770,"code":7460,"language":6772,"meta":49,"style":49},"python vote.py\npbs --project project_voting.json add_tasks --task-file=/tmp/translations_voting_tasks.json --redundancy=5\n",[1539,7462,7463,7471],{"__ignoreMap":49},[224,7464,7465,7468],{"class":3942,"line":3943},[224,7466,7467],{"class":4224},"python",[224,7469,7470],{"class":3958}," vote.py\n",[224,7472,7473,7475,7477,7479,7482,7485],{"class":3942,"line":130},[224,7474,7434],{"class":4224},[224,7476,7437],{"class":3958},[224,7478,7440],{"class":3958},[224,7480,7481],{"class":3958}," add_tasks",[224,7483,7484],{"class":3958}," --task-file=/tmp/translations_voting_tasks.json",[224,7486,7487],{"class":3958}," --redundancy=5\n",[11,7489,7490],{},"Then, 5 people will vote on which is the best translation. When all the strings have\nbeen curated by your community, in other words when the project is completed, all you\nhave to do to create the final translation file is running the following command:",[2914,7492,7494],{"className":6770,"code":7493,"language":6772,"meta":49,"style":49},"python create_mo.py\n",[1539,7495,7496],{"__ignoreMap":49},[224,7497,7498,7500],{"class":3942,"line":3943},[224,7499,7467],{"class":4224},[224,7501,7502],{"class":3958}," create_mo.py\n",[11,7504,7505],{},"Copy the new created file into your translations project, and you'll be done! As simple as that.",[15,7507,7509],{"id":7508},"firefox-extensions","Firefox extensions",[11,7511,7512,7513,554],{},"Yes, PYBOSSA also supports Firefox extensions. Thus, if you are writing a Firefox\nextension and you want to translate it to different languages, you can use\nPYBOSSA too. It's pretty similar and you have all the documentation about it\n",[37,7514,7516],{"href":7346,"rel":7515},[41],"here",[2643,7518,3774],{"id":3773},[11,7520,7521],{},"With our PYBOSSA translation template anyone can translate their open source project\nwith their community, involving them not only in the translation but also curating which\nis the best translation for every string.",[11,7523,7524],{},"Thus, don't get lost in translation anymore!",[2889,7526,7528],{"className":7527},[5261,5262],[425,7529,7530],{"autoPlay":145,"loop":145},[430,7531],{"src":7532},"https://media.giphy.com/media/ZCnP8OtmVRbPi/giphy.mp4",[5130,7534,7535],{},"html pre.shiki code .sMmZK, html code.shiki .sMmZK{--shiki-default:#1E66F5;--shiki-default-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic}html pre.shiki code .sgueU, html code.shiki .sgueU{--shiki-default:#40A02B;--shiki-dark:#A6E3A1}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":49,"searchDepth":130,"depth":130,"links":7537},[7538,7539,7540],{"id":7384,"depth":130,"text":7385},{"id":7417,"depth":130,"text":7418},{"id":7508,"depth":130,"text":7509},"2015-06-08T00:00:00.000Z","If you talk to a man in a language he understands, that goes to his head. If you talk to him in his own language, that goes to his heart. -Nelson Mandela.","lostintranslation","Alfonso","https://www.flickr.com/photos/tochis/3081093838/",{},"/blog/en/2015-06-08-translating-pybossa",{"title":7303,"description":7308},"translating-pybossa","blog/en/2015-06-08-translating-pybossa","Crowdcrafting, PYBOSSA, translation","wmOdL4kJxIm0Qd5n8Bz4LG4is7m-HQvZzvjX9zXn1RA",{"id":7554,"title":7555,"author":141,"body":7556,"date":7728,"description":7729,"extension":140,"headline":7730,"icon":5245,"icon_author":7731,"icon_url":7732,"layout":143,"location":6673,"meta":7733,"meta_description":49,"navigation":145,"path":7746,"quote":141,"seo":7747,"slug":6781,"stem":7748,"tags":7299,"template":6691,"__hash__":7749},"blog/blog/en/2015-03-05-uwsgi.md","uWSGI, or why you don't need Varnish",{"type":8,"value":7557,"toc":7721},[7558,7572,7576,7591,7597,7600,7620,7624,7632,7641,7647,7656,7659,7665,7668,7671,7675,7681,7684,7687,7690,7696,7699,7705,7708,7710,7713],[11,7559,7560,7561,7564,7565,7568,7569],{},"As a web developer one of my main goals is performance. In this blog post I\nexplain how we have boosted the performance of\n",[37,7562,5650],{"href":5648,"rel":7563},[41]," without touching\nthe ",[37,7566,3127],{"href":3125,"rel":7567},[41]," code or adding any extra layer to our\n",[37,7570,7571],{"href":6728},"stack.",[15,7573,7575],{"id":7574},"boosting-your-web-service-performance","Boosting your web service performance",[11,7577,7578,7579,7584,7585,7590],{},"If you are developing a web service you know that you have to cache content in\norder to serve lots of requests quickly, right? You might be using a memory\ncache like ",[37,7580,7583],{"href":7581,"rel":7582},"https://memcached.org/",[41],"memcached"," or\n",[37,7586,7589],{"href":7587,"rel":7588},"https://redis.io/",[41],"Redis",", like we do. However, sometimes this is\nnot enough because the request stills go through all your pipeline only saving\ntime from accessing the DB or computing a difficult value. Moreover, if you\nhave a distributed load-balanced high-available cache (as we do), the request\nwill take some time in retrieving the data from a node. Therefore you will end up\nsumming some precious milliseconds to that request just for fetching a value\nthat has been already computed (I always picture the requests like these\nskaters running to get to finish line).",[11,7592,7593],{},[47,7594],{"alt":7595,"src":7596},"Fast GIF","https://i.giphy.com/NUlSiaVrEaIdq.gif",[11,7598,7599],{},"When those milliseconds are precious, then you are looking for caching the whole\nrequest, not just some data in the DB.",[11,7601,7602,7603,7608,7609,7614,7615,554],{},"If you are looking for a solution to this problem you will probably find\n",[37,7604,7607],{"href":7605,"rel":7606},"https://www.varnish-cache.org",[41],"Varnish"," a web application accelerator also known\nas a caching HTTP reverse proxy. There is a\nlot of documentation on the web about it, and just to be fair we consider it\nfor some time but we decided to avoid it for a single reason: our\ninfrastructure uses cookies to handle sessions (we use ",[37,7610,7613],{"href":7611,"rel":7612},"https://flask-login.readthedocs.org/en/latest/",[41],"Flask-Login",") and this\nmakes things ",[37,7616,7619],{"href":7617,"rel":7618},"https://www.varnish-cache.org/docs/3.0/tutorial/cookies.html",[41],"really complicated",[29,7621,7623],{"id":7622},"looking-for-alternatives-uwsgi-cache-capabilities","Looking for alternatives: uWSGI cache capabilities",[11,7625,7626,7627,7631],{},"As I've explained in previous blog posts I love to keep things simple, so after\nchecking Varnish and all the issues that it will bring to our stack we decided\nto check the capabilities of uWSGI regarding caching (I even opened an\n",[37,7628,990],{"href":7629,"rel":7630},"https://github.com/maxcountryman/flask-login/issues/109",[41]," on\nFlask-Login about not using cookies for anonymous users in order to use Varnish\nwith no much luck).",[11,7633,7634,7635,7640],{},"uWSGI has a very powerful plugin system that allows you to customize how your\nweb service will behave. For example you can use the ",[37,7636,7639],{"href":7637,"rel":7638},"https://uwsgi-docs.readthedocs.io/en/latest/InternalRouting.html",[41],"internal\nrooting"," plus\nthe cache route plugin for caching specific requests based on some rules that you\nconfigure.",[11,7642,7643],{},[47,7644],{"alt":7645,"src":7646},"Success GIF","https://i.giphy.com/dmt0NRgroyTPW.gif",[11,7648,7649,7650,7655],{},"In the ",[37,7651,7654],{"href":7652,"rel":7653},"https://github.com/unbit/uwsgi-docs/blob/master/tutorials/CachingCookbook.rst",[41],"uWSGI Caching Cookbook",",\nthe explain step by step how you can do it for almost every single scenario,\nhowever the examples are very generic and you will need to work out your own\nrules to fit your project.",[11,7657,7658],{},"An example config file for uWSGI where you cache all the pages would be the\nfollowing:",[2914,7660,7663],{"className":7661,"code":7662,"language":2919},[2917],"[uwsgi]\nplugin = router_cache\nchdir = /your/project/\npythonpath = ..\nvirtualenv = /your/virtualenv\nmodule = run:app\nprocesses = 2\n; log response time with microseconds resolution\nlog-micros = true\n\n; create a cache with 100 items (default size per-item is 64k)\ncache2 = name=mycache,items=100\n\n; fallback to text/html all of the others request\nroute = .* cache:key=${REQUEST_URI},name=mycache\n; store each successfull request (200 http status code) in the 'mycache' cache using the REQUEST_URI as key\nroute = .* cachestore:key=${REQUEST_URI},name=mycache\n",[1539,7664,7662],{"__ignoreMap":49},[11,7666,7667],{},"This set of rules are very simple. It will cache every request that returns a\n200 status code in the cache. This config file is really nice for project where\nthe site is delivering content and there is no much changing.",[11,7669,7670],{},"However our site has a mixture of both things, pages that do not change too\nmuch over time and pages that have to be adapted for each user (specially for\nregistered users).",[29,7672,7674],{"id":7673},"dealing-with-cookies-and-sessions","Dealing with cookies and sessions",[11,7676,7677,7678],{},"As I've said before Flask-login place cookie for anonymous and authenticated\nusers. Hence, all users have a cookie, ",[247,7679,7680],{},"but authenticated ones have an extra one\nin our project as this cookie is used to remember the session of the user for a\nperiod of time.",[11,7682,7683],{},"Thanks to this configuration we can know that a user is a registered one if\nboth cookies exists, or the other way around: we can know if a user is an anonymous\nuser if only the remember me cookie does not exist.",[11,7685,7686],{},"Using this knowledge we can instruct uWSGI to cache some URLs (i.e. front page,\nabout page, etc.) only for anonymous users, as they don't need tailored\ninformation. If they sign up then, instead of serving their cached request we\nwill process the request as usual (remember that we've different levels of\ncaches, right?).",[11,7688,7689],{},"To us, for the moment, the most important aspect to cache is what anonymous\nusers see, as this segment is what's driving most of the traffic to our site.\nNow that we can distinguish between authenticated and anonymous users, we basically\nconfigure the uWSGI like this:",[2914,7691,7694],{"className":7692,"code":7693,"language":2919},[2917],"route-if = empty${cookie[remember_token]} goto:cacheme\nroute-run = continue:\n\n; the following rules are executed only if remember_token is empty\nroute-label = cacheme\nroute = ^/about$ cache:key${REQUEST_URI},name=cache2\nroute = ^/about$ cachestore:key=${REQUEST_URI},name=cache2\n",[1539,7695,7693],{"__ignoreMap":49},[11,7697,7698],{},"The above example caches for anonymous users the about page of our\nCrowdcrafting site. When the cache is clean, the first rule will fail, so it\nwill process the request,  stored it in the cache and then served it. Next time\nthe same anonymous user or another one request the same URI, the cached request\nwill be served boosting the performance a lot. Simple, right? Now you only\nadapt this snippet to your own URIs and web project and you will have an\namazing boost in performance. Best part? That you don't have to touch a single\nline of your source code. Amazing!",[11,7700,7701],{},[47,7702],{"alt":7703,"src":7704},"Clap GIF","https://i.giphy.com/DKqH1q9gN5AKA.gif",[11,7706,7707],{},"Registered users will never receive any cached request with this configuration.\nYou could cache for every user each URI based on their remember_token cookie\nhowever that will require lots of memory and it will defeat the purpose of\nhaving a cache: that lots of requests are already served from the same data\npoint. Having a cached item per user is useless on this regard, as you will be\nloosing performance. In this case it's is much better to cache at the data\nlevel, as all the users would benefit from it: anonymous and authenticated\nones.",[15,7709,3774],{"id":3773},[11,7711,7712],{},"Thanks to this solution we've improved our performance a lot. Before these\nimprovements, the average response time of our servers were close to 250ms and now all of\nthem are responding in average below the 50ms. Saving 200ms is incredible!\nMost importantly because we've not added a new layer or anything special to our\nown stack. We've just configured it better!",[11,7714,7715,7717,7718,7720],{},[510,7716,5148],{},": The heading photo pictures the filament of a light bulb. To take the\npicture the photographer used a ",[510,7719,5245],{}," lens, and I've always pictured uWSGI\nas micro WSGI ;-)",{"title":49,"searchDepth":130,"depth":130,"links":7722},[7723,7727],{"id":7574,"depth":130,"text":7575,"children":7724},[7725,7726],{"id":7622,"depth":135,"text":7623},{"id":7673,"depth":135,"text":7674},{"id":3773,"depth":130,"text":3774},"2015-03-05T00:00:00.000Z","As a web developer one of my main goals is performance. In this blog post I\nexplain how we have boosted the performance of\nCrowdcrafting without touching\nthe PYBOSSA code or adding any extra layer to our\nstack.","How to achieve a server response time of less than 50ms thanks to uWSGI","dorikowalski","https://www.flickr.com/photos/ptr-an/2134521914",{"excerpt":7734},{"type":8,"value":7735},[7736],[11,7737,7560,7738,7564,7741,7568,7744],{},[37,7739,5650],{"href":5648,"rel":7740},[41],[37,7742,3127],{"href":3125,"rel":7743},[41],[37,7745,7571],{"href":6728},"/blog/en/2015-03-05-uwsgi",{"title":7555,"description":7729},"blog/en/2015-03-05-uwsgi","xMEEUdO9QBOgsD0_TnvYCFSoDlPB5b8FGGChwsYGndI",{"id":7751,"title":7752,"author":141,"body":7753,"date":7910,"description":7757,"extension":140,"headline":7911,"icon":7912,"icon_author":7913,"icon_url":7914,"layout":143,"location":6673,"meta":7915,"meta_description":7911,"navigation":145,"path":7920,"quote":141,"seo":7921,"slug":7922,"stem":7923,"tags":7299,"template":6691,"__hash__":7924},"blog/blog/en/2015-02-25-autodeployments.md","Autodeployments",{"type":8,"value":7754,"toc":7902},[7755,7758,7762,7769,7790,7799,7803,7811,7814,7820,7823,7827,7830,7836,7839,7843,7852,7858,7861,7872,7875,7878,7882,7885,7888,7894],[11,7756,7757],{},"At Crowdcrafting we take really seriously shipping code. For this reason, we've\ncreated a very simple web service (it's our own software robot) that automatically\ndeploys for us any Github project with Ansible playbooks and posts the status of\nthe deployment in our Slack chat channel.",[15,7759,7761],{"id":7760},"why-another-deployment-server","Why another deployment server?",[11,7763,7764,7765,7768],{},"A fairly good question. We checked different options like HUBot, however using\nthe service meant to add extra layers to our ",[37,7766,7767],{"href":6728},"current stack",". In the case of HUBot\nwe would have to install Node.js and learn coffee script to write our own\nplugins. IMHO too much work for just doing some deployments, plus we will add a\nstack to our infrastructure that we do not fully know.",[11,7770,7771,7772,7777,7778,7783,7784,7789],{},"For these reasons we decided to create something very simple that uses the\n",[37,7773,7776],{"href":7774,"rel":7775},"https://developer.github.com/v3/repos/deployments/",[41],"Github API for\ndeployments"," and integrated\nwith ",[37,7779,7782],{"href":7780,"rel":7781},"https://www.ansible.com/home",[41],"Ansible"," (we use it for managing\nour own infrastructure) as well as with ",[37,7785,7788],{"href":7786,"rel":7787},"http://slack.com",[41],"Slack"," to follow the status of the\ndeployments.",[11,7791,7792,7793,7798],{},"The server uses the ",[37,7794,7797],{"href":7795,"rel":7796},"https://flask.palletsprojects.com/",[41],"Flask framework"," and we can host it in our current\ninfrastructure without adding any extra layer.",[15,7800,7802],{"id":7801},"our-deployments-solution-or-our-robot","Our deployments solution (or our robot)",[11,7804,7805,7810],{},[37,7806,7809],{"href":7807,"rel":7808},"https://github.com/PYBOSSA/deployments",[41],"The web server"," has less than 250 lines of\ncode. It's 100% tested, covered and with a code health quality of 100% according to\nLandscape.io. Oh, it's also open source!",[11,7812,7813],{},"The server uses a config file to specify which repositories from Github have to\nbe deployed. The structure is quite simple:",[2914,7815,7818],{"className":7816,"code":7817,"language":2919},[2917],"DEBUG = False\nSECRET = 'yoursecret-to-protect-your-server'\nTOKEN = 'your-github-token'\nSLACK_WEBHOOK = 'yourslackwebhook'\nREPOS = {\n    'user/repo': {'folder': '/repo',\n                  'required_contexts': [\"continuous-integration/travis-ci\"],\n                  'commands': [['git', 'fetch'],\n                               ['git', 'pull', 'origin', 'master']]}\n}\n",[1539,7819,7817],{"__ignoreMap":49},[11,7821,7822],{},"A very handy feature is that you can specify in the config file if you want to\nonly do a deployment when for example your continuous integration tests are passing. This is\noptional, but you are already testing your software, right?",[29,7824,7826],{"id":7825},"ansible-integration","Ansible integration",[11,7828,7829],{},"In the previous example you can add as many commands as you want. However,\nif you are already using Ansible playbooks all you have to do to use them with\nthe server is this:",[2914,7831,7834],{"className":7832,"code":7833,"language":2919},[2917],"DEBUG = False\nSECRET = 'yoursecret-to-protect-your-server'\nTOKEN = 'your-github-token'\nSLACK_WEBHOOK = 'yourslackwebhook'\nREPOS = {\n    'user/repo': {'ansible_hosts': 'hosts_file',\n                  'ansible_playbook': 'playbook.yml',\n                  'required_contexts': [\"continuous-integration/travis-ci\"],\n}\n",[1539,7835,7833],{"__ignoreMap":49},[11,7837,7838],{},"Thanks to Ansible you can deploy the same software in different machines,\nsomething very handy when you have project with several nodes running the\nsame stack as we do.",[29,7840,7842],{"id":7841},"slack-notifications","Slack notifications",[11,7844,7845,7846,7851],{},"In order to get Slack notifications, all you have to do is to add a new\nintegration in your Slack team: ",[37,7847,7850],{"href":7848,"rel":7849},"https://api.slack.com/incoming-webhooks",[41],"incoming webhooks",". This integration will give\nyou a URL that you only have to copy and paste into the config file. Once you\nhave done it the server will post messages about the status of\nthe deployment. The messages are like this:",[11,7853,7854],{},[47,7855],{"alt":7856,"src":7857},"Deployment screenshot","/img/blog/deployments.png",[11,7859,7860],{},"The message includes the following information:",[565,7862,7863,7866,7869],{},[568,7864,7865],{},"the repository that has been deployed,",[568,7867,7868],{},"the user that has done the deployment,",[568,7870,7871],{},"the status of the deployment.",[11,7873,7874],{},"The status is pretty handy because if something goes badly, you can debug what\nhappened as we store the error messages in the Github API, so you can review\nthem.",[11,7876,7877],{},"Best part: the robot communicates his work!",[29,7879,7881],{"id":7880},"doing-deployments","Doing deployments",[11,7883,7884],{},"How do you actually do deployments? Well, we just wanted to make it very simple\nlike clicking a single button.",[11,7886,7887],{},"Our solution? When a branch with fixes or a new feature in Github is merged\ninto the master branch, the service will deploy the changes into production\n(or the machines that you want). As simple as that! The system takes care of\nitself! Batteries included!!",[11,7889,7890],{},[47,7891],{"alt":7892,"src":7893},"BMO gif changing its batteries","https://i.giphy.com/AMqCTHuCMFpM4.gif",[11,7895,7896,7897,7901],{},"Thanks to this solution now every member of my team can actually do deployments\ninto production. This has been a significant change in our work flow as\neveryone can deploy changes into production (",[37,7898,7900],{"href":7899},"/blog/2015/02/06/teams","trust your team","), and you don't have to ask a favor to\ndo a deployment. You just simply click a button!",{"title":49,"searchDepth":130,"depth":130,"links":7903},[7904,7905],{"id":7760,"depth":130,"text":7761},{"id":7801,"depth":130,"text":7802,"children":7906},[7907,7908,7909],{"id":7825,"depth":135,"text":7826},{"id":7841,"depth":135,"text":7842},{"id":7880,"depth":135,"text":7881},"2015-02-25T00:00:00.000Z","Whether we are based on carbon or on silicon makes no fundamental difference; we should each be treated with appropriate respect. Arthur C. Clarke","robot","Daniel Lombraña González","https://www.flickr.com/teleyinex",{"excerpt":7916},{"type":8,"value":7917},[7918],[11,7919,7757],{},"/blog/en/2015-02-25-autodeployments",{"title":7752,"description":7757},"autodeployments","blog/en/2015-02-25-autodeployments","NjiL1uutOXcoDbnjwbI1g-d1N0ohsn76FVcE51UMmv4",{"id":7926,"title":7927,"author":141,"body":7928,"date":8353,"description":8354,"extension":140,"headline":8355,"icon":8356,"icon_author":8357,"icon_url":8358,"layout":143,"location":6673,"meta":8359,"meta_description":141,"navigation":145,"path":8367,"quote":141,"seo":8368,"slug":8369,"stem":8370,"tags":7299,"template":6691,"__hash__":8371},"blog/blog/en/2015-02-10-infrastructure.md","Crowdcrafting stack",{"type":8,"value":7929,"toc":8343},[7930,7939,7951,7954,7960,7964,7967,7970,7973,7977,7997,8008,8018,8032,8042,8053,8056,8062,8065,8071,8078,8082,8095,8100,8113,8121,8124,8141,8144,8157,8161,8175,8180,8190,8197,8204,8222,8225,8239,8241,8244,8247,8253,8258,8261,8265,8272,8275,8279,8286,8289,8299,8314,8318,8321,8324,8327,8335,8338],[11,7931,7932,7933,7938],{},"Putting all your heart in what you do makes the difference. Why? Because as the\nBaron says in the movie, ",[37,7934,7937],{"href":7935,"rel":7936},"https://en.wikipedia.org/wiki/The_Cat_Returns",[41],"The Cat\nReturns",", the creation is given a\nsoul.",[11,7940,7941,7942,7945,7946,554],{},"On December 4 of 2014, we got the very wonderful news that\n",[37,7943,5650],{"href":5648,"rel":7944},[41]," was recognized as ",[37,7947,7950],{"href":7948,"rel":7949},"http://socialtech.org.uk/nominet-trust-100/",[41],"one of the social\ntechnological companies of the year",[11,7952,7953],{},"Wining this price has been amazing, a recognition to our really hard to make our\nCrowdcrafting site robust, scalable and stable.",[11,7955,7956,7959],{},[510,7957,7958],{},"TL;DR"," as this is going to describe our current infrastructure and how we run\nCrowdcrafting, so you are advised!",[15,7961,7963],{"id":7962},"http-load-balancer","HTTP Load Balancer",[11,7965,7966],{},"We host all our services in Rackspace. The reason? Well, they've a handy\ncalculator that allows us to estimate how much is going to cost us running our\nservices there, and I love it. Basically, because they don't lie, and the\nnumbers fit.",[11,7968,7969],{},"One of the nice features that Rackspace offers, is the option to enable an\nHTTTP load balancer for your cloud servers. This simplifies a lot our set up,\nand we've configured it to balance the incoming requests to our PYBOSSA\nservers.",[11,7971,7972],{},"Therefore, when a user requests a page from Crowdcrafting, the first service\nthat it's contacted is the load balancer. The balancer will distribute the\nrequests to our PYBOSSA servers.",[15,7974,7976],{"id":7975},"nginx-uwsgi","Nginx & uWSGI",[11,7978,7979,7980,7985,7986,7991,7992,7996],{},"Once the request has been redirected to one of the PYBOSSA servers, the request\nhits the ",[37,7981,7984],{"href":7982,"rel":7983},"https://nginx.org",[41],"Nginx"," server. Nginx, checks its sites enabled, and directs the request\nto our PYBOSSA ",[37,7987,7990],{"href":7988,"rel":7989},"https://flask.palletsprojects.com",[41],"Flask"," application written in Python. At this point, the server\nis contacted and served via the ",[37,7993,6718],{"href":7994,"rel":7995},"https://uwsgi-docs.readthedocs.org",[41]," middleware, that will take care of moving\nthe request through our infrastructure.",[11,7998,7999,8000,8003,8004,8007],{},"Hence, ",[37,8001,7984],{"href":7982,"rel":8002},[41]," takes care of serving static files, while ",[37,8005,6718],{"href":7994,"rel":8006},[41]," takes care of the\nrest.",[11,8009,8010,8011,1112,8014,8017],{},"In the very beginning of Crowdcrafting we used Apache2 and mod_wsgi, but we\nchanged to ",[37,8012,7984],{"href":7982,"rel":8013},[41],[37,8015,6718],{"href":7994,"rel":8016},[41]," because:",[565,8019,8020,8026],{},[568,8021,8022,8025],{},[37,8023,7984],{"href":7982,"rel":8024},[41]," is really simple to configure.",[568,8027,8028,8031],{},[37,8029,6718],{"href":7994,"rel":8030},[41]," gives the best performance.",[11,8033,8034,8035,8038,8039,554],{},"When we were running on Apache2 and mod_wsgi the\nperformance was suboptimal (we tested it with Locust.io) and we could see a\nclear detriment in the number of requests per second that we were delivering in\ncomparison with the current setup. For this reason, we looked for new solutions\nand we found that the best match for us is ",[37,8036,7984],{"href":7982,"rel":8037},[41]," + ",[37,8040,6718],{"href":7994,"rel":8041},[41],[11,8043,8044,8045,8048,8049,8052],{},"While we've been developing PYBOSSA we've always keep in mind that PYBOSSA\nshould be able to ",[510,8046,8047],{},"scale horizontally without problems",". While this seems ",[247,8050,8051],{},"easy\nto achieve"," the truth is that there are so many options out there that at the\nend it becomes a nightmare to decide which one is the best solution.",[11,8054,8055],{},"For example, serving avatars from N different servers should always return the\nsame image from all of them to the clients.",[11,8057,8058,8061],{},[247,8059,8060],{},"In our case we decided to keep things as simple as possible",", (the KISS principle).",[11,8063,8064],{},"For this reason, we've enabled the Rackspace CDN support in PYBOSSA (it can be\neasily extended to any other CDN as we've a generic class that can be\ninherited) for serving files from a central place. This solution allows us to\ngrow horizontally without taking care of where the files are being served.",[11,8066,8067,8068,554],{},"Additionally, if someone does not want to enable the CDN, they can configure\nPYBOSSA to use the local uploader and use a Glusterfs to distribute the files\nacross all the servers. We didn't like this solution as it added another point for\nfailure in our systems and we've to take care of it ourselves, while the CDN does\nthis for us ",[247,8069,8070],{},"automagically",[11,8072,8073,8074,8077],{},"Once the request is in the ",[37,8075,6718],{"href":7994,"rel":8076},[41]," middleware, the PYBOSSA server will probably\nneed access data in the database, so it can render the HTML and return the\nresponse back to the client. The next section explains how we handle this part\nof the request.",[15,8079,8081],{"id":8080},"postgresql-pgbouncer","PostgreSQL & PgBouncer",[11,8083,8084,8085,8088,8089,8094],{},"Once the request hits the ",[37,8086,7990],{"href":7988,"rel":8087},[41]," app, usually it will involve a query to the\ndatabase. We use ",[37,8090,8093],{"href":8091,"rel":8092},"https://www.postgresql.org",[41],"PostgreSQL"," 9.3 and we're really impressed by the quality,\nperformance and community around it. We LOVE IT! Best DB ever.",[11,8096,8097],{},[47,8098],{"alt":49,"src":8099},"https://i.giphy.com/WxxsVAJLSBsFa.gif",[11,8101,8102,8103,8108,8109,8112],{},"As we will have lots of connections coming from different servers, we wanted to\nimprove how we handle those connections to the DB to reduce overhead and timing\nestablishing connections, closing, etc. For this issue we're using in each\nPYBOSSA server ",[37,8104,8107],{"href":8105,"rel":8106},"https://wiki.postgresql.org/wiki/PgBouncer",[41],"PgBouncer"," for pooling the connections to two ",[37,8110,8093],{"href":8091,"rel":8111},[41]," servers:",[565,8114,8115,8118],{},[568,8116,8117],{},"Master node accepting read and write queries, and",[568,8119,8120],{},"Slave node accepting only read queries.",[11,8122,8123],{},"PYBOSSA establishes two different connections to the databases in order to use\nread-only connections when we want to grab just information, or write\nconnections when we've to write something back to the DB.",[11,8125,8126,8127,8130,8131,8136,8137,8140],{},"While ",[37,8128,8107],{"href":8105,"rel":8129},[41]," pools connections, it does not load balance them, so for this\nreason we use ",[37,8132,8135],{"href":8133,"rel":8134},"https://www.haproxy.org",[41],"HAProxy"," to load balance the READ queries between the master and\nslave nodes transparently. The best part of this configuration is that\neverything is completely handled automagically and transparently by ",[37,8138,8135],{"href":8133,"rel":8139},[41],", so\nPYBOSSA does not know anything about it.",[11,8142,8143],{},"Thanks to this set up we can add more slave nodes horizontally, scaling and load\nbalancing our infrastructure easily.",[11,8145,8146,8147,1112,8151,8156],{},"While this solution is great, some queries need to be cached before hitting the\ndatabase as they take time to be processed (i.e. statistics for Crowdcrafting\nprojects). For this reason we're using ",[37,8148,7589],{"href":8149,"rel":8150},"https://redis.io",[41],[37,8152,8155],{"href":8153,"rel":8154},"https://redis.io/topics/sentinel",[41],"Sentinel"," to cache almost\neverything.",[15,8158,8160],{"id":8159},"redis-sentinel","Redis & Sentinel",[11,8162,8163,8164,8167,8168,1112,8171,8174],{},"If we're in love with ",[37,8165,8093],{"href":8091,"rel":8166},[41]," what can we say about ",[37,8169,7589],{"href":8149,"rel":8170},[41],[37,8172,8155],{"href":8153,"rel":8173},[41],": we\nlove them too :-)",[11,8176,8177],{},[47,8178],{"alt":49,"src":8179},"https://i.giphy.com/f31DK1KpGsyMU.gif",[11,8181,8182,8183,1112,8186,8189],{},"Since the very beginning PYBOSSA has been using ",[37,8184,7589],{"href":8149,"rel":8185},[41],[37,8187,8155],{"href":8153,"rel":8188},[41]," to build a\nload-balance high-available cache solution.",[11,8191,8192,8193,8196],{},"There set up is pretty simple: one ",[37,8194,7589],{"href":8149,"rel":8195},[41]," master node that accepts read and write\nqueries, while almost every other node in our infrastructure has a slave node.",[11,8198,8199,8200,8203],{},"Additionally ",[37,8201,8155],{"href":8153,"rel":8202},[41]," takes care of handling all these nodes for us\ntransparently, and we don't have to do anything ourselves. This solution has\nbeen working great for us, and thanks to it we're saving lots of queries from\nthe DB, improving our performance.",[11,8205,8206,8207,8210,8211,1112,8216,8221],{},"More over, we are using ",[37,8208,7589],{"href":8149,"rel":8209},[41]," also for background jobs (i.e. exporting results,\ncomputing statistics, sending emails, etc.) thanks to\n",[37,8212,8215],{"href":8213,"rel":8214},"https://python-rq.org/",[41],"Python-RQ",[37,8217,8220],{"href":8218,"rel":8219},"https://github.com/ui/rq-scheduler",[41],"rq-scheduler","\nto run periodic jobs.",[11,8223,8224],{},"We checked Celery but it was overkilling for what we are\nbuilding and we decided again to keep things simple.",[11,8226,8227,8230,8231,8234,8235,8238],{},[37,8228,8215],{"href":8213,"rel":8229},[41]," and\n",[37,8232,8220],{"href":8218,"rel":8233},[41]," are small libraries that can be easily adapted to our\nneeds, plus we already have in our systems ",[37,8236,7589],{"href":8149,"rel":8237},[41]," so it was the best candidate\nfor us.",[29,8240,3774],{"id":3773},[11,8242,8243],{},"In summary, we're using micro frameworks to build our project paired with\na very simple infrastructure that allows us to grow\nhorizontally without problems and load balance our incoming traffic efficiently.",[11,8245,8246],{},"The next picture shows how a request goes through our current setup:",[11,8248,8249],{},[47,8250],{"alt":8251,"src":8252},"Infrastructure diagram","/img/blog/infrastructurediagram.png",[11,8254,8255,8257],{},[510,8256,1552],{},": Some people have asked about our numbers. The truth is that\nthe current setup can serve up to 2.5k rpm in less than 200ms for 1500\nusers browsing the site at the same time (we've 2 PYBOSSA servers with 2GB of RAM\nand 2 cores each, while the DBs have 4GB of RAM and 4 cores -master and slave).",[11,8259,8260],{},"In August 2014 we managed to store in our servers more than 1.5 datum per second\none day. At that moment the DB servers have only 1GB of RAM,\nand taking into account that the OS takes around 200MB of it,\nthe DBs were using only 800MB of RAM.",[15,8262,8264],{"id":8263},"deployments-ansible","Deployments & Ansible",[11,8266,8267,8268,554],{},"Up to now we've been managing all our infrastructure by hand. However, in the\nlast weeks we've been migrating our infrastructure to be completely\ncontrolled via ",[37,8269,7782],{"href":8270,"rel":8271},"https://www.ansible.com",[41],[11,8273,8274],{},"Additionally, we've developed our own in-house solution\nfor automatic deployments for all the team integrated with Github Deployments\nAPI and Slack to get notifications in our own team chat channels. Doing a\ndeployment right now consist in merging and closing a pull request. As simple\nas that.",[11,8276,8277],{},[47,8278],{"alt":49,"src":7893},[11,8280,8281,8282,8285],{},"Using ",[37,8283,7782],{"href":8270,"rel":8284},[41]," for everything has helped us to have similar playbooks reused\nacross different clients, allowing us to do faster deployments that are easy to\nmaintain, debug and deploy.",[11,8287,8288],{},"On the other hand the automatic deployments solution uses the same playbooks,\nso everything runs on the same tools and technologies.",[11,8290,8291,8292,8038,8295,8298],{},"We checked different solutions like HUBot, but we decided again to have a very\nsimple solution to integrate all these tools in our toolchain. The deployments\nserver has less than 300 lines of code, is 100% fully tested and covered, so\nit's really simple to adapt it and fix it. Moreover, it runs in the same\nservices that we are currently using: ",[37,8293,7984],{"href":7982,"rel":8294},[41],[37,8296,6718],{"href":7994,"rel":8297},[41],", so we don't have to add\nanything different to our stack.",[11,8300,8301,8303,8304,8307,8308,8311,8312,554],{},[247,8302,5148],{},": I'll write a blog post about the ",[37,8305,8306],{"href":6733},"deployments"," solution :-)\n",[510,8309,8310],{},"EDIT",": You can read about the deployment solution\n",[37,8313,7516],{"href":6733},[15,8315,8317],{"id":8316},"continuous-integration-and-code-quality","Continuous integration and code quality",[11,8319,8320],{},"We take really seriously code quality and tests. Right now we've almost 1000\ntests (953 at the time of the writing) covering almost all the source code (97%\ncovered) and with a health quality of 94%.",[11,8322,8323],{},"Our deployments solution uses the Travis-CI Github Statuses API to do the\ndeployments, so we can know for sure that it will work in our production\nsystems.",[11,8325,8326],{},"We follow the Github Flow more or less, as we don't have a versioning schema\nper se for our PYBOSSA software. What we do is that everything that it is in\nmaster is stable, as our main service runs directly from it. For this reason,\nwe take really seriously the quality of our software as a bug or an issue will\nbreak our Crowdcrafting platform.",[11,8328,8329,8330,554],{},"We usually do several deployments per week, adding new features, bug fixes,\netc. to PYBOSSA and therefore Crowdcrafting, as all the team has deployment\nrights. This has proven to be an amazing feature, as we deliver really fast\nfollowing the RERO principle: ",[37,8331,8334],{"href":8332,"rel":8333},"http://www.catb.org/esr/writings/homesteading/cathedral-bazaar/ar01s04.html",[41],"Release Early Release Often",[11,8336,8337],{},"And that's all! I hope you like it. If you have questions, please, use the\ncomments section below and I'll try to answer you. Now:",[11,8339,8340],{},[47,8341],{"alt":49,"src":8342},"https://i.giphy.com/i2p0AzumArz3i.gif",{"title":49,"searchDepth":130,"depth":130,"links":8344},[8345,8346,8347,8348,8351,8352],{"id":7962,"depth":130,"text":7963},{"id":7975,"depth":130,"text":7976},{"id":8080,"depth":130,"text":8081},{"id":8159,"depth":130,"text":8160,"children":8349},[8350],{"id":3773,"depth":135,"text":3774},{"id":8263,"depth":130,"text":8264},{"id":8316,"depth":130,"text":8317},"2015-02-10T00:00:00.000Z","Putting all your heart in what you do makes the difference. Why? Because as the\nBaron says in the movie, The Cat\nReturns, the creation is given a\nsoul.","Whenever someone creates something with all of their heart, then that creation is given a soul","engine","Sina","https://www.flickr.com/photos/limerick6/14038228238",{"excerpt":8360},{"type":8,"value":8361},[8362],[11,8363,7932,8364,7938],{},[37,8365,7937],{"href":7935,"rel":8366},[41],"/blog/en/2015-02-10-infrastructure",{"title":7927,"description":8354},"infrastructure","blog/en/2015-02-10-infrastructure","V5fRzTtxihfQ8e3CFpaCyL5aeTdUQMbv_PLy2U2OKwQ",{"id":8373,"title":8374,"author":141,"body":8375,"date":8506,"description":8507,"extension":140,"headline":141,"icon":8508,"icon_author":8509,"icon_url":8510,"layout":141,"location":6673,"meta":8511,"meta_description":8512,"navigation":145,"path":8523,"quote":141,"seo":8524,"slug":1269,"stem":8525,"tags":8526,"template":6691,"__hash__":8527},"blog/blog/en/2015-02-06-teams.md","3 steps to build a successful team",{"type":8,"value":8376,"toc":8500},[8377,8386,8390,8399,8406,8412,8415,8419,8425,8428,8434,8438,8441,8448,8454,8461,8464,8470,8474,8477,8480,8491],[11,8378,8379,8380,8230,8383,554],{},"How do you build a successful team? Moreover, how do you do it when you don't\nhave any idea about recruiting? This is my story about how I've built the\namazing team behind ",[37,8381,5650],{"href":5648,"rel":8382},[41],[37,8384,3127],{"href":3125,"rel":8385},[41],[15,8387,8389],{"id":8388},"let-others-help-you","Let others help you",[11,8391,8392,8393,8398],{},"One of the best parts of being a ",[37,8394,8397],{"href":8395,"rel":8396},"https://shuttleworthfoundation.org/",[41],"Shuttleworth\nFellow"," is that you can\nbuild a team that will help you to achieve your goals.",[11,8400,8401,8402,8405],{},"While this sounds exciting, at the same time is ",[247,8403,8404],{},"terrifying",". Why? Because\nusually, for the very first time you'll be opening the door of your home to\nstrangers.",[11,8407,8408,8409,554],{},"While I confronted this feeling I decided the following: ",[510,8410,8411],{},"if I want to build\nthe most amazing and successful team on earth, I've to trust them since the very\nbeginning; otherwise I'm doomed",[11,8413,8414],{},"With this very basic principle, I've created the following list of \"rules\" that\nI've followed to build an amazing team.",[15,8416,8418],{"id":8417},"give-them-wings-to-fly","Give them Wings to fly",[11,8420,8421,8422,554],{},"As Dalai Lama said, since the very beginning I knew one thing when I started\nrecruiting people: ",[510,8423,8424],{},"I don't want to ruin their life, I want them to grow and\nimprove with me",[11,8426,8427],{},"For this reason I encourage them to learn while they work. Learning should be one\nof the main motivations to work with the team. Why? Because if they become\nbetter in what they do, everyone wins. As simple as that, plus I know that if\nthey quit, or our project fails, they'll have lots of expertise and skills that\nwill help them in the future.",[11,8429,8430,8431,554],{},"How do I encourage them to fly? Well they've free will to decide about how they work. Any\nteam member can decide if this\nweek instead of coding, designing or writing a blog post, they prefer to test a\nfancy new methodology mentioned in Hacker News. ",[510,8432,8433],{},"That's not lost time, it's\nan investment in learning that will pay you back",[15,8435,8437],{"id":8436},"give-them-roots-to-come-back","Give them Roots to come back",[11,8439,8440],{},"In every interview I told them that since day one they will have access to\nall the services that we have. Moreover, they'll have since minute 0 deployment\nrights to do releases, even though they are starting to work with me (yes, they\ncan break everything, but I'm fine with it).",[11,8442,8443,8444,8447],{},"Why am I doing this? Because I want to show to them that ",[510,8445,8446],{},"I really trust\nthem",". If they trust you, they can do incredible things!",[11,8449,8450],{},[47,8451],{"alt":8452,"src":8453},"Trust","/img/blog/trust.gif",[11,8455,8457],{"className":8456},[5330],[37,8458,8460],{"href":8459},"http://imgur.com/gallery/hcc0iD3"," Source",[11,8462,8463],{},"One thing is saying it, and another one is proving it.",[11,8465,8466,8467,554],{},"If they're going to be part of your team, they should have access to everything\nthat matters to them. And ",[510,8468,8469],{},"trust and confidence in your work is a good reason to\ncome back",[15,8471,8473],{"id":8472},"give-them-reasons-to-stay","Give them Reasons to stay",[11,8475,8476],{},"All my team manage their own time, they decide which days they want to work,\nhow do they handle their holidays, etc. They even take days off just for\ndisconnecting and have time with their loved ones. Oh, you don't have to make\nup fancy stories to get any of those days, as I said: I trust them.",[11,8478,8479],{},"Another good reason to stay is that I encourage them to say what they really\nthink. They must know that I respect their point of view, and that I'm not\nalways right, far from that. I commit errors, but that's fine. An error is a\nstep forward for learning and improving. And showing that you commit errors, it\nwill help them to not be afraid of failing.",[11,8481,8482,8483,8486,8487,8490],{},"Thus, ",[510,8484,8485],{},"I tell them that I don't want an echo chamber",". I need to know when\nI'm wrong so I can fix it. If they are afraid of discussing\nwith me, we're done. ",[510,8488,8489],{},"Not listening to your team is one of the worst things you\ncan do",". Again, trust them!",[11,8492,8493,8496,8497],{},[247,8494,8495],{},"In the last two years I've been trying to create a place where I would love to\nwork.","\nThis place is full of people like me that love what they do, that passion is what drives them, and\nthey are always trying to improve. ",[247,8498,8499],{},"I've always imagined that perfect place to\nwork, and now -thanks to the Shuttleworth Foundation- I'm making it real.",{"title":49,"searchDepth":130,"depth":130,"links":8501},[8502,8503,8504,8505],{"id":8388,"depth":130,"text":8389},{"id":8417,"depth":130,"text":8418},{"id":8436,"depth":130,"text":8437},{"id":8472,"depth":130,"text":8473},"2015-02-06T00:00:00.000Z","How do you build a successful team? Moreover, how do you do it when you don't\nhave any idea about recruiting? This is my story about how I've built the\namazing team behind Crowdcrafting and\nPYBOSSA.","team","Yasin Hassan","https://www.flickr.com/photos/yasinhasan/4431896656/",{"to stay \u003Cbr/> Dalai Lama XIV\" headline":8512,"to stay \u003Cbr/> Dalai Lama XIV\" layout":143,"excerpt":8513},"Give the ones you love wings to fly, roots to come back and reason",{"type":8,"value":8514},[8515],[11,8516,8379,8517,8230,8520,554],{},[37,8518,5650],{"href":5648,"rel":8519},[41],[37,8521,3127],{"href":3125,"rel":8522},[41],"/blog/en/2015-02-06-teams",{"title":8374,"description":8507},"blog/en/2015-02-06-teams","team, Crowdcrafting, PYBOSSA,","sIQSfx3ciTHG_h-4ArUo9YXTJ8e0TYjBSzog1MYy23w",{"id":8529,"title":8530,"author":141,"body":8531,"date":8768,"description":8769,"extension":140,"headline":8770,"icon":8771,"icon_author":8772,"icon_url":8773,"layout":143,"location":6673,"meta":8774,"meta_description":8781,"navigation":145,"path":8782,"quote":141,"seo":8783,"slug":8784,"stem":8785,"tags":8786,"template":6691,"__hash__":8787},"blog/blog/en/2014-11-26-video-pitch.md","Video pitching one day of my life",{"type":8,"value":8532,"toc":8762},[8533,8540,8548,8556,8566,8570,8577,8599,8605,8631,8634,8638,8641,8649,8652,8658,8661,8666,8669,8672,8675,8681,8684,8693,8696,8699,8705,8709,8722,8728,8731,8740,8743,8749,8753,8756],[11,8534,8535,8536,8539],{},"Video pitching is an art. Why? Because you want to be remembered, not just\nthrown away into the pool of ",[247,8537,8538],{},"boring-nothing-new"," videos basket.",[11,8541,8542,8543,8547],{},"As ",[37,8544,8546],{"href":8545},"/blog/2014/09/22/shuttleworth-fellow","I've told you\nrecently",",\nI've been offered a second year fellowship at the\nShuttleworth Foundation, but in order to get a second year you've to pitch again\nyour project, and of course it has to have a video.",[11,8549,8550,8551,8555],{},"When I got my first year, ",[37,8552,8554],{"href":8553},"/blog/2013/09/23/video-tutorial","I blogged about it",".\nShooting was a lot of fun, but also very painful due to the software I used to\nedit the video (OpenShot if you were wondering which one).",[11,8557,8558,8559,8562,8563,554],{},"While recording a second video this year should be easier because the foundation\nalready knows me, ",[510,8560,8561],{},"I wanted to shoot a video that explained\nwho am I, and more importantly, why it matters to support me",". For these\nreasons, ",[247,8564,8565],{},"I decided to record a day of my life and show it to them",[15,8567,8569],{"id":8568},"step-0-the-script","Step 0: The script",[11,8571,8572,8573,8576],{},"If you read my ",[37,8574,8575],{"href":8553},"previous blog post","\nabout how to shoot a video, you know that you've to ask yourself the 4 Ps before writing your script:",[565,8578,8579,8584,8589,8594],{},[568,8580,8581],{},[510,8582,8583],{},"People: Who is in the story?",[568,8585,8586],{},[510,8587,8588],{},"Place: Where does the story take place?",[568,8590,8591],{},[510,8592,8593],{},"Plot: What is the conflict and the journey?",[568,8595,8596],{},[510,8597,8598],{},"Purpose: Why should anyone care about this?",[11,8600,8601,8602,3955],{},"The answer to these questions was ",[247,8603,8604],{},"more or less easy",[565,8606,8607,8613,8619,8625],{},[568,8608,8609,8612],{},[510,8610,8611],{},"People",": my team in Madrid (flying to Oxford and Hannover would be too\nmuch for my budget, hehe) and myself.",[568,8614,8615,8618],{},[510,8616,8617],{},"Place",": the places I hang out: Medialab-Prado, Jorge's office, my\nneighborhood and obviously my home.",[568,8620,8621,8624],{},[510,8622,8623],{},"Plot",": One day of my life.",[568,8626,8627,8630],{},[510,8628,8629],{},"Purpose",": To explain why is important to support me to implement my idea\nfor social change.",[11,8632,8633],{},"With these ideas in my mind, I expend a few days crafting the whole script,\nwriting it down, and discussing with my friends and family where I should shoot\nthe video.",[15,8635,8637],{"id":8636},"step-1-video-gear","Step 1: Video gear",[11,8639,8640],{},"This year I used the same camera as in the last one, my beloved Canon 550D.\nI borrowed a 35mm fixed lens to have a nice touch in the video (just because I\nlove that lens, hehe).",[11,8642,8643,8644,554],{},"As I was going to film myself walking, I needed a way to shoot the video in a\nsteady mode. As I didn't want to expend lots of money in buying a professional rig, I\ndecided to create my own following some ",[37,8645,8648],{"href":8646,"rel":8647},"https://www.youtube.com/watch?v=RNCwPDXODMs",[41],"tutorials on the web",[11,8650,8651],{},"Next photo shows the front side of the rig. The white plate is where you attach\nyour camera. You can also see the two handles to do some panning shots:",[11,8653,8654],{},[47,8655],{"alt":8656,"src":8657},"shoulder rig","/img/blog/IMG_20141126_112836.jpg",[11,8659,8660],{},"The best part of this design is that I can add weight to the back, so it gives\nyou a nice balance for the camera while you walk with it, or when you do a\npanning shots. The next photo shows how I've added to the back some weight to\ngive me a more steady movement of the camera:",[11,8662,8663],{},[47,8664],{"alt":8656,"src":8665},"/img/blog/IMG_20141126_112844.jpg",[11,8667,8668],{},"Once I built my own rig (lots of fun!), I needed to work in the microphone of the camera.\nThe problem was that I was going to be shooting in the streets, so lots of\nnoise will get through ruining the sound due a feature known as Automatic Gain\nControl (AGC).",[11,8670,8671],{},"My camera has a microphone input, but it has an issue: you cannot disable the\nAGC. This feature continuously adjusts the audio levels so\nthat loud sounds won’t overload and distort, and soft sounds won’t go unheard.",[11,8673,8674],{},"While this sounds fantastic, it actually ruins your video recordings, as you\nwill get all the ambient noise in your movie, and what you really want is to listen\nto the speakers. Hence I needed a way to disable AGC hacking the camera. My\nreaction:",[11,8676,8677],{},[47,8678],{"alt":8679,"src":8680},"Yes to all","https://i.giphy.com/aCrRttmzK1jKo.gif",[11,8682,8683],{},"Luckily Internet has the knowledge, and I found several people with the same\nissue, and they shared how you could build a small gadget to disable AGC and\nrecord sound without problems. After following one of the tutorials I built my\nanti-AGC gadget:",[11,8685,8686,8690],{},[47,8687],{"alt":8688,"src":8689},"hacking AGC","/img/blog/IMG_20140502_203554.jpg",[47,8691],{"alt":8688,"src":8692},"/img/blog/IMG_20140502_210400.jpg",[11,8694,8695],{},"While the gadget worked, sometimes failed, and nothing was recorded which was\nterrible. Thus, I decided to look for a more secure solution: borrowing a sound\nrecorder (I guess the main issue was my inexperience soldering the wires).",[11,8697,8698],{},"While my last hack didn't work out, I really loved what I learned just for\npreparing to shoot my video. At this moment, I've not shot anything yet, but I've\nwritten the script and built my own gear to start filming.",[11,8700,8701],{},[47,8702],{"alt":8703,"src":8704},"dr. evil","https://i.giphy.com/2XfswSLHgkXXa.gif",[15,8706,8708],{"id":8707},"editing-the-video","Editing the video",[11,8710,8711,8712,8717,8718,8721],{},"Last year I used ",[37,8713,8716],{"href":8714,"rel":8715},"http://www.openshot.org/",[41],"OpenShot"," and I had lots of problems.\nBasically, every time I changed anything, the software crashed. Luckily for me,\neven though it crashed\nthe status was saved, so ",[247,8719,8720],{},"I could work with it",". However, as you can imagine,\nthis was very painful as every change involved a crash, restart, wait to load\nall the video and sound clips, check the changes, do a modification and again a\ncrash.",[11,8723,8724],{},[47,8725],{"alt":8726,"src":8727},"frustrated","https://i.giphy.com/6xgslyYQCyLa8.gif",[11,8729,8730],{},"To me this was the most stressful part, as I remembered quite vividly all the\nfrustration of going through that loop with every change, so I decided to try a\ndifferent open source tool for editing the video this time.",[11,8732,8733,8734,8739],{},"The chosen one: ",[37,8735,8738],{"href":8736,"rel":8737},"http://www.blender.org/",[41],"Blender",". And all I can say: yes, finally, something that\nworks, that never crashes, and that allows me to do whatever I want to do in a\nsimple way. I'll never ever look back!!",[11,8741,8742],{},"The only downside was to learn a new tool, as it takes time and effort. However,\nthis employed time was priceless as I could modify the video without a crash,\ndo fancy filtering (even color correction), and in the future if I want, many\nmore advance techniques.",[11,8744,8745],{},[47,8746],{"alt":8747,"src":8748},"I'm so happy","https://i.giphy.com/YFIn0ICJFwGNa.gif",[15,8750,8752],{"id":8751},"making-it-personal","Making it personal",[11,8754,8755],{},"With everything in place, the only missing part was the setup for shooting the\nvideo. Where I could, I tried to control light, objects shown in the frame,\netc, etc. I wanted to tell a story not just with my words but also with the\nitems that are shown in it. The result, judge it yourself:",[2889,8757,8759],{"className":8758},[5261,5262],[2893,8760],{"src":8761,"frameBorder":2897,"allowFullScreen":145},"https://www.youtube.com/embed/rQ3yLqdEhvc",{"title":49,"searchDepth":130,"depth":130,"links":8763},[8764,8765,8766,8767],{"id":8568,"depth":130,"text":8569},{"id":8636,"depth":130,"text":8637},{"id":8707,"depth":130,"text":8708},{"id":8751,"depth":130,"text":8752},"2014-11-26T00:00:00.000Z","Video pitching is an art. Why? Because you want to be remembered, not just\nthrown away into the pool of boring-nothing-new videos basket.","Filming one day of my life to pitch why it matters to support me.","8mm","Kevin Stanchfield","https://www.flickr.com/photos/sgt_spanky/3970722137",{"excerpt":8775},{"type":8,"value":8776},[8777],[11,8778,8535,8779,8539],{},[247,8780,8538],{},"Video Pitching","/blog/en/2014-11-26-video-pitch",{"title":8530,"description":8769},"video-pitch","blog/en/2014-11-26-video-pitch","video, science, Crowdcrafting, PYBOSSA, application","qoM0ARX-CZht4OzzgODL8v7DS-kWCH1yIjRh7mNN72o",{"id":8789,"title":8790,"author":141,"body":8791,"date":8935,"description":8795,"extension":140,"headline":8936,"icon":8937,"icon_author":8938,"icon_url":8939,"layout":141,"location":8940,"meta":8941,"meta_description":8949,"navigation":145,"path":8950,"quote":141,"seo":8951,"slug":8828,"stem":8952,"tags":8953,"template":6691,"__hash__":8954},"blog/blog/en/2014-10-31-makers.md","Makers vs Craftsmen",{"type":8,"value":8792,"toc":8932},[8793,8796,8799,8812,8815,8819,8833,8839,8842,8848,8854,8857,8860,8863,8869,8875,8881,8891,8902,8909,8914,8917,8920,8923,8929],[11,8794,8795],{},"Makers are getting a lot of press coverage lately. However, I haven't read any article\nabout the craftsmen: people who also build things with their hands and tools.",[11,8797,8798],{},"Why these articles do not write about carpenters, sculptors, turners,\netc.? Is it because they don't consider them makers?",[11,8800,8801,8802,8805,8806,8811],{},"The last weekend of September I was invited to give a talk about\n",[37,8803,5650],{"href":5648,"rel":8804},[41]," at the ",[37,8807,8810],{"href":8808,"rel":8809},"http://makerfaireleon.com/makers-en-leon/",[41],"Mini Maker Fair León",". The\nevent was mostly about new ways of thinking, with a big attention to fabrication and production systems in the\nmaker community.",[11,8813,8814],{},"Between sessions I listened carefully to the maker talks. In general they\nwere about people using 3D printers (I saw again a sculpture of Yoda), laser cutters,\nand new tools that allow you to build stuff \"very easily\". However,  I felt\nthat something was missing and I was puzzled. What was I looking for?",[15,8816,8818],{"id":8817},"makers-or-should-we-say-craftsmen","Makers, or should we say Craftsmen?",[11,8820,8821,8822,8825,8826,8829,8830,554],{},"While I was approaching the booths, I realized that:\n",[510,8823,8824],{},"makers are craftsmen using new tools, nothing else",". However, the fair was\nonly filled with the new so called ",[247,8827,8828],{},"makers"," and none of the old ",[247,8831,8832],{},"craftsmen",[11,8834,8835],{},[47,8836],{"alt":8837,"src":8838},"Why","https://i.giphy.com/skXEIUJKHLrsk.gif",[11,8840,8841],{},"I think the maker community is trying to find the path for a brighter future,\nbut in my humble opinion, they are not asking to the right persons. They hang\ntogether, but they don't talk to the people that have been doing this, building stuff,\nfor centuries: carpenters, turners, sculptors, mechanics, etc. (the photo of this blog\nentry is from 1913).",[11,8843,8844,8845],{},"These guilds produce prototypes, items, products, etc. using their hands and\ntools. If we compare them with the makers, the only difference is the tools\nthey are using. ",[247,8846,8847],{},"However, I have never seen them invited to participate in these\nevents.",[11,8849,8850,8851,554],{},"Moreover, there are lots of retired people that still have a passion for making\nstuff with their own hands and tools and they don't know anything either about\nthis new maker movement. Let me give you an example. ",[247,8852,8853],{},"José Manuel Hermo Barreiro\nis a 72 years old man with a passion: building engines from scratch",[11,8855,8856],{},"Thanks to his passion, José has built the smallest V12 engine in the world\nusing only his hands and tools in his garage (does it ring a bell with you?).",[11,8858,8859],{},"José starts drawing the blueprints, then building the metal pieces -one by one- accounting all\nthe hours that takes him to create one of these marvelous engines.",[11,8861,8862],{},"In the following video he explains this process, and best of all: you can see\nand feel his passion in every word.",[2889,8864,8866],{"className":8865},[5261,5262],[2893,8867],{"src":8868,"frameBorder":2897,"allowFullScreen":145},"https://www.youtube.com/embed/c1pJIVqCC1E",[11,8870,8871,8872,554],{},"He is amazing! He has become my hero! ",[510,8873,8874],{},"I would love to meet him, talk with him just to learn from\nhis experience",[11,8876,8877,8878,554],{},"José (who started mechanics when he was 16 years old) is a master and\n",[510,8879,8880],{},"it is a pity that his knowledge is getting lost",[11,8882,8883,8884,8890],{},"In the video, he says: ",[510,8885,8886,8887,8889],{},"\"engineers lack the inventiveness to repair a piece or\nfind an alternative for it, ",[224,8888,6604],{}," they don't wonder why it broke\"."," It touched my\nheart, because sadly I endorse his words.",[11,8892,8893,8894,8897,8898,8901],{},"To me José is a maker, but I don't think he would describe himself as a\n",[247,8895,8896],{},"maker",". ",[510,8899,8900],{},"José is an artisan, a craftsman that knows how to build\namazing engines in his garage",". In other words, he shares the same passion and\npurpose as thousands of makers with only one tiny difference: they use\ndifferent tools, that's all.",[11,8903,8904,8905,8908],{},"Like José there are hundreds of retired persons that to me are the voice of\nthe experience. These people really know how to\nsolve problems and they say that ",[247,8906,8907],{},"new generations do not have the\ninventiveness to solve them",", so wouldn't be nice to invite them to next Maker\nfair?",[11,8910,8911],{},[510,8912,8913],{},"I think it is crucial for the maker and 3D printing communities to connect with the old generations that keep building stuff in their garages.",[11,8915,8916],{},"Listening to people like José will open the door to pure knowledge.\nNew generations will learn how they solve problems in the past, which tools\nwere used and more importantly see their passion and gentleness for their work.",[11,8918,8919],{},"Moreover, old generations will discover new tools for their developments and\ntogether they will improve the production chains that will lead to better\nprototypes.",[11,8921,8922],{},"For these reasons I want to make a proposition to the Mini Maker Fair Leon\norganizers (well, this is actually a proposition to anyone that organizes Maker\nfairs, events, workshops, etc.):",[11,8924,8925,8928],{},[510,8926,8927],{},"I would love to co-organize a new fair where retired craftsmen and makers\ntalk to each other sharing their knowledge",". I would love to see José giving a talk\nabout how he builds his engines, participate in a workshop where he shows how\nhe produces them so the makers can adapt those methodologies to their 3D\nprinters and CNC machines.",[11,8930,8931],{},"I would love to see how retired people take a more active role in teaching\nwhat they have learned in their life, so us, you and me, can learn and become\nbetter professionals in what we do. It's a crime losing these knowledge and us,\nthe society, should include them as they have a lot to teach.",{"title":49,"searchDepth":130,"depth":130,"links":8933},[8934],{"id":8817,"depth":130,"text":8818},"2014-10-31T00:00:00.000Z","Engineers lack the inventiveness to repair a piece or find a","carpenter","Richard","https://www.flickr.com/photos/rich701/8110384009","León, Spain",{"alternative for it, they don't wonder why it broke":8942,"excerpt":8943},{"\" layout":143},{"type":8,"value":8944},[8945,8947],[11,8946,8795],{},[11,8948,8798],{},"Makers on the go","/blog/en/2014-10-31-makers",{"title":8790,"description":8795},"blog/en/2014-10-31-makers","fabrication, science, Crowdcrafting, PYBOSSA, makers","08XhVGQRE-s0DUydGykBRiL2FzFIPMiuKrI__l-hvfQ",{"id":8956,"title":8957,"author":141,"body":8958,"date":9296,"description":9297,"extension":140,"headline":9298,"icon":9299,"icon_author":9300,"icon_url":9301,"layout":143,"location":6673,"meta":9302,"meta_description":9315,"navigation":145,"path":9316,"quote":141,"seo":9317,"slug":9318,"stem":9319,"tags":9320,"template":6691,"__hash__":9321},"blog/blog/en/2014-09-22-shuttleworth-fellow.md","Year in review as a Shuttleworth Fellow",{"type":8,"value":8959,"toc":9290},[8960,8969,8977,8981,8995,9001,9004,9011,9016,9021,9024,9026,9038,9048,9052,9079,9085,9099,9102,9110,9113,9117,9125,9140,9146,9152,9172,9189,9191,9200,9213,9215,9249,9256,9263,9278,9284,9287],[11,8961,8962,8963,8968],{},"One year ago I started a ",[37,8964,8967],{"href":8965,"rel":8966},"https://shuttleworthfoundation.org",[41],"fellowship"," that\nchanged my life.",[11,8970,8971,8972,8976],{},"One year later, the ",[37,8973,8975],{"href":8965,"rel":8974},[41],"Shuttleworth\nFoundation"," has renewed my fellowship for\nanother year. Amazing!",[15,8978,8980],{"id":8979},"becoming-a-fellow","Becoming a fellow",[11,8982,8983,8984,8989,8990,8994],{},"One of the most interesting aspects of pitching to Shuttleworth Foundation is\nthe ",[37,8985,8988],{"href":8986,"rel":8987},"https://shuttleworthfoundation.org/applications/",[41],"video pitch",". Last year,\nI wrote a ",[37,8991,8993],{"href":8992},"/blog/2013/09/23/video-tutorial.html","blog post about it"," explaining\nhow I shot that video.",[11,8996,8997,9000],{},[247,8998,8999],{},"The video is a very interesting exercise",", as you are forced to express your\nideas in a very succinct way, as you only have 5 minutes, and you have to use\nthem wisely.",[11,9002,9003],{},"My first video was done in two days, and I loved the result, however I needed\nsomething better for my second year.",[11,9005,9006,9007,9010],{},"I wanted to show ",[247,9008,9009],{},"how much I love my work",",\nwho am I, and what do I do thanks to the foundation's support. The result?\nWell, judge it yourself (please leave me a comment about the video):",[2889,9012,9014],{"className":9013},[5261,5262],[2893,9015],{"src":8761,"frameBorder":2897,"allowFullScreen":145},[11,9017,9018],{},[247,9019,9020],{},"I'll write another blog post about the video and its creation. I promise.",[11,9022,9023],{},"The foundation liked it, and I have another year to do many more things thanks\nto their support.",[15,9025,3643],{"id":6320},[11,9027,9028,9029,9033,9034,554],{},"The first fellowship year helped me to have a ",[37,9030,8508],{"href":9031,"rel":9032},"https://pybossa.com/about/",[41],"\nof awesome people. Thanks to the their support, I've managed to\nhire a UX person (to me he's the best in the world), two developers (that work\nreally hard and love what they do), and a young communications person (who writes\nawesome blog posts about our work) -don't be shy and check our ",[37,9035,9037],{"href":9031,"rel":9036},[41],"team\npage",[11,9039,9040,9041,8230,9044,9047],{},"Now, with a team behind ",[37,9042,3127],{"href":3125,"rel":9043},[41],[37,9045,5650],{"href":5648,"rel":9046},[41],", I could move quickly, learn from the\nteam, attend more meatings, develope new features and make Crowdcrafting a place\nto hang out for citizen scientists.",[15,9049,9051],{"id":9050},"growing-step-by-step","Growing step by step",[11,9053,9054,9055,9060,9061,9066,9067,9070,9071],{},"While we were working, we got a great opportunity: the ",[37,9056,9059],{"href":9057,"rel":9058},"http://www.britishmuseum.org/",[41],"British\nMuseum"," and the ",[37,9062,9065],{"href":9063,"rel":9064},"https://www.ucl.ac.uk/",[41],"UCL","\nwere interested in ",[37,9068,3127],{"href":3125,"rel":9069},[41]," and more importantly: ",[247,9072,9073,9074,554],{},"they\nwanted to use it for their ",[37,9075,9078],{"href":9076,"rel":9077},"https://micropasts.org/",[41],"own citizen science project",[11,9080,9081],{},[47,9082],{"alt":9083,"src":9084},"Happy animated gif","https://i.giphy.com/13k4VSc3ngLPUY.gif",[11,9086,9087,9088,9093,9094,9098],{},"In April of 2014, the project was launched with great ",[37,9089,9092],{"href":9090,"rel":9091},"https://www.ucl.ac.uk/news/news-articles/0414/160414-crowdsourcing-bronze-age",[41],"coverage","\nfrom the\n",[37,9095,3875],{"href":9096,"rel":9097},"https://www.theguardian.com/science/2014/aug/18/volunteers-british-museum-crowdsourcing-archeology",[41],".\nAt the time of this writing, the project has managed to have more than 1\nthousand contributors with 18 published projects. Awesome!",[11,9100,9101],{},"We worked with them closely to build two templates that have being used to build\nthe 18 projects:",[565,9103,9104,9107],{},[568,9105,9106],{},"a transcription template to make available a huge card catalogue of British\nprehistoric metal artefacts discovered in the 19th and 20th century, and",[568,9108,9109],{},"a template that enables the creation of a high quality 3D model of an\narchaeological artefact via process known as photo-masking.",[11,9111,9112],{},"I'm really proud of the work done for this project and its successthe work done\nfor this. This achievement has proved that PYBOSSA is mature to be used as a\ntool for doing citizen science, and more importantly that international\ninstitutions trust our software, tools and methodologies.",[15,9114,9116],{"id":9115},"exciting-times-ahead","Exciting times ahead",[11,9118,9119,9120,9124],{},"I collaborate with the ",[37,9121,5692],{"href":9122,"rel":9123},"https://medialab-prado.es",[41]," institution\nin Madrid, Spain, and I coordinate there the citizen science workstation. As\npart of my collaboration, we organize international workshops where anyone can\npitch their project. If the project is interesting, it gets accepted, and a\ngroup of collaborators join you to collaborate.",[11,9126,9127,9128,9133,9134,9139],{},"In one of these\n",[37,9129,9132],{"href":9130,"rel":9131},"https://medialab-prado.es/article/madridlaboratoriourbano",[41],"calls",", a research\ngroup from the ",[37,9135,9138],{"href":9136,"rel":9137},"http://guaix.fis.ucm.es/node/1651",[41],"Complutense University","\napplied to create a citizen science project to analyze the light pollution of\ncities. The interesting part: they wanted to use photographs taken directly\nfrom the International Space Station by astronauts!",[11,9141,9142,9143],{},"Cool, right? And best of all: ",[247,9144,9145],{},"they wanted to use Crowdcrafting for developing\nthe project!!!",[11,9147,9148],{},[47,9149],{"alt":9150,"src":9151},"Oh My God GIF","https://i.giphy.com/QMcamps7Gzj2g.gif",[11,9153,9154,9155,9160,9161,8230,9166,9171],{},"The project was accepted and left beta in July. In this month the research\ngroup sent out a ",[37,9156,9159],{"href":9157,"rel":9158},"https://www.ucm.es/data/cont/media/www/pag-56948/Atlas%20de%20im%C3%A1genes%20nocturnas%20DEFbuena.pdf",[41],"press release about the\nproject",".\nThe press release was sent to ",[37,9162,9165],{"href":9163,"rel":9164},"https://www.nasa.gov/",[41],"NASA",[37,9167,9170],{"href":9168,"rel":9169},"http://www.esa.int/ESA",[41],"ESA"," and they supported the project with\ntweets like this one from ESA:",[6330,9173,9175,6539,9187],{"className":9174,"lang":6511,"align":6512},[6510],[11,9176,9177,6519,9179,6524,9181,6529,9183,6534,9185],{},[37,9178,6518],{"href":6517},[37,9180,6523],{"href":6522},[37,9182,6528],{"href":6527},[37,9184,6533],{"href":6532},[37,9186,6538],{"href":6537},[37,9188,6543],{"href":6542},[4103,9190],{"async":145,"src":6546,"charSet":6547},[11,9192,9193,9194,9199],{},"Then, the unexpected happened. NASA wrote a ",[37,9195,9198],{"href":9196,"rel":9197},"https://www.nasa.gov/mission_pages/station/research/news/crowdsourcing_night_images/#.U-zmA_ldWSo",[41],"full\narticle","\nabout the project and obviously tweeted it:",[6330,9201,9203,6575,9211],{"className":9202,"lang":6511,"align":6512},[6510],[11,9204,6562,9205,6566,9207,1592,9209],{},[37,9206,6565],{"href":6565},[37,9208,6570],{"href":6569},[37,9210,6574],{"href":6573},[37,9212,6579],{"href":6578},[4103,9214],{"async":145,"src":6546,"charSet":6547},[11,9216,9217,9218,4292,9223,4292,9228,4292,9233,4292,9236,1319,9240,4292,9245,554],{},"The result? Well lots of international media mentioned the project like\n",[37,9219,9222],{"href":9220,"rel":9221},"http://www.popsci.com/blog-network/do-try-home/join-crowd",[41],"Popsci",[37,9224,9227],{"href":9225,"rel":9226},"http://www.fastcoexist.com/3033228/these-incredible-photos-from-astronauts-show-the-brightest-cities-on-earth",[41],"Co.Exists",[37,9229,9232],{"href":9230,"rel":9231},"http://www.nbcnews.com/science/space/scientists-want-you-help-crowdsource-night-lights-n181116",[41],"NBC\nNews",[37,9234,6599],{"href":6597,"rel":9235},[41],[37,9237,6594],{"href":9238,"rel":9239},"https://gizmodo.com/",[41],[37,9241,9244],{"href":9242,"rel":9243},"http://www.smithsonianmag.com/smart-news/help-nasa-out-looking-beautiful-pictures-space-180952407/?no-ist",[41],"Smithsonian\nMagazine",[37,9246,9248],{"href":6602,"rel":9247},[41],"etc",[11,9250,9251,9252,9255],{},"Amazing right? Well, this was not yet the best part. Trust me. The 21 of\nAugust, FOX News TV showed on prime time\n",[37,9253,5650],{"href":5648,"rel":9254},[41]," and how to contribute to the\nproject:",[2889,9257,9259],{"className":9258},[5261,5262],[2893,9260],{"src":9261,"style":9262},"https://video.foxnews.com/v/video-embed.html?video_id=3742323090001","border:0",[11,9264,9265,9266,1592,9269,9272,9273,5431],{},"Thanks to this ",[247,9267,9268],{},"amazing coverage",[510,9270,9271],{},"Crowdcrafting stored in one single day more than one\nanswer per second",", with thousands of new volunteers registering in the site\nand thousands of tasks completed in hours! (check the\n",[37,9274,9277],{"href":9275,"rel":9276},"https://web.archive.org/web/2019/http://crowdcrafting.org/app/darkskies/stats",[41],"statistics",[11,9279,9280],{},[47,9281],{"alt":9282,"src":9283},"Despicable Me Minion OMG","https://i.giphy.com/CHyxN9bNkMc3S.gif",[11,9285,9286],{},"Since then, we have had new users registering every day, tasks completed every\nday, and lots of contributions from volunteers. Amazing!",[11,9288,9289],{},"And this has happened only in the first year of my fellowship, so what will\nbring my second year? Really looking into it!!!!",{"title":49,"searchDepth":130,"depth":130,"links":9291},[9292,9293,9294,9295],{"id":8979,"depth":130,"text":8980},{"id":6320,"depth":130,"text":3643},{"id":9050,"depth":130,"text":9051},{"id":9115,"depth":130,"text":9116},"2014-09-22T00:00:00.000Z","One year ago I started a fellowship that\nchanged my life.","Being a Shuttleworth Fellow has changed my life forever.","open","Open Source","https://www.flickr.com/photos/opensourceway/7496803264",{"excerpt":9303},{"type":8,"value":9304},[9305,9310],[11,9306,8962,9307,8968],{},[37,9308,8967],{"href":8965,"rel":9309},[41],[11,9311,8971,9312,8976],{},[37,9313,8975],{"href":8965,"rel":9314},[41],"Shuttleworth Fellow","/blog/en/2014-09-22-shuttleworth-fellow",{"title":8957,"description":9297},"shuttleworth-fellow","blog/en/2014-09-22-shuttleworth-fellow","citizen science, open source, PYBOSSA, tools, shuttleworth","TalXx134IP8OkAZxtdVmn_6v0z-xjSmc1REzJCwS95g",{"id":9323,"title":9324,"author":141,"body":9325,"date":9755,"description":9329,"extension":140,"headline":9756,"icon":9757,"icon_author":9758,"icon_url":9759,"layout":143,"location":6673,"meta":9760,"meta_description":9324,"navigation":145,"path":9769,"quote":141,"seo":9770,"slug":9771,"stem":9772,"tags":9773,"template":6691,"__hash__":9774},"blog/blog/en/2014-07-04-commandline-candy-for-pybossa.md","Command line candy for PYBOSSA",{"type":8,"value":9326,"toc":9743},[9327,9330,9337,9341,9356,9361,9368,9372,9382,9397,9403,9407,9410,9413,9420,9486,9496,9499,9503,9510,9572,9575,9586,9589,9593,9600,9607,9610,9630,9637,9641,9644,9647,9664,9667,9678,9681,9699,9703,9711,9714,9717,9723,9727,9733,9740],[11,9328,9329],{},"PYBOSSA is a great framework, however we were lacking a nice command line tool to\ninteract with it.",[11,9331,9332,9333,9336],{},"For this reason, after providing several different scripts to create projects, add\ntasks, etc, etc. I've decided to finally create a ",[510,9334,9335],{},"simple"," command line tool to\nmaster the PYBOSSA API.",[15,9338,9340],{"id":9339},"pbs-mastering-pybossa-api","pbs - mastering PYBOSSA API",[11,9342,9343,9344,9349,9350,9355],{},"As I wanted to create a powerful but simple tool to manage PYBOSSA projects via the\ncommand line, I looked for different solutions: argparse, docopt, etc. From all the\navailable solutions I found ",[37,9345,9348],{"href":9346,"rel":9347},"http://click.pocoo.org/",[41],"Click"," from\n",[37,9351,9354],{"href":9352,"rel":9353},"http://lucumr.pocoo.org/",[41],"Armin Ronacher"," and after trying it I was simply AMAZED.",[11,9357,9358],{},[247,9359,9360],{},"Click is really powerful, simple and its feature for nesting commands is incredible.",[11,9362,9363,9364,9367],{},"Thanks to Click I've managed to develop a command line tool for PYBOSSA in two days,\nthat behaves more or less like ",[247,9365,9366],{},"git"," with commands, sub-commands and --help options\nto make your life much simpler!",[15,9369,9371],{"id":9370},"installing-pbs","Installing pbs",[11,9373,9374,9375,9377,9378,9381],{},"Installing ",[247,9376,7434],{}," is very simple. Just install it with ",[510,9379,9380],{},"pip"," with the following command:",[2914,9383,9385],{"className":6770,"code":9384,"language":6772,"meta":49,"style":49},"pip install pybossa-pbs\n",[1539,9386,9387],{"__ignoreMap":49},[224,9388,9389,9391,9394],{"class":3942,"line":3943},[224,9390,9380],{"class":4224},[224,9392,9393],{"class":3958}," install",[224,9395,9396],{"class":3958}," pybossa-pbs\n",[11,9398,9399,9400,554],{},"Then all the magic happens ",[5823,9401],{"className":9402},[5826,6287],[15,9404,9406],{"id":9405},"configuring-pbs","Configuring pbs",[11,9408,9409],{},"I've designed pbs to be very flexible, so all the options can be passed as arguments,\ngiving you all the flexibility that you could need.",[11,9411,9412],{},"One of the key aspects that I love from pbs is the possibility of having a config file\nfor storing my credentials for different PYBOSSA servers. This simplifies my life,\nreduces the ammount of typing and I don't have to check all the time my API-KEY in the\nservers that I'm using :-)",[11,9414,9415,9416,9419],{},"The config file is very simple. It's just a file named ",[510,9417,9418],{},".pybossa.cfg"," that looks something\nlike this:",[2914,9421,9424],{"className":9422,"code":9423,"language":7467,"meta":49,"style":49},"language-python shiki shiki-themes catppuccin-latte catppuccin-mocha","[default]\nserver: yourserver\napikey: yourkey\n\n[anotherserver]\nserver: youranotherserver\napikey: youranotherkey\n",[1539,9425,9426,9435,9445,9455,9459,9468,9477],{"__ignoreMap":49},[224,9427,9428,9430,9433],{"class":3942,"line":3943},[224,9429,4504],{"class":3946},[224,9431,9432],{"class":4019},"default",[224,9434,6784],{"class":3946},[224,9436,9437,9440,9442],{"class":3942,"line":130},[224,9438,9439],{"class":4019},"server",[224,9441,3955],{"class":3946},[224,9443,9444],{"class":4019}," yourserver\n",[224,9446,9447,9450,9452],{"class":3942,"line":135},[224,9448,9449],{"class":4019},"apikey",[224,9451,3955],{"class":3946},[224,9453,9454],{"class":4019}," yourkey\n",[224,9456,9457],{"class":3942,"line":3982},[224,9458,4694],{"emptyLinePlaceholder":145},[224,9460,9461,9463,9466],{"class":3942,"line":3993},[224,9462,4504],{"class":3946},[224,9464,9465],{"class":4019},"anotherserver",[224,9467,6784],{"class":3946},[224,9469,9470,9472,9474],{"class":3942,"line":4042},[224,9471,9439],{"class":4019},[224,9473,3955],{"class":3946},[224,9475,9476],{"class":4019}," youranotherserver\n",[224,9478,9479,9481,9483],{"class":3942,"line":4072},[224,9480,9449],{"class":4019},[224,9482,3955],{"class":3946},[224,9484,9485],{"class":4019}," youranotherkey\n",[11,9487,9488,9489,9491,9492,9495],{},"By default, pbs will use the ",[247,9490,9432],{}," section, but if you want to authenticate against\nanother server, all you've to do is to pass the following command line option: ",[510,9493,9494],{},"--credentials anotherserver",".\nDone!",[11,9497,9498],{},"You don't actually need that file, but if you are working a lot with PYBOSSA I would\nrecommend you to create it. It's really amazing.",[15,9500,9502],{"id":9501},"creating-a-project","Creating a project",[11,9504,9505,9506,9509],{},"Now that we've pbs configured all we've to do is to create a project. Creating a project\nis as simple as always. All you need is a ",[510,9507,9508],{},"project.json"," with something like this:",[2914,9511,9515],{"className":9512,"code":9513,"language":9514,"meta":49,"style":49},"language-json shiki shiki-themes catppuccin-latte catppuccin-mocha","{\n   \"name\": \"Name of your application\",\n   \"short_name\": \"theslug\",\n   \"description\": \"description\"\n}\n","json",[1539,9516,9517,9521,9538,9554,9568],{"__ignoreMap":49},[224,9518,9519],{"class":3942,"line":3943},[224,9520,4936],{"class":3946},[224,9522,9523,9526,9529,9531,9533,9536],{"class":3942,"line":130},[224,9524,9525],{"class":3946},"   \"",[224,9527,9528],{"class":3950},"name",[224,9530,1585],{"class":3946},[224,9532,3955],{"class":3946},[224,9534,9535],{"class":3958}," \"Name of your application\"",[224,9537,4292],{"class":3946},[224,9539,9540,9542,9545,9547,9549,9552],{"class":3942,"line":135},[224,9541,9525],{"class":3946},[224,9543,9544],{"class":3950},"short_name",[224,9546,1585],{"class":3946},[224,9548,3955],{"class":3946},[224,9550,9551],{"class":3958}," \"theslug\"",[224,9553,4292],{"class":3946},[224,9555,9556,9558,9561,9563,9565],{"class":3942,"line":3982},[224,9557,9525],{"class":3946},[224,9559,9560],{"class":3950},"description",[224,9562,1585],{"class":3946},[224,9564,3955],{"class":3946},[224,9566,9567],{"class":3958}," \"description\"\n",[224,9569,9570],{"class":3942,"line":3993},[224,9571,4824],{"class":3946},[11,9573,9574],{},"Then, if you run pbs from the same folder where that file has been created, all you've\nto do for creating a project is running the following command:",[2914,9576,9578],{"className":6770,"code":9577,"language":6772,"meta":49,"style":49},"pbs create_project\n",[1539,9579,9580],{"__ignoreMap":49},[224,9581,9582,9584],{"class":3942,"line":3943},[224,9583,7434],{"class":4224},[224,9585,7443],{"class":3958},[11,9587,9588],{},"Two words, and your project is created!",[15,9590,9592],{"id":9591},"adding-tasks","Adding tasks",[11,9594,9595,9596,9599],{},"Now that we've our project available in the server, we can add tasks to it. With pbs\nI wanted to allow users to import tasks from PYBOSSA servers without having to do\nnothing special. If you visit a project in ",[37,9597,5650],{"href":5648,"rel":9598},[41],"\nyou will see that right now PYBOSSA allows you to download tasks as files in two\ndifferent formats: CSV and JSON.",[11,9601,9602,9603,9606],{},"Once you've downloaded one set of tasks from Crowdcrafting, pbs allows you to ",[510,9604,9605],{},"re-use","\nthe data, as all the projects are using an open-data license. Cool, right?",[11,9608,9609],{},"How do you re-use the tasks's file? If you've downloaded the tasks in CSV format, all\nyou have to do is running the following command:",[2914,9611,9613],{"className":6770,"code":9612,"language":6772,"meta":49,"style":49},"pbs add_tasks --tasks-file file --tasks-type=csv\n",[1539,9614,9615],{"__ignoreMap":49},[224,9616,9617,9619,9621,9624,9627],{"class":3942,"line":3943},[224,9618,7434],{"class":4224},[224,9620,7481],{"class":3958},[224,9622,9623],{"class":3958}," --tasks-file",[224,9625,9626],{"class":3958}," file",[224,9628,9629],{"class":3958}," --tasks-type=csv\n",[11,9631,9632,9633,9636],{},"Done! ",[510,9634,9635],{},"You've even a progress bar and if you have more than 300 tasks, pbs will auto\nenable the throttling to respect the PYBOSSA limits of the server."," I love this ;-)",[15,9638,9640],{"id":9639},"adding-the-task-presenter-long-description-and-tutorial","Adding the task presenter, long description and tutorial",[11,9642,9643],{},"Now, all we've to do is to add the tutorial, task presenter and long description.",[11,9645,9646],{},"For adding those files to the project, you can have those files created in a folder,\nwith the following names:",[565,9648,9649,9654,9659],{},[568,9650,9651],{},[510,9652,9653],{},"template.html",[568,9655,9656],{},[510,9657,9658],{},"lon_description.md",[568,9660,9661],{},[510,9662,9663],{},"tutorial.html",[11,9665,9666],{},"If those file names exist where you are running the command, then you don't have to\ntype almost anything, just this command:",[2914,9668,9670],{"className":6770,"code":9669,"language":6772,"meta":49,"style":49},"pbs update_project\n",[1539,9671,9672],{"__ignoreMap":49},[224,9673,9674,9676],{"class":3942,"line":3943},[224,9675,7434],{"class":4224},[224,9677,7454],{"class":3958},[11,9679,9680],{},"Done! Quick, fast and simple. If you are testing something new, or if you want to\nreuse a template from another project, all you've to do is tell it to pbs:",[2914,9682,9684],{"className":6770,"code":9683,"language":6772,"meta":49,"style":49},"pbs update_project --task-template /path/to/template.html\n",[1539,9685,9686],{"__ignoreMap":49},[224,9687,9688,9690,9693,9696],{"class":3942,"line":3943},[224,9689,7434],{"class":4224},[224,9691,9692],{"class":3958}," update_project",[224,9694,9695],{"class":3958}," --task-template",[224,9697,9698],{"class":3958}," /path/to/template.html\n",[15,9700,9702],{"id":9701},"an-example","An example",[11,9704,9705,9706,554],{},"In the following video you can see how quickly you can create a project in\nCrowdcrafting (or any PYBOSSA server) using pbs with the ",[37,9707,9710],{"href":9708,"rel":9709},"https://github.com/PYBOSSA/app-flickrperson/",[41],"Flickr Person Finder template",[11,9712,9713],{},"Enjoy!",[29,9715,9371],{"id":9716},"installing-pbs-1",[2889,9718,9720],{"className":9719},[5261,5262],[2893,9721],{"src":9722,"frameBorder":2897,"webkitallowfullscreen":49,"mozallowfullscreen":49,"allowFullScreen":145},"https://player.vimeo.com/video/99921525",[29,9724,9726],{"id":9725},"creating-a-project-and-adding-tasks","Creating a project and adding tasks",[2889,9728,9730],{"className":9729},[5261,5262],[2893,9731],{"src":9732,"frameBorder":2897,"webkitallowfullscreen":49,"mozallowfullscreen":49,"allowFullScreen":145},"https://player.vimeo.com/video/99921526",[11,9734,9735,9736,554],{},"PS: I almost forgot to mention it: everything is open source and you can check the\nsource code ",[37,9737,7516],{"href":9738,"rel":9739},"https://github.com/PYBOSSA/pbs/",[41],[5130,9741,9742],{},"html pre.shiki code .sMmZK, html code.shiki .sMmZK{--shiki-default:#1E66F5;--shiki-default-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic}html pre.shiki code .sgueU, html code.shiki .sgueU{--shiki-default:#40A02B;--shiki-dark:#A6E3A1}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sxyLT, html code.shiki .sxyLT{--shiki-default:#7C7F93;--shiki-dark:#9399B2}html pre.shiki code .s0aCy, html code.shiki .s0aCy{--shiki-default:#4C4F69;--shiki-dark:#CDD6F4}html pre.shiki code .sS0zD, html code.shiki .sS0zD{--shiki-default:#1E66F5;--shiki-dark:#89B4FA}",{"title":49,"searchDepth":130,"depth":130,"links":9744},[9745,9746,9747,9748,9749,9750,9751],{"id":9339,"depth":130,"text":9340},{"id":9370,"depth":130,"text":9371},{"id":9405,"depth":130,"text":9406},{"id":9501,"depth":130,"text":9502},{"id":9591,"depth":130,"text":9592},{"id":9639,"depth":130,"text":9640},{"id":9701,"depth":130,"text":9702,"children":9752},[9753,9754],{"id":9716,"depth":135,"text":9371},{"id":9725,"depth":135,"text":9726},"2014-07-04T00:00:00.000Z","Managing a PYBOSSA project was never so easy.","candy","Lost in space","https://www.flickr.com/photos/gentagrafie/12723952215/",{"excerpt":9761},{"type":8,"value":9762},[9763,9765],[11,9764,9329],{},[11,9766,9332,9767,9336],{},[510,9768,9335],{},"/blog/en/2014-07-04-commandline-candy-for-pybossa",{"title":9324,"description":9329},"commandline-candy-for-pybossa","blog/en/2014-07-04-commandline-candy-for-pybossa","citizen science, open source, PYBOSSA, tools","02pxlgEJrEVDavyv18PgvPDE5BlMEVzme10emfIS4_k",{"id":9776,"title":9777,"author":141,"body":9778,"date":9983,"description":9984,"extension":140,"headline":9985,"icon":9986,"icon_author":9987,"icon_url":9988,"layout":143,"location":9989,"meta":9990,"meta_description":9777,"navigation":145,"path":10006,"quote":141,"seo":10007,"slug":10008,"stem":10009,"tags":10010,"template":6691,"__hash__":10011},"blog/blog/en/2014-02-26-reinventing-the-wheel.md","Reinventing the wheel",{"type":8,"value":9779,"toc":9981},[9780,9786,9789,9799,9806,9809,9815,9827,9837,9847,9858,9861,9870,9873,9882,9885,9888,9893,9902,9908,9925,9928,9940,9952,9968,9978],[11,9781,9782,9783,554],{},"In the last three days I've participated in the third ",[37,9784,6395],{"href":6393,"rel":9785},[41],[11,9787,9788],{},"The event has been the biggest so far, and you could appreciate it not only in the number of people, but also in the number of new projects coming out from the crowd.",[11,9790,9791,9792,9795,9796],{},"After several talks and workshops you could actually see a trend: ",[510,9793,9794],{},"different groups are reinventing the wheel",". Now the obligated question: ",[510,9797,9798],{},"is this a good or a bad thing?",[11,9800,9801,9802,9805],{},"Before going forward, let me be clear, in my personal case I'm doing the same, I'm developing ",[247,9803,9804],{},"another"," citizen science framework, so to some extent I'm contributing to reinventing the wheel, right?",[11,9807,9808],{},"Reinventing the wheel is not new to me. I'm a GNU/Linux user since Red Hat 5.2 and I can say that I've heard the same argument several times in the open source community: another window manager? This is the year for GNU/Linux.",[11,9810,9811],{},[47,9812],{"alt":9813,"src":9814},"meme","https://i.imgur.com/JBYFSxa.png",[11,9816,9817,9818,1112,9822,9826],{},"If you want to check what I'm saying, all you have to do is the following: search in Google the name of an open source project, go to its e-mail list and your chances of finding a heated discussion about this specific issue are high, quite high (just check the last controversy about SystemD vs Upstart ",[37,9819,7516],{"href":9820,"rel":9821},"http://www.reddit.com/r/linux/comments/1w9qtv/the_design_flaws_of_upstart/",[41],[37,9823,7516],{"href":9824,"rel":9825},"http://ewontfix.com/14/",[41]," as two different points of view).",[11,9828,9829,9830,9833,9834,554],{},"While I'm used to this type of controversy, the truth is that ",[247,9831,9832],{},"I've not been thinking really carefully about it, until the conference",". In the summit we have had the same conversations, everyone complaining about reinventing the wheel but all of us creating our own wheel and saying to the rest of the world: ",[510,9835,9836],{},"this IS THE wheel",[11,9838,9839,9840,8897,9843,9846],{},"Moreover, ",[510,9841,9842],{},"it looks like for everyone reinventing the wheel is something bad",[510,9844,9845],{},"But is it really bad?"," Have you think about it carefully?",[11,9848,9849,9850,9853,9854,9857],{},"One of the most used arguments to say that ",[510,9851,9852],{},"reinventing the wheel"," is something bad, is that it is a ",[510,9855,9856],{},"waste of energy and resources",", repeating almost exactly the same features. The point is that: both solutions should join forces and build a better unified solution.",[11,9859,9860],{},"What do you think? Is it a waste of time, energy and resources? My answer: yes, it is, but is this enough to stop trying reinventing the wheel?",[11,9862,9863,9864,9869],{},"During these three days I've thinking about all these issues and I've realized that when we are arguing about it, what we are actually doing is describing ",[37,9865,9868],{"href":9866,"rel":9867},"https://en.wikipedia.org/wiki/On_the_Origin_of_Species",[41],"the evolution of species"," (thanks Darwin!).",[11,9871,9872],{},"Yes, you have read it right: the evolution of species. Let me explain it to you.",[11,9874,9875,9876,9878,9879,554],{},"Let's pick a topic completely randomly (cough): ",[247,9877,6405],{},". Now let's pick a problem within it: ",[247,9880,9881],{},"developing a citizen science framework",[11,9883,9884],{},"Developing the best possible and imaginable citizen science framework is challenging, right? Thus, we can say that finding a solution is going to be complicated, really difficult.",[11,9886,9887],{},"Let's imagine that the perfect framework exists. However, we do not know where it is, or how it looks like. For this reason we have a huge search space. Really big (deep space). Even though it looks like it is almost impossible to find a solution, some people will try and start building their own solution.",[11,9889,9890],{},[47,9891],{"alt":9813,"src":9892},"https://i.imgur.com/tn0NZMx.png",[11,9894,9895,9896,9901],{},"As with every new born, the very first version is not going to be the best one, it lacks a lot of features, fails a lot, and has a very small community (generation zero). While this team is developing their solution, another group starts something similar without even knowing anything about the previous work. Interestingly, they are focused on the same goals, and therefore they will build similar solutions: they share some ",[37,9897,9900],{"href":9898,"rel":9899},"http://ieeexplore.ieee.org/xpl/login.jsp?tp=&arnumber=4983245&url=http%3A%2F%2Fieeexplore.ieee.org%2Fxpls%2Fabs_all.jsp%3Farnumber%3D4983245",[41],"building blocks",". In other words, they are reinventing the wheel.",[11,9903,9904,9907],{},[510,9905,9906],{},"But the truth is that even though they share some building blocks, both projects are not quite the same",". They have their own unique features: how the project is handled, the employed technology, the community around it, etc, etc.",[11,9909,9910,9911,9914,9915,9918,9919,9924],{},"In summary we have two individuals (aka as candidate solutions) looking to ",[510,9912,9913],{},"survive"," in the field of citizen science. In order to know which solution is the best one, we have a fitness function that can compare them: i.e. ",[510,9916,9917],{},"sustainability",". At this point you might realize that what I'm describing it is an ",[37,9920,9923],{"href":9921,"rel":9922},"https://en.wikipedia.org/wiki/Evolutionary_algorithm",[41],"evolutionary algorithm",". In a pure evolutionary algorithm, the candidate solutions will be breed together to create new offspring (crossover and mutation operations) with the goal of generating better solutions for the next generation.",[11,9926,9927],{},"From the point of view of software, this is a bit more complicated, but the reproduction could be done by implementing features that another framework lacks because that feature has proved to be a successful solution (crossover operation). On the other hand, new features are developed to distinguish it from its competitors (mutation operation). While it is not 100% the same, I think that we can see the parallelism between both approaches, as all the projects at some point implement similar solutions in other to compete and survive while adding new features that make them unique.",[11,9929,9930,9931,9934,9935,554],{},"Therefore, all the features of every framework can be treated, from this point of view, as ",[510,9932,9933],{},"traits or genetic features of the frameworks",". In evolution theory we know that: ",[37,9936,9939],{"href":9937,"rel":9938},"http://evolution.berkeley.edu/evosite/relevance/IIIA2Lowvariation.shtml",[41],"\"without genetic variation a population cannot evolve in response to changing environmental variables and, as a result, may face an increased risk of extinction\"",[11,9941,9942,9943,9948,9949],{},"Moreover, in a recent study it is shown that ",[37,9944,9947],{"href":9945,"rel":9946},"http://www.enn.com/wildlife/article/23391",[41],"loss of genetic diversity threatens species diversity",". According to Dr. Richard Lankau: ",[247,9950,9951],{},"\"Diversity within a species is necessary to maintain diversity among species, and at the same time, diversity among species is necessary to maintain diversity within a species. And if any one type is removed from the system, the cycle can break down, and the community becomes dominated by a single species.\"",[11,9953,9954,9955,9958,9959,9964,9965,554],{},"If we add to the equation that ",[510,9956,9957],{},"genetic diversity plays an important role in the survival of the species"," (see this ",[37,9960,9963],{"href":9961,"rel":9962},"http://www.sciencedirect.com/science/article/pii/S0006320705002089",[41],"paper"," from Dr. Richard Frankman), then ",[510,9966,9967],{},"we can assume that having different similar frameworks that try to solve a problem is not bad, it is good, really good",[11,9969,9970,9971,1319,9974,9977],{},"In summary, ",[510,9972,9973],{},"to me",[247,9975,9976],{},"reinventing the wheel can be treated as a technique that will assure enough genetic diversity"," (different features) for frameworks, so the species can survive. What do you think?",[11,9979,9980],{},"NOTE: The photo of this entry has been modified to remove a banner on right bottom corner.",{"title":49,"searchDepth":130,"depth":130,"links":9982},[],"2014-02-26T00:00:00.000Z","In the last three days I've participated in the third Citizen Cyberscience Summit.","Reinventing the wheel can be treated as a technique that will assure enough genetic diversity.","wheel","Rego Korosi","https://www.flickr.com/photos/korosirego/4849943530","London, United Kingdom",{"excerpt":9991},{"type":8,"value":9992},[9993,9998,10000],[11,9994,9782,9995,554],{},[37,9996,6395],{"href":6393,"rel":9997},[41],[11,9999,9788],{},[11,10001,9791,10002,9795,10004],{},[510,10003,9794],{},[510,10005,9798],{},"/blog/en/2014-02-26-reinventing-the-wheel",{"title":9777,"description":9984},"reinventing-the-wheel","blog/en/2014-02-26-reinventing-the-wheel","citizen science, open source, PYBOSSA, evolution, discussion","OYAew99-ctbSHo1AnbdAVfl3aaEwmgxc2GWLRKPs2DE",{"id":10013,"title":10014,"author":141,"body":10015,"date":10055,"description":10056,"extension":140,"headline":10057,"icon":10058,"icon_author":10059,"icon_url":10060,"layout":143,"location":6673,"meta":10061,"meta_description":10075,"navigation":145,"path":10076,"quote":141,"seo":10077,"slug":10078,"stem":10079,"tags":10080,"template":141,"__hash__":10081},"blog/blog/en/2014-02-18-entrevista-aventura-del-saber.md","Interview",{"type":8,"value":10016,"toc":10053},[10017,10029,10032,10035],[11,10018,10019,10020,10024,10025,10028],{},"Last week I was invited by ",[37,10021,10023],{"href":5707,"rel":10022},[41],"La Aventura del Saber",", a TV show from the ",[510,10026,10027],{},"Spanish National TV",",\nto talk about Citizen Science and explain it.",[11,10030,10031],{},"To me it was a great surprise, one of those that make your day, and I felt really honored and proud to be part of their program.",[11,10033,10034],{},"Today, the interview was aired, and thanks to their on demand service, you can now watch it here (note, only in Spanish, sorry!). Enjoy!",[2889,10036,3843,10038,3843,10042],{"style":10037},"width:100%;padding-top:64%;position:relative;display:inline-block;background:#eee;background:rgba(255,255,255,0.9);",[2893,10039],{"frameBorder":2897,"src":10040,"name":10041,"scrolling":3848,"style":3849},"https://www.rtve.es/drmn/embed/video/2403790","La aventura del Saber. Daniel Lombraña. Ciencia ciudadana",[2889,10043,3853,10044,1592,10048],{"style":3852},[224,10045,10046],{"style":3856},[47,10047],{"style":3860,"src":3861},[37,10049,10051],{"style":3865,"title":10041,"href":10050},"https://www.rtve.es/alacarta/videos/la-aventura-del-saber/aventura-del-saber-daniel-lombrana-ciencia-ciudadana/2403790/",[510,10052,10041],{},{"title":49,"searchDepth":130,"depth":130,"links":10054},[],"2014-02-18T00:00:00.000Z","Last week I was invited by La Aventura del Saber, a TV show from the Spanish National TV,\nto talk about Citizen Science and explain it.","Citizen science means opening the doors of the labs.","camera","EstatesGazzette","https://www.flickr.com/photos/48698930@N04/7637177726/",{"excerpt":10062},{"type":8,"value":10063},[10064,10071,10073],[11,10065,10019,10066,10024,10069,10028],{},[37,10067,10023],{"href":5707,"rel":10068},[41],[510,10070,10027],{},[11,10072,10031],{},[11,10074,10034],{},"The adventure of knowing interview","/blog/en/2014-02-18-entrevista-aventura-del-saber",{"title":10014,"description":10056},"entrevista-aventura-del-saber","blog/en/2014-02-18-entrevista-aventura-del-saber","citizen science, tv, interview, open science, crowdcrafting, PYBOSSA","sHlmCmNsnxK-djo7OQ-Opgkoq-PzqXXucL55pTAF6Qk",{"id":10083,"title":10084,"author":141,"body":10085,"date":10164,"description":10165,"extension":140,"headline":10166,"icon":10167,"icon_author":10168,"icon_url":10169,"layout":143,"location":6673,"meta":10170,"meta_description":10084,"navigation":145,"path":10196,"quote":141,"seo":10197,"slug":10198,"stem":10199,"tags":10200,"template":6691,"__hash__":10201},"blog/blog/en/2014-01-14-la-aventura-del-saber.md","The adventure of knowing",{"type":8,"value":10086,"toc":10162},[10087,10106,10129,10139,10156,10159],[11,10088,10089,10090,10094,10095,10100,10101,554],{},"Last year, I was the director of a ",[37,10091,10093],{"href":10092},"/blog/2013/12/02/hackfest-cienciaciudadana","citizen science hackfest",", with international and well respected professionals on the field like Francois Grey from the ",[37,10096,10099],{"href":10097,"rel":10098},"https://citizencyberscience.net/",[41],"Citizen Cyberscience Centre"," and Shannon Dosemagen from ",[37,10102,10105],{"href":10103,"rel":10104},"https://publiclab.org/",[41],"Public Labs",[11,10107,10108,10109,10114,10115,10118,10119,10124,10125,10128],{},"The event ",[37,10110,10113],{"href":10111,"rel":10112},"https://www.rtve.es/alacarta/videos/la-aventura-del-saber/aventura-del-saber-13-01-14/2306728/",[41],"was covered"," -",[247,10116,10117],{},"starts at minute 0:40:19","- by the Spanish national tv, ",[37,10120,10123],{"href":10121,"rel":10122},"https://www.rtve.es/alacarta/tve/la2/",[41],"La 2"," for a show named ",[37,10126,5709],{"href":5707,"rel":10127},[41]," with more than 18 years on air.",[11,10130,10131,10132,10135,10136,554],{},"Here you have the snippet of the program showing the event (",[247,10133,10134],{},"starts at minute 00:05:30",") and the venue of the event ",[37,10137,5692],{"href":5690,"rel":10138},[41],[2889,10140,3843,10141,3843,10145],{"style":10037},[2893,10142],{"frameBorder":2897,"src":10143,"name":10144,"scrolling":3848,"style":3849},"https://www.rtve.es/drmn/embed/video/2306808","La Aventura del Saber. Medialab-Prado",[2889,10146,3853,10147,1592,10151],{"style":3852},[224,10148,10149],{"style":3856},[47,10150],{"style":3860,"src":3861},[37,10152,10154],{"style":3865,"title":10144,"href":10153},"https://www.rtve.es/alacarta/videos/la-aventura-del-saber/aventura-del-saber-medialab-prado/2306808/",[510,10155,10144],{},[11,10157,10158],{},"La aventura del saber (or the adventure of knowing) is a daily show in the mornings of the Spanish national tv, with the goal of teaching and divulge using interviews and documentaries.",[11,10160,10161],{},"Enjoy!!!",{"title":49,"searchDepth":130,"depth":130,"links":10163},[],"2014-01-14T00:00:00.000Z","Last year, I was the director of a citizen science hackfest, with international and well respected professionals on the field like Francois Grey from the Citizen Cyberscience Centre and Shannon Dosemagen from Public Labs.","Hacking together at Medialab-Prado.","adventure","Sean Kelly","https://www.flickr.com/photos/thekellyscope/4450666660/",{"excerpt":10171},{"type":8,"value":10172},[10173,10183],[11,10174,10089,10175,10094,10177,10100,10180,554],{},[37,10176,10093],{"href":10092},[37,10178,10099],{"href":10097,"rel":10179},[41],[37,10181,10105],{"href":10103,"rel":10182},[41],[11,10184,10108,10185,10114,10188,10118,10190,10124,10193,10128],{},[37,10186,10113],{"href":10111,"rel":10187},[41],[247,10189,10117],{},[37,10191,10123],{"href":10121,"rel":10192},[41],[37,10194,5709],{"href":5707,"rel":10195},[41],"/blog/en/2014-01-14-la-aventura-del-saber",{"title":10084,"description":10165},"la-aventura-del-saber","blog/en/2014-01-14-la-aventura-del-saber","learning, tv, show, open science, crowdcrafting, PYBOSSA","2-LtUDMhh7WEhzNSuBhcA_skX1Ps27krkG8PZltRTEI",{"id":10203,"title":10204,"author":141,"body":10205,"date":10360,"description":10361,"extension":140,"headline":10362,"icon":10235,"icon_author":10363,"icon_url":10364,"layout":143,"location":6673,"meta":10365,"meta_description":10204,"navigation":145,"path":10366,"quote":141,"seo":10367,"slug":10368,"stem":10369,"tags":10370,"template":6691,"__hash__":10371},"blog/blog/en/2013-12-16-analyzing-pybossa.md","Sharing your PYBOSSA application analysis with Enki",{"type":8,"value":10206,"toc":10356},[10207,10219,10222,10225,10233,10236,10250,10258,10261,10267,10270,10273,10279,10282,10286,10293,10301,10313,10321,10333,10341,10347],[11,10208,10209,10210,10214,10215,10218],{},"Up to now if you have created your own application in your ",[37,10211,10213],{"href":10212},"/projects/pybossa","PYBOSSA server"," or\nin ",[37,10216,5650],{"href":5648,"rel":10217},[41]," you have to create your own library or script to download the results\nfrom the server and process them.",[11,10220,10221],{},"PYBOSSA provides links for every application to download the tasks and task runs in a CSV file or in JSON (if you want\nto hack around it more easily), however doing the analysis usually involved some work that could be tedious.",[11,10223,10224],{},"In order to solve this problem, I decided to creat a very simple to use Python package that downloads all the completed tasks\nand its associated answers and gives you the right tools for doing the analysis without having to write none of the usual tests.",[11,10226,10227,10228],{},"The result: ",[37,10229,10232],{"href":10230,"rel":10231},"https://github.com/PYBOSSA/enki",[41],"Enki",[15,10234,10232],{"id":10235},"enki",[11,10237,10238,10239,1112,10244,10249],{},"Enki is a very simple package that uses the ",[37,10240,10243],{"href":10241,"rel":10242},"https://github.com/PYBOSSA/pybossa-client",[41],"PYBOSSA-Client",[37,10245,10248],{"href":10246,"rel":10247},"https://pandas.pydata.org/",[41],"Pandas","\npackage to achieve the following two items:",[565,10251,10252,10255],{},[568,10253,10254],{},"Get all the tasks and task_runs,",[568,10256,10257],{},"Analyze them using the amazing Pandas framework.",[11,10259,10260],{},"Enki is so simple to use, that all you have to do to analyze your app is the following:",[2914,10262,10265],{"className":10263,"code":10264,"language":2919},[2917],"    >>> import enki\n    >>> e = enki.Enki(api_key='private', endpoint='http://server', app_short_name='your-app-slug')\n    >>> e.get_all()\n",[1539,10266,10264],{"__ignoreMap":49},[11,10268,10269],{},"Once all the tasks and task_runs have been downloaded, Enki will create automatically for you a list of data frames for the tasks,\nand a dictionary where the keys are the tasks IDs and the values are data frames of the associated task runs.",[11,10271,10272],{},"Then, if your application was for example asking if you see a human face in a picture, and the available answers are: Yes, No and I do not know,\ngetting the most voted answer is as simple as this:",[2914,10274,10277],{"className":10275,"code":10276,"language":2919},[2917],"    >>> task = e.tasks[0]\n    >>> e.task_runs_df[task.id]['info'].describe()\n",[1539,10278,10276],{"__ignoreMap":49},[11,10280,10281],{},"As Enki uses Pandas software, the describe function will detect if it is dealing with strings, or with numbers. In the latter case you\nwill get the mean, avg, std, etc. as a result of the output. Handy, right?",[15,10283,10285],{"id":10284},"ipython-enki-sharing-the-analysis","Ipython + Enki = sharing the analysis",[11,10287,10288,10289,10292],{},"Therefore, Enki is the right tool for doing the analysis of any of your PYBOSSA applications. However, I wanted to provide a more\ninteresting tool. I wanted to easily share the analysis in order to embrace ",[510,10290,10291],{},"open science",", so other researchers and citizens could\nreplicate my analysis and let me know if I made a mistake.",[11,10294,10295,10296,554],{},"For these reasons, as Pandas is integrated with Ipython you can create a notebook and share it with the rest of the world using\nthe ",[37,10297,10300],{"href":10298,"rel":10299},"https://nbviewer.jupyter.org",[41],"Ipython Notebook viewer",[11,10302,10303,10304,10307,10308,554],{},"This integration is ",[510,10305,10306],{},"amazing",". Now you can not only share your study, you can also get feedback and patches on your notebook,\ntweet about it, and improve it over time because you can save the notebook as a ",[37,10309,10312],{"href":10310,"rel":10311},"https://gist.github.com/",[41],"Github Gist",[11,10314,10315,10316,554],{},"In order to show how awesome is this feature, I have created a simple notebook to analyze the ",[37,10317,10320],{"href":10318,"rel":10319},"https://web.archive.org/web/2019/http://crowdcrafting.org/app/vimeo/",[41],"Crowdcrafting Video Pattern Recognition application",[11,10322,10323,10324,10328,10329,554],{},"The Gist is available ",[37,10325,7516],{"href":10326,"rel":10327},"https://gist.github.com/teleyinex/7991086",[41],", and you can directly view it ",[37,10330,7516],{"href":10331,"rel":10332},"https://nbviewer.jupyter.org/gist/teleyinex/7991086",[41],[2889,10334,10336],{"className":10335},[5261,5262],[2893,10337],{"className":10338,"src":10331,"style":10340},[10339],"hidden-phone","width:100%; height:500px;",[11,10342,10343,10344,554],{},"Thus, if you have a Crowdcrafting application and you need to analyze it, start using ",[37,10345,10232],{"href":10230,"rel":10346},[41],[11,10348,10349,6524,10351,554],{},[510,10350,5148],{},[37,10352,10355],{"href":10353,"rel":10354},"https://en.wikipedia.org/wiki/Enki",[41],"Enki is the name of a Sumerian god of the intelligence",{"title":49,"searchDepth":130,"depth":130,"links":10357},[10358,10359],{"id":10235,"depth":130,"text":10232},{"id":10284,"depth":130,"text":10285},"2013-12-16T00:00:00.000Z","Up to now if you have created your own application in your PYBOSSA server or\nin Crowdcrafting you have to create your own library or script to download the results\nfrom the server and process them.","Analyzing your PYBOSSA project with Python.","Georgelazenby","https://en.wikipedia.org/wiki/File:Chaos_Monster_and_Sun_God.png",{},"/blog/en/2013-12-16-analyzing-pybossa",{"title":10204,"description":10361},"analyzing-pybossa","blog/en/2013-12-16-analyzing-pybossa","enki, science, analysis, sharing, open science, crowdcrafting, PYBOSSA","zPEz30dfb_yjau5fTzvydkJsyOzwCqrTMvAdiQpnjyI",{"id":10373,"title":10374,"author":141,"body":10375,"date":10633,"description":49,"extension":140,"headline":10634,"icon":10635,"icon_author":10636,"icon_url":10637,"layout":143,"location":6673,"meta":10638,"meta_description":10374,"navigation":145,"path":10661,"quote":141,"seo":10662,"slug":10663,"stem":10664,"tags":10665,"template":6691,"__hash__":10666},"blog/blog/en/2013-12-02-hackfest-cienciaciudadana.md","Citizen Science hackfest in Madrid",{"type":8,"value":10376,"toc":10627},[10377,10383,10405,10408,10431,10434,10437,10444,10451,10462,10471,10485,10489,10492,10499,10502,10508,10511,10517,10520,10523,10534,10553,10555,10558,10561,10569,10583,10592,10595,10598,10604,10620],[6330,10378,10379],{},[11,10380,10381,6337],{},[510,10382,6336],{},[11,10384,10385,10386,1319,10391,8230,10396,10399,10400,10404],{},"The 29 and 30 of November of 2013 I organized with the support of ",[37,10387,10390],{"href":10388,"rel":10389},"http://fecyt.es/",[41],"FECYT",[37,10392,10395],{"href":10393,"rel":10394},"http://obrasocial.lacaixa.es/nuestroscentros/caixaforummadrid/caixaforummadrid_es.html",[41],"La Caixa Forum",[37,10397,5692],{"href":9122,"rel":10398},[41]," the second ",[37,10401,10093],{"href":10402,"rel":10403},"https://medialab-prado.es/article/encuentrodecienciaciudadana",[41]," in Madrid, Spain.",[11,10406,10407],{},"The event this time had the participation of two respected experts in the field of Citizen Science:",[565,10409,10410,10417,10423],{},[568,10411,10412,10413,4406],{},"Francois Grey, from ",[37,10414,10099],{"href":10415,"rel":10416},"https://citizencyberscience.net",[41],[568,10418,10419,10420,3829],{},"Shannon Dosemagen, from ",[37,10421,10105],{"href":10103,"rel":10422},[41],[568,10424,10425,10426],{},"Fermín Serrano, from ",[37,10427,10430],{"href":10428,"rel":10429},"https://ibercivis.es/",[41],"Ibercivis Foundation",[11,10432,10433],{},"The hackfest started with a morning session with talks from all the experts in a dedicated session\nfor the FECYT ComCiRed event at Medialab-Prado.",[11,10435,10436],{},"Francois Grey introduced the past,\npresent and future of citizen science.",[11,10438,10439,10440,10443],{},"Shannon explained how her team create open hardware tools\nfor measuring the world (balloon mapping tools, spectrometers, infrared cameras, etc.) representing\nthe ",[247,10441,10442],{},"volunteer sensing"," area.",[11,10445,10446,10447,10450],{},"Then, Fermín Serrano presented the Ibercivis Foundation and its work\nin Spain regarding ",[247,10448,10449],{},"volunteer computing"," with several research projects.",[11,10452,10453,10454,10457,10458,10461],{},"I closed the session\ntalking about ",[247,10455,10456],{},"volunteer thinking"," showing how ",[37,10459,5650],{"href":5648,"rel":10460},[41]," can\nbe used by citizens or researchers to create citizen science projects in minutes.",[11,10463,10464,10465,10470],{},"After lunch, we meet again and presented the proposed projects to work during the 30th of November\nat Medialab-Prado. The Saturday started with a short briefing for the day, explaining the ",[37,10466,10469],{"href":10467,"rel":10468},"https://etherpad.mozilla.org/cienciaciudadana",[41],"micro-workshops","\nthat we will be having along the day:",[565,10472,10473,10476,10479,10482],{},[568,10474,10475],{},"Balloon Mapping: mapping your surroundings,",[568,10477,10478],{},"EpiCollect+: gathering data with your phone,",[568,10480,10481],{},"Crowdcrafting: creating your own citizen science project in minutes, and",[568,10483,10484],{},"DIY Spectrometer",[15,10486,10488],{"id":10487},"balloon-mapping","Balloon Mapping",[11,10490,10491],{},"We started with the balloon mapping workshop. Shannon explained step by step how to\nbuild the balloon mapping using one of the kits they shell (but that you can build yourself if you want).",[6330,10493,10494],{},[11,10495,10496],{},[247,10497,10498],{},"Video no longer available - the Mixbit video hosting service was discontinued.",[11,10500,10501],{},"We had a very good weather in terms of wind: the balloon was really stable as well as the\ncamera, however it was really cold!",[11,10503,10504],{},[47,10505],{"alt":10506,"src":10507},"The materials","https://farm4.staticflickr.com/3828/11170358894_7e6d1d8a4c_k_d.jpg",[11,10509,10506],{"className":10510},[5330],[11,10512,10513],{},[47,10514],{"alt":10515,"src":10516},"Filling in the ballon","https://farm6.staticflickr.com/5521/11170361244_c6c44c51f2_k_d.jpg",[11,10518,10515],{"className":10519},[5330],[15,10521,5914],{"id":10522},"epicollect",[11,10524,10525,10526,10529,10530,554],{},"Then, we had the ",[37,10527,5914],{"href":5912,"rel":10528},[41]," workshop. We worked in creating an Odour Collect project\nthat basically asks volunteers to quantify or calify the odours that you can find in the\ncity. All you need to participate, is to install the EpiCollect+ application in your Android\nphone (iOS coming soon!) and join the ",[37,10531,7348],{"href":10532,"rel":10533},"https://five.epicollect.net/OdourCollect/",[41],[11,10535,10536,10537,10542,10543,10548,10549,554],{},"We also worked in adding more data samples for the ",[37,10538,10541],{"href":10539,"rel":10540},"https://web.archive.org/web/2019/http://crowdcrafting.org/app/airquality/",[41],"Crowdcrafting Lichens project","\nwith the participants of the events. We went to park El Retiro, split in teams, and take\nseveral samples with our phones. The result: ",[37,10544,10547],{"href":10545,"rel":10546},"https://five.epicollect.net/lichens/Lichens",[41],"almost 50 new samples from Madrid city"," that\ncan be directly analyzed in the ",[37,10550,10552],{"href":10539,"rel":10551},[41],"Crowdcrafting project",[15,10554,5650],{"id":6212},[11,10556,10557],{},"Then we moved to the Crowdcrafting workshop, were I teached and showed how you can create a\ncitizen science project using the available templates, and more impotantly, how you can import\nthe data from the previous two workshops into a Crowdcrafting application, and analyze the data\nwith the help of the volunteers.",[11,10559,10560],{},"For example, after taking the pictures of the balloon mapping workshop, a group of the participants\northo-referenced the pictures for creating the following map:",[2889,10562,10564],{"className":10563},[5261,5262],[2893,10565],{"style":10566,"width":5744,"height":10567,"src":10568},"border:none;",375,"https://archive.publiclab.org/leaflet/?tms=https://mapknitter.org/tms/plant-wall-in-madrid/&lat=40.4110814393&lon=-3.6931872467",[11,10570,10571,10572,10577,10578,10582],{},"That was imported into a ",[37,10573,10576],{"href":10574,"rel":10575},"https://web.archive.org/web/2019/http://crowdcrafting.org/app/balloonmappingmadrid/",[41],"Crowdcrafting application",", using this ",[37,10579,5015],{"href":10580,"rel":10581},"https://github.com/PYBOSSA/app-mapknitter",[41],".\nThe result, people can help you to count the number of participants in the workshop really easily.",[11,10584,10585,10586,10591],{},"The template provides also an example for measuring areas within the map, and this was the clue to\npropose to the ",[37,10587,10590],{"href":10588,"rel":10589},"http://mieldebarrio.wordpress.com/",[41],"Medialab-Prado Urban Bees Keepers"," to use this\ntechnique to map the roofs of the city, and quantify which ones are good or not (sometimes they cannot\naccess the roofs) and also to measure how many square meters are available to place several hives.",[15,10593,10484],{"id":10594},"diy-spectrometer",[11,10596,10597],{},"We ended the hackfest with the last workshop: build your own spectrometer. This time, we had the collaboration\nof the Medialab-Prado Origami team, as this spectrometer is built using a sheet of paper. In the following\nvideo you can see how we built several spectrometers and play with them.",[6330,10599,10600],{},[11,10601,10602],{},[247,10603,10498],{},[11,10605,10606,10607,10610,10611,10615,10616,554],{},"As you can see, we learned a lot, we produced several prototypes along the day, and\nabove all: ",[247,10608,10609],{},"we had a lot of fun while learning",". If you want to participate in the next\ncitizen science hackfest in Madrid, keep an eye in the ",[37,10612,10614],{"href":9122,"rel":10613},[41],"Medialab-Prado website",",\nmy site and/or ",[37,10617,10619],{"href":6522,"rel":10618},[41],"Twitter account",[11,10621,10622,10623,10626],{},"PS: I would like to give a ",[510,10624,10625],{},"big thank you"," to FECYT, La Caixa Forum and Medialab-Prado\nfor supporting the event, to Francois, Shanon and Fermín for coming to Madrid and present their\nwork in citizen science, and also to all the participants: without you this would not be possible! THANKS!!!",{"title":49,"searchDepth":130,"depth":130,"links":10628},[10629,10630,10631,10632],{"id":10487,"depth":130,"text":10488},{"id":10522,"depth":130,"text":5914},{"id":6212,"depth":130,"text":5650},{"id":10594,"depth":130,"text":10484},"2013-12-02T00:00:00.000Z","Madrid citizens participate in a citizen science hackfest.","balloon","Daniel Lombraña","https://www.flickr.com/photos/32985084@N00/11170324726/",{"excerpt":10639},{"type":8,"value":10640},[10641,10647],[6330,10642,10643],{},[11,10644,10645,6337],{},[510,10646,6336],{},[11,10648,10385,10649,1319,10652,8230,10655,10399,10658,10404],{},[37,10650,10390],{"href":10388,"rel":10651},[41],[37,10653,10395],{"href":10393,"rel":10654},[41],[37,10656,5692],{"href":9122,"rel":10657},[41],[37,10659,10093],{"href":10402,"rel":10660},[41],"/blog/en/2013-12-02-hackfest-cienciaciudadana",{"title":10374,"description":49},"hackfest-cienciaciudadana","blog/en/2013-12-02-hackfest-cienciaciudadana","citizen, science, spectrometer, balloonmapping, epicollect, crowdcrafting, PYBOSSA","RIJGVHDKhgQJQiEn2o73GdQBH-Baj1YlF2O82iqiWnE",{"id":10668,"title":10669,"author":141,"body":10670,"date":10805,"description":10674,"extension":140,"headline":10806,"icon":10807,"icon_author":10808,"icon_url":10809,"layout":143,"location":6673,"meta":10810,"meta_description":10669,"navigation":145,"path":10831,"quote":141,"seo":10832,"slug":10833,"stem":10834,"tags":10835,"template":6691,"__hash__":10836},"blog/blog/en/2013-11-26-pybossa-cache.md","Adding a load balanced & high-availability cache to PYBOSSA",{"type":8,"value":10671,"toc":10803},[10672,10675,10697,10704,10715,10721,10732,10744,10753,10756,10764,10767,10774,10785],[11,10673,10674],{},"In the last days I have been working really hard to add a new cache system to PYBOSSA.",[11,10676,10677,10678,10680,10681,10686,10687,10690,10691,1849,10694,5431],{},"Up to now, ",[37,10679,3127],{"href":10212}," has been using ",[37,10682,10685],{"href":10683,"rel":10684},"http://pythonhosted.org/Flask-Cache/",[41],"Flask-Cache",", an extension for the ",[37,10688,7990],{"href":7795,"rel":10689},[41]," micro-framework\nthat allows you to use several types of caching backends (i.e. ",[37,10692,7583],{"href":7581,"rel":10693},[41],[37,10695,7589],{"href":8149,"rel":10696},[41],[11,10698,10699,10703],{},[37,10700,5650],{"href":10701,"rel":10702},"https://web.archive.org/web/2019/http://crowdcrafting.org/",[41]," was using memcached, as it is a robust solution and it is really well documented.\nHowever in the last days due to high loads in the server, I've been thinking how I can\nimprove the situation, and have a cache system that meets the following criteria:",[565,10705,10706,10709,10712],{},[568,10707,10708],{},"Load-balanced: queries should be balanced between a master-slave architecture within PYBOSSA.",[568,10710,10711],{},"High-availability: if one slave or master node goes down, the system should recover itself without having to do anything special in PYBOSSA.",[568,10713,10714],{},"Persistence: avoid warming up the cache every time you need to reboot the server.",[11,10716,10717,10718,554],{},"After checking several solutions, the best candidate that meets those requirements is: ",[37,10719,7589],{"href":8149,"rel":10720},[41],[11,10722,10723,10726,10727,10729,10730,554],{},[37,10724,7589],{"href":8149,"rel":10725},[41]," is ",[247,10728,10306],{},". Let me repeat it: ",[510,10731,10306],{},[11,10733,10734,10735,10740,10741,554],{},"The reason I decided to start using\nRedis as the main cache for PYBOSSA is that it has an incredible set of ",[37,10736,10739],{"href":10737,"rel":10738},"https://redis.io/topics/introduction",[41],"features",",\na very simple master-slave setup, it is asynchronous, and over all those features: it gives you ",[37,10742,8155],{"href":8153,"rel":10743},[41],[11,10745,10746,10747,10752],{},"Sentinel is a system that allows you to monitor your master-slave setup, and discover\nRedis services in a very simple way. Fortunately, there is a ",[37,10748,10751],{"href":10749,"rel":10750},"https://github.com/andymccurdy/redis-py",[41],"Python client"," that uses\nthe Sentinel mode, and allows you to connect your Python software to Redis, handling behind\nthe curtains which nodes are alive and which nodes are not.",[11,10754,10755],{},"As Sentinel is perfect for what I wanted to build, I decided to start using it.\nThe result a new PYBOSSA caching module based on Redis.",[11,10757,863,10758,10763],{},[37,10759,10762],{"href":10760,"rel":10761},"https://github.com/PYBOSSA/pybossa/blob/master/pybossa/cache/__init__.py",[41],"new module is very simple",", it uses Sentinel to discover the master-slave setup\nand configure two clients: master and slave. Then, all read actions are loaded from the slave node, and all write actions are done in the master, balancing the\nload between the infrastructure.",[11,10765,10766],{},"The most interesting aspect of this setup, is that you can add more slaves in real time,\nand Sentinel will handle them for you. If the master node dies, then it will look for\nanother master to configure it (this needs another Sentinel node), and voile: system\nup and running without having to do any special.",[11,10768,10769,10770,10773],{},"Today I've deployed this new version (bumping PYBOSSA version to v0.2.0) in ",[37,10771,5650],{"href":5648,"rel":10772},[41],"\nand the speed of the site is really awesome!",[11,10775,10776,10777,10780,10781,10784],{},"The only \"issue\" with Redis, is that Ubuntu LTS does not have the most recent version\nof it (not even 2.6), so you have to download it manually, and compile it. The good news are\nthat after installing the Ubuntu package ",[247,10778,10779],{},"build-essential"," you should have all the requirements to run\na simple ",[247,10782,10783],{},"make"," command and build it.",[11,10786,10787,10789,10790,1112,10793,10796,10797,10802],{},[510,10788,5148],{},": in order to add it to the init.d section of Ubuntu, install first the old version via the\npackage manager, copy the files ",[247,10791,10792],{},"/etc/init.d/redis-server",[247,10794,10795],{},"/etc/redis/redis.conf"," to your\nhome folder, modify them to your needs (use the redis.conf as a guide for your redis.conf 2.6 config\nfile) and you will be done. Another option is to configure everything with ",[37,10798,10801],{"href":10799,"rel":10800},"http://supervisord.org/",[41],"Supervisor","\nwhich would be pretty handy (mental note, write a blog post about it).",{"title":49,"searchDepth":130,"depth":130,"links":10804},[],"2013-11-26T00:00:00.000Z","Redis.io is an amazing software for building a cache system.","balance","Felipe Gabaldón","https://www.flickr.com/photos/felipe_gabaldon/4334984556",{"excerpt":10811},{"type":8,"value":10812},[10813,10815],[11,10814,10674],{},[11,10816,10677,10817,10680,10819,10686,10822,10690,10825,1849,10828,5431],{},[37,10818,3127],{"href":10212},[37,10820,10685],{"href":10683,"rel":10821},[41],[37,10823,7990],{"href":7795,"rel":10824},[41],[37,10826,7583],{"href":7581,"rel":10827},[41],[37,10829,7589],{"href":8149,"rel":10830},[41],"/blog/en/2013-11-26-pybossa-cache",{"title":10669,"description":10674},"pybossa-cache","blog/en/2013-11-26-pybossa-cache","cache, high-availability, load balance, crowdcrafting, PYBOSSA","nH3erH-P7Myuhc7fTVmKRAfa-pMlvtRz9PRtfkF-mgw",{"id":10838,"title":10839,"author":141,"body":10840,"date":11242,"description":11243,"extension":140,"headline":11244,"icon":11245,"icon_author":11246,"icon_url":11247,"layout":143,"location":6673,"meta":11248,"meta_description":11287,"navigation":145,"path":11288,"quote":141,"seo":11289,"slug":11290,"stem":11291,"tags":11292,"template":6691,"__hash__":11293},"blog/blog/en/2013-09-23-video-tutorial.md","Shooting and Editing videos in GNU/Linux",{"type":8,"value":10841,"toc":11234},[10842,10850,10856,10863,10894,10903,10907,10915,10926,10934,10937,10943,10963,10969,10973,10976,10987,10993,11005,11019,11022,11025,11030,11033,11036,11040,11043,11049,11052,11074,11077,11086,11092,11098,11101,11104,11107,11110,11114,11117,11120,11124,11127,11133,11137,11155,11164,11167,11174,11190,11193,11207,11210,11216,11219,11222],[11,10843,10844,10845,554],{},"This year, in summer, I decided to apply for the prestigious ",[37,10846,10849],{"href":10847,"rel":10848},"https://www.shuttleworthfoundation.org/fellowship-model/",[41],"Shuttleworth Fellowship program",[2889,10851,3843,10853],{"className":10852},[5261,5262],[2893,10854],{"src":10855,"frameBorder":2897,"webkitallowfullscreen":49,"mozallowfullscreen":49,"allowFullScreen":145},"https://player.vimeo.com/video/33213160?title=0&byline=0&portrait=0&color=8cbd01",[11,10857,10858,10859,10862],{},"The Fellowship program is incredible!!! Why? Because all the fellows are amazing and their projects and ideas are mind blowing :-) Just to give you an idea, here is a ",[247,10860,10861],{},"short"," list of their Alumni:",[565,10864,10865,10872,10879,10887],{},[568,10866,10867],{},[37,10868,10871],{"href":10869,"rel":10870},"https://www.shuttleworthfoundation.org/fellows/mark-surman/",[41],"Mark Surman, Executive Director of Mozilla",[568,10873,10874],{},[37,10875,10878],{"href":10876,"rel":10877},"https://www.shuttleworthfoundation.org/fellows/francois-grey/",[41],"Francois Grey, Coordinator of Citizen Cyberscience Centre",[568,10880,10881,10886],{},[37,10882,10885],{"href":10883,"rel":10884},"https://www.shuttleworthfoundation.org/fellows/dr-rufus-pollock/",[41],"Rufus Pollock, co-founder & director of Open Knowledge Foundation",", or",[568,10888,10889,554],{},[37,10890,10893],{"href":10891,"rel":10892},"https://www.shuttleworthfoundation.org/fellows/philipp-schmidt/",[41],"Phillip Schmidt, Executive Director & Co-founder of Peer 2 Peer University",[11,10895,10896,10897,10902],{},"Amazing right!? As you can see, the level is pretty high!!! If you additionally take a look to the ",[37,10898,10901],{"href":10899,"rel":10900},"https://www.shuttleworthfoundation.org/funding/current-fellows/",[41],"current fellows"," then you can start to tremble.",[15,10904,10906],{"id":10905},"fellowship-application","Fellowship Application",[11,10908,10909,10914],{},[37,10910,10913],{"href":10911,"rel":10912},"https://www.shuttleworthfoundation.org/funding/fellowship-programme/",[41],"Applying for the fellowship"," has two steps:",[565,10916,10917,10920],{},[568,10918,10919],{},"the regular paperwork, plus",[568,10921,10922,10925],{},[247,10923,10924],{},"a short video"," pitching why they should fund you and your idea that would change the world.",[11,10927,10928,8897,10931,554],{},[510,10929,10930],{},"Pitching a project or idea is always hard",[247,10932,10933],{},"Really hard",[11,10935,10936],{},"You need to work on it as much as possible, trying to express as clear as possible what do you want to achieve if they fund you.",[11,10938,10939,10940],{},"For the written proposal, a good colleague and friend helped me to shape the document. However ",[247,10941,10942],{},"for the video I was alone!",[11,10944,10945,10946,1592,10949,10958,10959,10962],{},"Before moving forward I have to say that I own a ",[247,10947,10948],{},"good",[37,10950,10953,10957],{"href":10951,"rel":10952},"https://en.wikipedia.org/wiki/Digital_single-lens_reflex_camera",[41],[10954,10955,10956],"abbr",{},"DSLR"," camera",". It is not a professional one, those are ",[247,10960,10961],{},"really"," expensive, but a modest one that allows me to record video in high quality without too many problems.",[11,10964,10965,10966,554],{},"As you can see, the gear was not the problem. ",[510,10967,10968],{},"The problem was that I've never filmed a short-movie in my life",[15,10970,10972],{"id":10971},"learning-how-to-shoot-a-video","Learning how to shoot a video",[11,10974,10975],{},"OK, so I do not know how to shot a video, and I only have 2 weeks to write the application, shoot the video, edit it, and send everything to the program. Did I hear the word: stress? :-)",[11,10977,10978,10979,10982,10983,10986],{},"Well, as I didn't have any idea about how to shoot a video with my DSLR camera ",[247,10980,10981],{},"I decided to learn about it",". I love films, art, etc. so I usually visit the video website ",[37,10984,5760],{"href":5759,"rel":10985},[41],". Vimeo is like the playground for artists, where they show their creations. Just to give you an idea how creative are the users, check this video:",[2889,10988,3843,10990],{"className":10989},[5261,5262],[2893,10991],{"src":10992,"frameBorder":2897,"webkitallowfullscreen":49,"mozallowfullscreen":49,"allowFullScreen":145},"https://player.vimeo.com/video/67809013?title=0&byline=0&portrait=0&color=0094f0",[11,10994,10995,10996,10999,11000,11004],{},"Obviously, I would love to create something like that, but I've to be realistic. First I didn't know how to shoot properly a video, second you need to be ",[247,10997,10998],{},"very creative"," to build something similar to the previous movie, and third I only had two weeks. Additionally, I only had used a very simple video editor in my life: ",[37,11001,8716],{"href":11002,"rel":11003},"https://www.openshot.org/",[41],". Hence, I just wanted to learn the very basics principles, and apply them for my video application.",[11,11006,11007,11008,11013,11014,554],{},"Luckily, the Vimeo crew have created the ",[37,11009,11012],{"href":11010,"rel":11011},"https://vimeo.com/videoschool",[41],"School of Video"," with a specific set of lessons just for ",[37,11015,11018],{"href":11016,"rel":11017},"https://vimeo.com/videoschool/lesson/11/introduction-to-dslr-cameras",[41],"DSLR Cameras",[11,11020,11021],{},"The DSLR lessons are a must if you want to shoot with your reflex camera. I watched all of them while I had my camera with me, configuring it properly, and experimenting a bit with it. If you can, watch all videos, they are very helpful and you will learn a lot.",[11,11023,11024],{},"Once I had the proper configuration for the camera, I had to actually shoot the video. But before going crazy and shooting the video I decided to do a bit of research again. I basically expended one afternoon browsing Vimeo and Youtube looking for other video applications for the Shuttleworth program to see what other people have done.",[11,11026,11027,554],{},[247,11028,11029],{},"In general all the videos were shot with one cut, with the applicant in front of it pitching his/her project, using almost all the time available (5 minutes)",[11,11031,11032],{},"While I was watching them I knew that I had to do something different, if I wanted to get the attention of the Shuttleworth judges. Hence, I decided to create several cuts and reduce the video length as much as possible. Why? Because I didn't want to get them bored :-)",[11,11034,11035],{},"Now that I knew the initial structure, it was time to learn a bit more about how to tell a story with a film.",[15,11037,11039],{"id":11038},"the-art-of-storytelling","The Art of Storytelling",[11,11041,11042],{},"Again, I went back to the school of video for more resources and I found this amazing video:",[2889,11044,3843,11046],{"className":11045},[5261,5262],[2893,11047],{"src":11048,"frameBorder":2897,"webkitallowfullscreen":49,"mozallowfullscreen":49,"allowFullScreen":145},"https://player.vimeo.com/video/64207362?title=0&byline=0&portrait=0&color=0094f0",[11,11050,11051],{},"The video explains perfectly well how your script has to look like. Basically you need to answer the following questions or points:",[565,11053,11054,11059,11064,11069],{},[568,11055,11056,11058],{},[510,11057,8583],{}," This one was easy to answer: me!",[568,11060,11061,11063],{},[510,11062,8588],{}," Easy: Madrid, Spain.",[568,11065,11066,11068],{},[510,11067,8593],{}," This is the tough one! Basically pitching my project.",[568,11070,11071,11073],{},[510,11072,8598],{}," Another complicated one. Here I explained why I'm pitching my project and why is important.",[11,11075,11076],{},"After watching the video I started to write down my script answering those questions. The process helped me a lot to focus on what I wanted to tell, and more importantly: how I wanted to tell it.",[11,11078,11079,11080,6524,11083,554],{},"My pitch is about ",[510,11081,11082],{},"Citizen Science",[247,11084,11085],{},"citizens doing science themselves with simple tools that I am building",[11,11087,11088,11091],{},[247,11089,11090],{},"Citizens are a key aspect of my pitch",", so I wanted to give them a lot of relevance and I decided that I needed to film citizens, but where?",[11,11093,11094,11095,11097],{},"Well, the question ",[510,11096,8617],{}," gave me the answer. As I am based in Madrid, I decided to present the place, Madrid, filming in the most popular places: Sol, Callao and Plaza Mayor.",[11,11099,11100],{},"As I was going to shoot in the streets, I needed to add also a sound track according to the city style, so I browsed several open licensed tracks from Hip-Hop that could fit with the video. As you can see, I was giving body to the video thanks to answering the four P's.",[11,11102,11103],{},"Then I wrote plot. I expend a lot of time refining it until I was happy with it. I recorded myself several times repeating the text, just to get used to what I wanted to say, to check the rhythm, etc. This process helped me to rephrase several times parts of the script and to make it the way I wanted. It may sound silly, but I recommend you to film yourself to relax, learn your script, look natural, etc.",[11,11105,11106],{},"Finally, my wife and I went to the final place where she was going to film me. But when we were preparing I realized that we had a problem: the quality of sound as we were going to shoot in a public space.",[11,11108,11109],{},"The previous cuts were fine, because the sound of the camera were going to be overwritten by the sound track. However, in this new cuts I needed to sound as clear as possible. Therefore, how can I do it without a professional camera? The solution: back to Vimeo and Google to do some research about it.",[15,11111,11113],{"id":11112},"recording-clear-sound","Recording clear sound",[11,11115,11116],{},"In general people recommend you to use a separated voice recorder, so you can sync the audio later in the video editing tool. I didn't want to buy a recorder just for this video, but it looked like it was the only feasible solution. While I was checking prices, I had an idea: what if I used my own smartphone with its headphones and integrated mic? It sounded crazy, but it was worthy to give it a try.",[11,11118,11119],{},"I set it up: the phone in my pocket, the headphones inside my polo using one of the buttons to lock the mic properly and hide it from the view of the camera. Then, I pressed the record button, say the standard \"hello, hello, one, two three\"  and a new audio clip was saved. It worked like a charm, and the cost of it was 0 EUR :-)",[15,11121,11123],{"id":11122},"a-cheap-prompter","A cheap prompter",[11,11125,11126],{},"With everything more or less solved, it was time to create a prompter. The solution: a spiral notebook. Each page was the text I've to say when recording a cut, so it was really easy for me to read it. Tips: use capital letters, so you can read it clearly, and adjust the length of the sentence in a way that it fits the rhythm that you want to give to your pitch. Try it several times before going to shoot, until you are really comfortable with the result.",[11,11128,11129,11130,554],{},"We filmed every cut several times, from different angles, and in different places. This work flow allowed me to choose between different videos and try different ideas when editing it. With all the materials saved in my hard disk, it was time to start the video editing, or how I called it: ",[247,11131,11132],{},"the panicking area",[15,11134,11136],{"id":11135},"editing-the-video-aka-panicking-mode-on","Editing the video (aka panicking mode on!)",[11,11138,11139,11140,11145,11146,11151,11152,554],{},"I am a big fan and user of open source software. I release ",[37,11141,11144],{"href":11142,"rel":11143},"https://flickr.com/photos/teleyinex",[41],"all my photos under an open license"," and all ",[37,11147,11150],{"href":11148,"rel":11149},"https://github.com/teleyinex",[41],"the code I develop is also open source",". In other words, I am a true believer in open source, so I wanted to create the full video using only open source editing tools. In this case ",[37,11153,8716],{"href":11002,"rel":11154},[41],[11,11156,11157,11158,11163],{},"OpenShot is very handy. You can separate several tracks in your movie, add vectorial tittles (that you can edit with ",[37,11159,11162],{"href":11160,"rel":11161},"https://inkscape.org/",[41],"Inkscape","), sound clips, make transitions, etc. It looks amazing, right? Well,I guess that for small projects is not a problem, but for me it was a really frustrating time because every time I saved the project or changed something, the application crashed.",[11,11165,11166],{},"The good thing though, was that even tough it crashed almost all the time, the progress was always saved and I never lost any information.",[11,11168,11169,11170,11173],{},"The first thing I worked on were the titles. I used ",[37,11171,11162],{"href":11160,"rel":11172},[41]," to create them, and again, in order to give the same look and feel to the whole video, I searched for a nice font and a background to overlay the text. As the main theme for the video is the city, I decided to use some graffiti droplets as the background for the text, keeping a clean and modern font.",[11,11175,11176,11177,11180,11181,11184,11185,554],{},"The next step was to sync the audio files with the videos. To my surprise ",[247,11178,11179],{},"I discovered that OpenShot doesn't have that feature",", so I started to freak out. Literally. Two breaths later, I did some ",[247,11182,11183],{},"Googling"," and fortunately I found another open source video editor that actually can do the sync \"automatically\": ",[37,11186,11189],{"href":11187,"rel":11188},"https://www.pitivi.org/",[41],"PiTiVi",[11,11191,11192],{},"I installed the software, and I tried out. The first time it worked, so I was really happy (later I discovered that for some video and audio clips, it never synchronized the audio tracks; as I filmed several times the same cut, I'd always a pair of clips that worked). Thus, my current work flow was the following:",[565,11194,11195,11198,11201,11204],{},[568,11196,11197],{},"Import video and sound clip in PiTiVi,",[568,11199,11200],{},"Sync the sound in both items,",[568,11202,11203],{},"Export the final video with the synchronized audio,",[568,11205,11206],{},"Import the video in OpenShot to do the final editing.",[11,11208,11209],{},"Did you say: painful? Yes, really painful. Add also that every time I changed something in OpenShot it crashed, so you can have an idea how painful it was. However, I wanted to create the video using only open software tools so I forced myself, and the result was this:",[2889,11211,3843,11213],{"className":11212},[5261,5262],[2893,11214],{"src":11215,"frameBorder":2897,"webkitallowfullscreen":49,"mozallowfullscreen":49,"allowFullScreen":145},"https://player.vimeo.com/video/66246703?title=0&byline=0&portrait=0",[11,11217,11218],{},"After all, the experience was really beautiful because I learned a lot. Some people would say that open source tools sucks (I do not share that feeling at all), but actually, thanks to that I've learned a lot, due to all the research I did.",[11,11220,11221],{},"When I finished my video, I checked the OpenShot web site to see if there is a new version that fixes all the problems I had,  and luckily it seems like a new version is in the oven. Thus, in the future it should be much easier to do it in GNU/Linux.",[11,11223,11224,11225,11230,11231,554],{},"Final note: I want to try the popular ",[37,11226,11229],{"href":11227,"rel":11228},"http://libregraphicsworld.org/blog/entry/first-look-at-lightworks-beta-for-linux",[41],"Lightworks"," and see how good it is, but as usual, I do not have enough time ",[5823,11232],{"className":11233},[5826,5827],{"title":49,"searchDepth":130,"depth":130,"links":11235},[11236,11237,11238,11239,11240,11241],{"id":10905,"depth":130,"text":10906},{"id":10971,"depth":130,"text":10972},{"id":11038,"depth":130,"text":11039},{"id":11112,"depth":130,"text":11113},{"id":11122,"depth":130,"text":11123},{"id":11135,"depth":130,"text":11136},"2013-09-23T00:00:00.000Z","This year, in summer, I decided to apply for the prestigious Shuttleworth Fellowship program.","Open source tools for video editing.","film","Rami","https://www.flickr.com/photos/rhk313/4846377172",{"excerpt":11249},{"type":8,"value":11250},[11251,11256,11261,11265],[11,11252,10844,11253,554],{},[37,11254,10849],{"href":10847,"rel":11255},[41],[2889,11257,3843,11259],{"className":11258},[5261,5262],[2893,11260],{"src":10855,"frameBorder":2897,"webkitallowfullscreen":49,"mozallowfullscreen":49,"allowFullScreen":145},[11,11262,10858,11263,10862],{},[247,11264,10861],{},[565,11266,11267,11272,11277,11282],{},[568,11268,11269],{},[37,11270,10871],{"href":10869,"rel":11271},[41],[568,11273,11274],{},[37,11275,10878],{"href":10876,"rel":11276},[41],[568,11278,11279,10886],{},[37,11280,10885],{"href":10883,"rel":11281},[41],[568,11283,11284,554],{},[37,11285,10893],{"href":10891,"rel":11286},[41],"How to make a short film using only open source tools","/blog/en/2013-09-23-video-tutorial",{"title":10839,"description":11243},"video-tutorial","blog/en/2013-09-23-video-tutorial","video, open source, tutorial, shuttleworth, tools, crowdcrafting, PYBOSSA","hg8q04MM2hQctjv_SdQ8XJmDLHF94SS-7-cGe_Ig82Q",{"id":11295,"title":11296,"author":141,"body":11297,"date":11459,"description":11460,"extension":140,"headline":11461,"icon":11462,"icon_author":10636,"icon_url":11463,"layout":143,"location":11464,"meta":11465,"meta_description":11305,"navigation":145,"path":11477,"quote":141,"seo":11478,"slug":11462,"stem":11479,"tags":11480,"template":6691,"__hash__":11481},"blog/blog/en/2013-08-06-cernsummerwebfest2013.md","2nd CERN Summer Webfest",{"type":8,"value":11298,"toc":11457},[11299,11312,11315,11324,11354,11360,11363,11413,11416,11425,11428,11433,11436,11454],[11,11300,11301,11302,11306,11307,11311],{},"The second ",[37,11303,11305],{"href":11304},"https://citizencyberscience.net/wiki","CERN Summer Student Webfest"," has been an amazing event. Physicists, designers, computer scientists and engineers worked together in a 48 hours marathon to create a set of amazing ",[37,11308,3663],{"href":11309,"rel":11310},"https://citizencyberscience.net/wiki/index.php?title=Projects",[41]," involving physics and modern web technologies.",[11,11313,11314],{},"This year, students worked in data visualizations for the most popular scientists at CERN, an antimatter Crowdcrafting.org application, games for teaching and learning physics using different type of games: simulators, puzzles, strategy, etc., reproducible science, and more many more!",[11,11316,11317,11318,11323],{},"The first day, the students pitched several projects and ideas. Most of the students proposed a ",[37,11319,11322],{"href":11320,"rel":11321},"https://citizencyberscience.net/wiki/index.php?title=Projects#Gaming",[41],"game"," based solution for teaching and learning physics, becoming this category the most popular with 8 games! There were other categories:",[565,11325,11326,11333,11340,11347],{},[568,11327,11328],{},[37,11329,11332],{"href":11330,"rel":11331},"https://citizencyberscience.net/wiki/index.php?title=Projects#Tools_for_Science",[41],"Tools for science",[568,11334,11335],{},[37,11336,11339],{"href":11337,"rel":11338},"https://citizencyberscience.net/wiki/index.php?title=Projects#Physics.2FStandard_Model",[41],"Physics/Standard model",[568,11341,11342],{},[37,11343,11346],{"href":11344,"rel":11345},"https://citizencyberscience.net/wiki/index.php?title=Projects#Data_Visualization",[41],"Data Visualization",[568,11348,11349],{},[37,11350,11353],{"href":11351,"rel":11352},"https://citizencyberscience.net/wiki/index.php?title=Projects#Education",[41],"Education",[11,11355,11356,11359],{},[510,11357,11358],{},"This year we have introduced a series of tutorials"," where the students could learn new technologies, techniques, etc. Additionally, we invited them to also propose to give some of the tutorials, making the webfest a very alive event where not only the organizers take part but also the participants suggesting and creating new elements in it.",[11,11361,11362],{},"The tutorials were really interesting:",[565,11364,11365,11373,11381,11389,11397,11405],{},[568,11366,11367,11372],{},[37,11368,11371],{"href":11369,"rel":11370},"https://citizencyberscience.net/wiki/index.php?title=Making_Website_and_Media_using_Mozilla_Webmaker_and_Popcorn_Maker",[41],"Making Website and Media using Mozilla Webmaker and Popcorn Maker",", by Michael Kohler (Mozilla).",[568,11374,11375,11380],{},[37,11376,11379],{"href":11377,"rel":11378},"https://citizencyberscience.net/wiki/index.php?title=Introduction_to_Crowdcrafting/Pybossa",[41],"Introduction to Crowdcrafting/PYBOSSA",", by Daniel Lombraña González (Citizen Cyberscience Centre).",[568,11382,11383,11388],{},[37,11384,11387],{"href":11385,"rel":11386},"https://citizencyberscience.net/wiki/index.php?title=Facemesh_Clone_--_Web_Programming_Workshop",[41],"Facemesh Clone -- Web Programming Workshop"," by S.p. Mohanty a CERN Summer Student.",[568,11390,11391,11396],{},[37,11392,11395],{"href":11393,"rel":11394},"https://citizencyberscience.net/wiki/index.php?title=Hardware_Programming_and_Arduino",[41],"Hardware Programming and Arduino"," by James Devine (CERN).",[568,11398,11399,11404],{},[37,11400,11403],{"href":11401,"rel":11402},"https://citizencyberscience.net/wiki/index.php?title=Communicating_Your_Science",[41],"Communicating Your Science"," by Julie Gould (The Movile Collective).",[568,11406,11407,11412],{},[37,11408,11411],{"href":11409,"rel":11410},"https://citizencyberscience.net/wiki/index.php?title=Masterclass_on_particle_physics_--_Measuring_lifetime_of_D0_particle",[41],"Masterclass on particle physics -- Measuring lifetime of D0 particle"," by Andrey Ustyuzhanin (CERN).",[11,11414,11415],{},"As in the previous year, the atmosphere was amazing. The students participated in the tutorials (when they were not really busy working on their projects), chat and about everything: code, code, code and work ;-)",[11,11417,11418,11419,11424],{},"On Sunday afternoon, the final pitches about the projects were made and the winner was announced: ",[37,11420,11423],{"href":11421,"rel":11422},"https://citizencyberscience.net/wiki/index.php?title=Mother_Hunt",[41],"Mother Hunt",". In this game you are an end state particle that explores CERN to try to reconstruct his family history of decay mothers and ancestors.",[11,11426,11427],{},"The team created a 3D world using some of the available models at CERN, making a very interesting and immersing game in the CERN scenario. They created a short story line that could be played in one computer, and they are hoping to release the software, so more people could play it and learn physics.",[11,11429,11430],{},[47,11431],{"alt":49,"src":11432},"https://i.imgur.com/fyxppic.png",[11,11434,11435],{},"The other two final chosen projects were:",[565,11437,11438,11446],{},[568,11439,11440,11445],{},[37,11441,11444],{"href":11442,"rel":11443},"https://citizencyberscience.net/wiki/index.php?title=Reproducible_Science_--_improving_scientific_research_to_the_next_level_of_clearness_%26_reproducibility",[41],"Reproducible Science",": an IPython module for ROOT that allows any scientist using the ROOT software to share and improve their research on the web.",[568,11447,11448,11453],{},[37,11449,11452],{"href":11450,"rel":11451},"https://citizencyberscience.net/wiki/index.php?title=Popular_Physics_in_History",[41],"Popular Physics in History"," a web tool that analyzes the most popular scientists at CERN querying back end services like CERN Document Server and INSPIRE High Energy Physics Library.",[11,11455,11456],{},"The event was a success, and we hope that all the students had a lot of fun participating and developing their projects. We will be update this entry with more photos and videos, as soon as they are available.",{"title":49,"searchDepth":130,"depth":130,"links":11458},[],"2013-08-06T00:00:00.000Z","The second CERN Summer Student Webfest has been an amazing event. Physicists, designers, computer scientists and engineers worked together in a 48 hours marathon to create a set of amazing projects involving physics and modern web technologies.","Brilliant students from CERN participate in the 2nd CERN Summer Webfest.","cernsummerwebfest2013","https://www.flickr.com/photos/32985084@N00/5389725627/","CERN, Geneva, Switzerland",{"excerpt":11466},{"type":8,"value":11467},[11468,11475],[11,11469,11301,11470,11306,11472,11311],{},[37,11471,11305],{"href":11304},[37,11473,3663],{"href":11309,"rel":11474},[41],[11,11476,11314],{},"/blog/en/2013-08-06-cernsummerwebfest2013",{"title":11296,"description":11460},"blog/en/2013-08-06-cernsummerwebfest2013","CERN, Webfest, physics, science","jgOqvVCUwQW8vt0eojA6R4XkOTSPv05m5w_xVxJlfuo",{"id":11483,"title":11484,"author":141,"body":11485,"date":11459,"description":49,"extension":140,"headline":11640,"icon":11641,"icon_author":11561,"icon_url":11642,"layout":143,"location":11464,"meta":11643,"meta_description":11665,"navigation":145,"path":11666,"quote":141,"seo":11667,"slug":11668,"stem":11669,"tags":11670,"template":6691,"__hash__":11671},"blog/blog/en/2013-08-06-mapping-antimatter-with-crowdcrafting.md","Mapping Antimatter tracks with Crowdcrafting.org",{"type":8,"value":11486,"toc":11637},[11487,11493,11505,11513,11516,11525,11532,11535,11538,11542,11545,11548,11551,11554,11557,11563,11566,11569,11572,11586,11595,11604,11613,11616,11621,11625,11628],[6330,11488,11489],{},[11,11490,11491,6337],{},[510,11492,6336],{},[11,11494,11495,11496,11501,11502,554],{},"This last weekend, CERN hosted a very special event: ",[37,11497,11500],{"href":11498,"rel":11499},"https://citizencyberscience.net/wiki/index.php?title=Main_Page",[41],"the 2nd CERN Summer Student Webfest"," organized by the ",[37,11503,10099],{"href":10097,"rel":11504},[41],[11,11506,11507,11508,554],{},"The Webfest invites CERN summer students to participate in a 48 hours marathon hacking new applications, tools, games, etc. about physics. This year, I participated and worked in a very interesting one: ",[37,11509,11512],{"href":11510,"rel":11511},"https://web.archive.org/web/2019/http://crowdcrafting.org/app/antimatter/",[41],"The Antimatter project",[11,11514,11515],{},"With a team of around 8 persons, we divided the work in different areas and learned about the project and the goals for the Crowdcrafting application.",[11,11517,11518,11519,11524],{},"Michael Doser from CERN and the spokesperson from the ",[37,11520,11523],{"href":11521,"rel":11522},"https://aegis.web.cern.ch/aegis/",[41],"AEgIS experiment",", is studying antimatter.",[11,11526,11527,11528,11531],{},"But, ",[510,11529,11530],{},"what is antimatter?"," The observable Universe is composed almost entirely of matter but we can produce stuff called antimatter in the lab. Antimatter is material composed of antiparticles. So for example, a positron (the antiparticle of an electron) combines with an antiproton to form an antihydrogen atom.",[11,11533,11534],{},"Antiparticles have the same mass as normal matter particles but the opposite charge. When an antiparticle collides with an ordinary matter particle they both obliterate to emit radiation and some other particles - this is called annihilation.",[11,11536,11537],{},"Because of Einstein's weak equivalence principle (gravity doesn't depend on composition) antiparticles should interact gravitationally just like particles of ordinary matter - and that's what scientist's expect to observe - but if they don't then Einstein was wrong...",[15,11539,11541],{"id":11540},"whats-the-experiment","What's the experiment?",[11,11543,11544],{},"The Antihydrogen Experiment: Gravity, Interferometry, Spectroscopy (AEgIS) experiment at CERN shoot antihydrogen atoms horizontally, whereupon they fly (and drop) until they hit a wall made of matter - any matter will do, silicon, silver, paper,... - and annihilate there",[11,11546,11547],{},"On hitting the wall, the antihydrogen annihilates with a nucleus of the wall to produce mostly pions and some other particles - which we'll call starburst.",[11,11549,11550],{},"The starburst travel through a special gel called an emulsion and we can see its tracks. If we trace these tracks to their point of origin then we know exactly where annihilation occurred.",[11,11552,11553],{},"Then as we know the starting position of the antiparticles, the distance they travelled to the point of annihilation and how much they dropped - we can work out how far the antiparticle fell during its journey.",[11,11555,11556],{},"Then we can figure out how antimatter interacts gravitationally.",[11,11558,11559],{},[47,11560],{"alt":11561,"src":11562},"CERN","https://i.imgur.com/uVVjKzD.jpg",[11,11564,11565],{},"Michael Doser gave us access to a set of 99 areas photographed with a microscope, that allows us to see tracks and the starbursts. Each of the areas have 40 pictures. These pictures cover the same area but at a differen depth.",[11,11567,11568],{},"As we discussed about the project, we decided to create a \"movie style\" task, where the Crowdcrafting application will be playing in a loop all the images for the same area. Then, we will allow the volunteers to map the tracks using their mouse as in any image software. The coordinates of the tracks, starting and ending points, will be saved, and we will use those points to render in real time a 3D model of the tracks thanks to WebGL.",[11,11570,11571],{},"We divided the work between different groups, and we worked together in the different areas:",[565,11573,11574,11577,11580,11583],{},[568,11575,11576],{},"Creating of tasks based on the data.",[568,11578,11579],{},"2D movie style using HTML5 canvas feature.",[568,11581,11582],{},"3D model of tracks using HTML5 WebGL.",[568,11584,11585],{},"Physics description of the problem and tutorial.",[11,11587,11588,11589,11594],{},"For the 2D Canvas solution we decided to use the popular ",[37,11590,11593],{"href":11591,"rel":11592},"http://www.kineticjs.com/",[41],"Kinetic.JS"," library. This library is very versatile as you can not only render images in the 2D canvas, but also paint lines.",[11,11596,11597,11598,11603],{},"For the 3D model we decided to use the popular ",[37,11599,11602],{"href":11600,"rel":11601},"http://threejs.org/",[41],"Three.JS library",". We created a 3D area using the Tron colors palette to draw the reported tracks by the users.",[11,11605,11606,11607,11612],{},"Then, we have another group that worked really hard in explaining the physics of the experiment and the tutorial. We even created a ",[37,11608,11611],{"href":11609,"rel":11610},"https://juanracasti.makes.org/popcorn/1adt",[41],"Mozilla Webmaker project"," about it.",[11,11614,11615],{},"At the end of Sunday we had a fully operational prototype that allows you to actually track antimatter in Crowdcrafting:",[11,11617,11618],{},[47,11619],{"alt":10552,"src":11620},"https://github-camo.global.ssl.fastly.net/9a7c3a33b5470bf0c42f19f74a7443adf0e116ef/687474703a2f2f692e696d6775722e636f6d2f716b32393067352e706e67",[11,11622,11624],{"className":11623},[5330],"Crowdsourcing antimatter prototype",[11,11626,11627],{},"From here I would like to thank to all the team members because the actually loved the project and push it to the next level. This efforts will help other Crowdcrafting/PYBOSSA developers to use the new HTML5 Canvas and WebGL features developed for this application, as the source code is already available in Github and can be used as a template for any Crowdcrafting/PYBOSSA application.",[11,11629,11630,11631,11636],{},"If you want, you can follow the ",[37,11632,11635],{"href":11633,"rel":11634},"https://github.com/CERNSummerWebfest/antimatter",[41],"Github repository"," development of the project.",{"title":49,"searchDepth":130,"depth":130,"links":11638},[11639],{"id":11540,"depth":130,"text":11541},"Does antimatter fall up or down?","antimatter","http://home.web.cern.ch/sites/home.web.cern.ch/files/styles/medium/public/image/experiment/2013/01/alpha.jpg?itok=ZPb7wNsC",{"excerpt":11644},{"type":8,"value":11645},[11646,11652,11660],[6330,11647,11648],{},[11,11649,11650,6337],{},[510,11651,6336],{},[11,11653,11495,11654,11501,11657,554],{},[37,11655,11500],{"href":11498,"rel":11656},[41],[37,11658,10099],{"href":10097,"rel":11659},[41],[11,11661,11507,11662,554],{},[37,11663,11512],{"href":11510,"rel":11664},[41],"A CERN antimatter citizen science application built with PYBOSSA","/blog/en/2013-08-06-mapping-antimatter-with-crowdcrafting",{"title":11484,"description":49},"mapping-antimatter-with-crowdcrafting","blog/en/2013-08-06-mapping-antimatter-with-crowdcrafting","CERN, crowdcrafting, Webfest, science, physics","VsTzL4RCwg0uRT1pQledNHiQdj065-x-uhqFiVjVSZc",{"id":11673,"title":11674,"author":141,"body":11675,"date":11791,"description":49,"extension":140,"headline":11792,"icon":11793,"icon_author":11794,"icon_url":11795,"layout":143,"location":11796,"meta":11797,"meta_description":11826,"navigation":145,"path":11827,"quote":141,"seo":11828,"slug":11829,"stem":11830,"tags":11831,"template":6691,"__hash__":11832},"blog/blog/en/2013-07-31-crodcrafting-data-journalism.md","Analyzing Icelandic conviction rates",{"type":8,"value":11676,"toc":11789},[11677,11683,11715,11737,11746,11751,11758,11764,11767,11777],[6330,11678,11679],{},[11,11680,11681,6337],{},[510,11682,6336],{},[11,11684,11685,11689,11690,11694,11695,11700,11701,1319,11704,11709,11710,554],{},[37,11686,11688],{"href":5648,"rel":11687},[41],"Crowdcrafting.org"," hosts a wide variety of applications that range from ",[37,11691,11693],{"href":10539,"rel":11692},[41],"science"," to\n",[37,11696,11699],{"href":11697,"rel":11698},"https://web.archive.org/web/2019/http://crowdcrafting.org/app/bardomatic/",[41],"humanities",". Since the official launch of ",[37,11702,11688],{"href":5648,"rel":11703},[41],[37,11705,11708],{"href":11706,"rel":11707},"https://web.archive.org/web/2019/http://crowdcrafting.org/app/category/featured/",[41],"lots of applications have been created","\n, but one of them has done a really impressive job: ",[37,11711,11714],{"href":11712,"rel":11713},"https://web.archive.org/web/2019/http://crowdcrafting.org/app/heradsdomar/",[41],"Héraðsdómar -\nsýknað eða sakfellt",[11,11716,11717,11720,11721,1505,11726,1319,11731,11736],{},[510,11718,11719],{},"Héraðsdómar - sýknað eða sakfellt"," is an application developed by ",[37,11722,11725],{"href":11723,"rel":11724},"http://gogn.in/",[41],"Páll Hilmarsson",[37,11727,11730],{"href":11728,"rel":11729},"https://twitter.com/pallih",[41],"@pallih",[37,11732,11735],{"href":11733,"rel":11734},"https://github.com/pallih",[41],"Github","). The application was one of the most popular and active\napplications in Crowdcrafting.org when it was published (300 volunteers helped!),\nso I wanted to interview the author and ask some questions about it: why he created the application,\nwhat was the result, etc.",[11,11738,11739,11740,11745],{},"Páll told me that he created the application after reading the ",[37,11741,11744],{"href":11742,"rel":11743},"http://www.visir.is/simon-sigvaldason-sakfellir-naer-alltaf/article/2012121229180",[41],"an article"," published in an Icelandic news web site.",[11,11747,11748],{},[47,11749],{"alt":49,"src":11750},"https://i.imgur.com/6GlMJ1p.png",[11,11752,11753,11754,11757],{},"The article analyzed the ",[510,11755,11756],{},"conviction rates of a named judged in the Reykjavik district court",",\nstating that the conviction rates for cases where he presided as a judge was 99%.\nPáll found it interesting, but also \"biased\" as the reporter only analyzed one judge.",[11,11759,11760,11761,11763],{},"After the publication of the story, some bloggers and readers of the post, discussed\nabout why analyzing only one judge, reporting it back to the author. The journalist\naddressed all the questions and comments answering that",[5493,11762],{},"\ncalculating all the conviction rates for every case would take too long.",[11,11765,11766],{},"Páll was not happy with this answer, so he decided to show him, and other reporters, that\nthis could be easily done by crowdsourcing the job, and that it would not take too long.",[11,11768,11769,11772,11773,5431],{},[510,11770,11771],{},"Páll uploaded around 4,700 rulings as tasks, and the volunteers analyze them in 7 days!"," Each ruling\nwent to at least three different users, totaling 14,208 assessments. In the end more than\n17,000 assessments were made by over 300 users! (you can check the stats ",[37,11774,7516],{"href":11775,"rel":11776},"https://web.archive.org/web/2019/http://crowdcrafting.org/app/heradsdomar/stats",[41],[11,11778,11779,11780,11783,11784,6088],{},"But here it comes the best part, ",[510,11781,11782],{},"Páll only spent 10 hours in this project"," (including\nthe time to scrape the rulings, set up the tasks on Crowdcrafting.org and displaying\nthe ",[37,11785,11788],{"href":11786,"rel":11787},"http://gogn.in/heradsdomar/",[41],"results on his blog",{"title":49,"searchDepth":130,"depth":130,"links":11790},[],"2013-07-31T00:00:00.000Z","One single sample is not enought to draw conclusions.","justice","mira66","https://www.flickr.com/photos/21804434@N02/6250645786/","Adalstraeti, Reykjavik, Iceland",{"excerpt":11798},{"type":8,"value":11799},[11800,11806],[6330,11801,11802],{},[11,11803,11804,6337],{},[510,11805,6336],{},[11,11807,11808,11689,11811,11694,11814,11700,11817,1319,11820,11709,11823,554],{},[37,11809,11688],{"href":5648,"rel":11810},[41],[37,11812,11693],{"href":10539,"rel":11813},[41],[37,11815,11699],{"href":11697,"rel":11816},[41],[37,11818,11688],{"href":5648,"rel":11819},[41],[37,11821,11708],{"href":11706,"rel":11822},[41],[37,11824,11714],{"href":11712,"rel":11825},[41],"Analyzing Icelandic conviction rates with PYBOSSA","/blog/en/2013-07-31-crodcrafting-data-journalism",{"title":11674,"description":49},"crodcrafting-data-journalism","blog/en/2013-07-31-crodcrafting-data-journalism","crowdcrafting, PYBOSSA, data journalism, social","5yGg3n-ajSXz8aeIXr2dlFNRgTZthnLlvUip6TqCgJQ",{"id":11834,"title":11835,"author":141,"body":11836,"date":12045,"description":12046,"extension":140,"headline":12047,"icon":12048,"icon_author":10636,"icon_url":12049,"layout":143,"location":11464,"meta":12050,"meta_description":11305,"navigation":145,"path":12057,"quote":141,"seo":12058,"slug":12048,"stem":12059,"tags":12060,"template":6691,"__hash__":12061},"blog/blog/en/2012-08-09-cernsummerwebfest.md","CERN Summer Webfest",{"type":8,"value":11837,"toc":12043},[11838,11846,11852,11855,11860,11901,11906,11910,11917,11925,11936,11942,11950,11967,11970,11973,11998,12006,12009,12016,12024],[11,11839,11840,11841,11845],{},"The first weekend of August of 2012, CERN hosted the first ",[37,11842,11844],{"href":11843},"https://citizencyberscience.net/cern-webfest/index.htm","Summer Student Webfest"," where physicists, designers, computer scientists and engineers worked together in a 48 hours marathon to create a set of amazing web applications prototypes involving physics and modern web technologies.",[11,11847,11848],{},[47,11849],{"alt":11850,"src":11851},"CERN Restaurant 1","/img/blog/cern-resto1.jpg",[11,11853,11850],{"className":11854},[5330],[11,11856,11857,11858],{},"The first day, different projects were presented so the students could decide in which one they wanted to participate. Some of the ideas were proposed by the organizers, but also some of the students came with really good suggestions. At the end the projects that were chosen to work over the 48 hours period were:",[5493,11859],{},[565,11861,11864,11871,11877,11883,11889,11895],{"className":11862},[11863],"angle-list",[568,11865,11866],{},[37,11867,11870],{"href":11868,"target":11869},"https://citizencyberscience.net/wiki/index.php?title=Create_an_open_data_website_for_CERN","_blank","Open Data for CERN site",[568,11872,11873],{},[37,11874,11876],{"href":11875,"target":11869},"https://citizencyberscience.net/wiki/index.php?title=ParticleQuest_game","ParticleQuest a game to learn physics",[568,11878,11879],{},[37,11880,11882],{"href":11881,"target":11869},"https://citizencyberscience.net/wiki/index.php?title=A_cheaper_distributed_cosmic_ray_detector","A cheap Cosmic Ray detector built with Arduino and Android",[568,11884,11885],{},[37,11886,11888],{"href":11887,"target":11869},"https://citizencyberscience.net/wiki/index.php?title=Standard_Model,_Standard_Infographic","A new infographics and explanation for the Standard Model",[568,11890,11891],{},[37,11892,11894],{"href":11893,"target":11869},"https://citizencyberscience.net/wiki/index.php?title=Improve_the_LHC_Dashboard","A revamped LHC Dashboard using HTML5",[568,11896,11897],{},[37,11898,11900],{"href":11899,"target":11869},"https://citizencyberscience.net/wiki/index.php?title=Build_a_computer_center_in_a_virtual_world_to_show_volunteer_participation","Virtual Worlds for the LHC@Home platform",[11,11902,11903],{},[47,11904],{"alt":11850,"src":11905},"/img/blog/webfest-2012-people.jpg",[11,11907,11909],{"className":11908},[5330],"Hacking on science!",[11,11911,11912,11913,554],{},"One of the most repeated \"memes\" during this first day was that everyone wanted to  make as easy as possible the explanations about physics for the general public. As a consequence of this overlapping,  a huge team was created regarding the idea of explaining physics via a new Standard Model as ",[37,11914,11916],{"href":11915,"target":11869},"http://press.web.cern.ch/press/PressReleases/Releases2012/PR17.12E.html","one month ago the Higgs Boson discovery was announced at CERN",[11,11918,11919,11920],{},"The next 48 hours were amazing! The students arrived the Saturday morning around 10:00 am and they worked almost 48 hours non-stop in order to win the prize: a trip to the ",[224,11921,11924],{"className":11922},[11923],"text-basic","Mozilla Festival in London in November, courtesy of the Mozilla Foundation.",[11,11926,11927,11928,11932,11933,554],{},"The event was free-form based, so some of the projects evolved during the event, and for example the mega-team around making more accessible physics for the public split themselves in two small teams that worked together in the Standard Model and a new awesome idea about creating a new web tool to create ",[37,11929,11931],{"href":11930,"target":11869},"https://en.wikipedia.org/wiki/Feynman_diagram","Feyman diagrams"," and use it to explain physics ",[5823,11934],{"className":11935},[5826,5827],[11,11937,11938,11939,554],{},"It is really difficult to tell you how amazing it was, so I \"interviewed\" each participant so they have to explain what they have done during the weekend and if they were enjoying the event. The following video (14 minutes long!) shows how people worked together in different teams and their projects. The video was recorded before the prize ceremony, so you can feel the pressure of not having enough time to improve a bit more their project ",[5823,11940],{"className":11941},[5826,5827],[2889,11943,11945],{"className":11944},[5261,5262],[2893,11946],{"width":11947,"height":11948,"src":11949,"frameBorder":2897,"allowFullScreen":145},560,315,"https://www.youtube.com/embed/cky9OFcoIsI",[11,11951,11952,11953,11957,11958,11962,11963,554],{},"The winning project was the ",[37,11954,11956],{"href":11955},"http://particlequest.com/","ParticleQuest game"," (you can actually play it at ",[37,11959,11960],{"href":11960,"rel":11961},"http://particlequest.com",[41],") a fork of the Mozilla's Open Source game ",[37,11964,11966],{"href":11965,"target":11869},"http://browserquest.mozilla.org/","BrowserQuest",[11,11968,11969],{},"The competition was really tough as the projects created really awesome applications, but the best part for me was seeing how these students got really involved in the event.",[11,11971,11972],{},"We asked the participants what they liked about the event and if they were happy. The mega-team basically summarized the event like this:",[565,11974,3843,11976,3843,11987],{"className":11975},[11863],[568,11977,11978,11982,11983,11986],{},[11979,11980,11981],"b",{},"The event should start earlier",", so we have ",[11979,11984,11985],{},"more time to work"," on the project.",[568,11988,11989,11990,11993,11994,11997],{},"We have been able to ",[11979,11991,11992],{},"self-organized"," ourselves ",[11979,11995,11996],{},"without a supervisor","!",[11,11999,12000,12001,12005],{},"Amazing!! Indeed all the participants loved the event. Just to give you an example: after the prize ceremony ",[37,12002,12004],{"href":12003,"target":11869},"https://en.wikipedia.org/wiki/John_Ellis_%28physicist%29","John Ellis"," gave a special talk about the State of the Higgs Address. A few minutes after the full event was over, the students started to organized themselves again to keep working in their respective projects.",[11,12007,12008],{},"Another interesting outcome from the event was that only a few designers joined, but they were key persons to the success of all the projects, as they actually helped in every project (special mention to Andre-Pierre Olivier for his help in almost every project!).",[11,12010,12011,12012,12015],{},"The source code of the projects is available in ",[37,12013,11735],{"href":12014,"target":11869},"https://github.com/CERNSummerWebfest",", so if you want to know what we actually did during those 48 hours, go to Github and enjoy it!",[11,12017,12018,12019,12023],{},"If you want to see more photos from the event ",[37,12020,12022],{"href":12021,"target":11869},"https://pl72543786574640449","check the album"," I've created with pictures from almost all the participants!",[11,12025,12026,12027,9060,12029,12033,12034,12038,12039,554],{},"The event was co-organized by the ",[37,12028,10099],{"href":10097},[37,12030,12032],{"href":12031},"http://p2pu.org/","Peer 2 Peer University",", and sponsored by the ",[37,12035,12037],{"href":12036},"http://www.mozilla.org/foundation/","Mozilla Fondation","  and the ",[37,12040,12042],{"href":12041},"https://www.shuttleworthfoundation.org/","Shuttleworth Fondation",{"title":49,"searchDepth":130,"depth":130,"links":12044},[],"2012-08-09T00:00:00.000Z","The first weekend of August of 2012, CERN hosted the first Summer Student Webfest where physicists, designers, computer scientists and engineers worked together in a 48 hours marathon to create a set of amazing web applications prototypes involving physics and modern web technologies.","CERN hosts the first webfest for building new tools with students.","cernsummerwebfest","https://www.flickr.com/photos/32985084@N00/7771808714/",{"excerpt":12051},{"type":8,"value":12052},[12053],[11,12054,11840,12055,11845],{},[37,12056,11844],{"href":11843},"/blog/en/2012-08-09-cernsummerwebfest",{"title":11835,"description":12046},"blog/en/2012-08-09-cernsummerwebfest","CERN, Webfest, hackfest, science, physics","6LMaSrGn-DmBwQpgZrMVgyTozE4rO7GIQCRbIcqkaGI",{"id":12063,"title":12064,"author":141,"body":12065,"date":12149,"description":12069,"extension":140,"headline":12150,"icon":12151,"icon_author":10636,"icon_url":12152,"layout":143,"location":12153,"meta":12154,"meta_description":12159,"navigation":145,"path":12160,"quote":141,"seo":12161,"slug":12162,"stem":12163,"tags":12164,"template":6691,"__hash__":12165},"blog/blog/en/2012-02-26-earthquakes.md","Earthquakes & citizen scientists",{"type":8,"value":12066,"toc":12147},[12067,12070,12076,12080,12086,12090,12093,12100,12106,12110,12114,12117,12123,12127,12133,12139,12143],[11,12068,12069],{},"The Asia@Home workshop started focused on earthquakes and volunteers to track them.\nThe project The Quake Catcher Network presented their results an approach in different parts of the world (Chile, Christchurch, California, etc.) and a collaboration with Taiwan for monitoring earthquakes.",[11,12071,12072],{},[47,12073],{"alt":12074,"src":12075},"Jesse Lawrence","/img/blog/jesse-lawrence.jpg",[11,12077,12079],{"className":12078},[5330],"Jesse Lawrance by Daniel Lombraña",[11,12081,12082],{},[47,12083],{"alt":12084,"src":12085},"Angela Chung","/img/blog/angela-chung.jpg",[11,12087,12089],{"className":12088},[5330],"Angela Chung by Daniel Lombraña",[11,12091,12092],{},"This project uses low cost USB sensors to detect earthquakes that can be attached to any computer with an USB port. The only requirement is to screw the sensor to a wall or a surface so when there is an earthquake you the sensor will not jump.",[11,12094,12095,12096,12099],{},"There was a talk about a different sensor, ",[11979,12097,12098],{},"Palert",", that tries to measure earthquakes but using a different approach: self-sustained sensors that can have a battery to record the shock waves even though there is no power supply.",[11,12101,12102],{},[47,12103],{"alt":12104,"src":12105},"The Quake Catcher Network Sensor","/img/blog/quake-catcher.jpg",[11,12107,12109],{"className":12108},[5330],"The Quake Catcher Network Sensor by Daniel Lombraña",[11,12111,12113],{"className":12112},[5330],"A gadget by Daniel Lombraña",[11,12115,12116],{},"While all these talks presented the point of view of the projects, we have a nice talk from the point of view of the volunteers: Dudumomo. He presented several charts about how volunteers provide lots of CPU cycles to different projects, and only ask -in most of the cases- news about the research and progress that the project is achieving thanks to their donations.",[11,12118,12119],{},[47,12120],{"alt":12121,"src":12122},"Volunteer","/img/blog/volunteer.jpg",[11,12124,12126],{"className":12125},[5330],"The point of view of a vounteer by Daniel Lombraña",[11,12128,12129,12130,554],{},"There was a lot of discussion about different ideas to engage more volunteers, communities, outreach, new places for deployment, etc. After a first successful day, we relaxed a bit having dinner in one of my favorite Taiwanese restaurants: The House of tea, where everything, and when I say everything, is everything, is cooked with tea leaves ",[5823,12131],{"className":12132},[5826,5827],[11,12134,12135],{},[47,12136],{"alt":12137,"src":12138},"Beef","/img/blog/beef.jpg",[11,12140,12142],{"className":12141},[5330],"Beef by Daniel Lombraña",[11,12144,12146],{"className":12145},[5330],"Shrimps by Daniel Lombraña",{"title":49,"searchDepth":130,"depth":130,"links":12148},[],"2012-02-26T00:00:00.000Z","Asia@Home a workshop about citizen scientists studying earthquakes.","asiathome","https://www.flickr.com/photos/32985084@N00/6930671175/","Academia Sinica, Taipei",{"excerpt":12155},{"type":8,"value":12156},[12157],[11,12158,12069],{},"Asia@Home citizen science workshop on earthquakes","/blog/en/2012-02-26-earthquakes",{"title":12064,"description":12069},"earthquakes","blog/en/2012-02-26-earthquakes","hackfest, science, citizen, earthquake, damage assessment, geology","XEbKWb1EpDPITM6fU_iX2NwO_sfEHoBKWYeF4TEhLlU",1773164172208]