Menu

Recurse Center: Week 3

Follow my progress along at my new blog: !


 

My 3rd week at the Recurse Center went well, and felt like, hopefully, a bit of a turning point. In general, I haven’t had an externally bad day here yet, although internally, I’ve definitely had had a few conflicted and doubtful days.

Monday was MLK day, and an “optional” day at RC, but I saw no reason to stay home. I had a long dim sum lunch with a bunch of Recursers and alums in Chinatown, and then read up and took notes on lexers and parsers as a part of my compiler research. On Tuesday, I met with a faculty member to talk about getting support applying to jobs, which felt stressful. Having to talk about my experience and “tell my story” made me feel uneasy, and there were no easy answers to my questions ( a la “oh yeah, we’ll definitely get you a job”.) But, I look forward to getting some help from RC hopefully sharpening my profile. That night, I organized an outing Baba’s Pierogies (inspired by Victoria’s trip to Noodle House), which was fun and went well.

Wednesday and Thursday was the Hack RC event, where groups try to build tools for RC & generally improve the space. I and almost sat it out. I was feeling anxious about my compiler research – how little I understand, and how much fundamental CS knowledge I seem to be missing. I thought it might be a better use of my time to focus on really learning rather than collaborating. However, I figured – hell, it’s only day, and I already committed. I think the secret to life is low expectations, because the hackathon turned out to be one of the most rewarding things I’ve done at RC thus far. I was initially going to pair with Tom, and two more people – Adelle and Buyong joined our project last minute, making us a pretty diverse team in both background and experience.

Every hackathon I’ve been in has blown up in scope and collapsed in communication, so I gently but intently pushed us to define our feature set, scope out the project, and agree on goals and functionality before we started coding. I was really worried about coming across as bossy, and was grateful that my teammates not only followed me, but seemed to appreciate the structure this created. We worked for until 11PM on Wednesday, (breaking to get dinner and get sleep for the night) and all of Thursday, and actually shipped a Go/sqlite/JS pairing aggregator, called Matchbox. In addition to gently PMing the project (which felt wonderful), I worked mostly on the UI design and a bit of Javascript/UX, which felt right up my alley. I felt comfortable with this kind of work, and it was great to pair with Adelle. Her JS code was easy to read, clever, and effective. I am getting more and more comfortable collaborating and writing code communally, seeing patterns and thinking as we go.

At some point during the Hackathon, I grabbed tea with Rachel, one of the faculty members and chatted about the inner workings of RC, and met up with Dan – an ex-Codecademy colleague.

That Wednesday night, I finished coding around 11 PM, but hung out at the space until past midnight (by far, the latest I’ve stayed). A bunch of us sat on the couches, played guitar, and sang in the dimly lit space, as some Recursers around us painted a mural on the wall, and others continued to code. It was a truly magical, wonderful moment. I picked up the guitar and played for the first time since my birthday nearly a month ago. I was very rusty and messed up a bunch, but at RC, felt that it was okay to not be perfect. I relaxed and basked in the moment as I strummed the strings and others sang along. I felt like I really belonged.

After non-stop coding and paring on Wednesday, my 3 teammates headed off to an outside event, and I was left to present Matchbox to groups of RCers, which went well. I got compliments on the UI I had built (which felt great, since, I’ve really struggled with UI in the past) and general approval of the product idea that my team had synthesized together. Afterwards, I stayed for game night – more Avalon with now-experienced people! – and dollar pizza.

Friday was a quieter day. I had also been touch typing all week, so I practiced that a bit – I’ve started to notice positive effects even though I hadn’t yet learned the entire keyboard. I wanted to work on compiler research – I had resolved to present whatever I learned at the following week – but couldn’t bring myself to. So, I figured I could leave, or work on something else. So, I gave myself permission to go back to what I feel comfortable with for a bit, and worked on a small front-end text reader for more efficient reader. I also grabbed tea with Emily, and learned about her amazing trek across the Appalachian Trail.

I can’t predict how this will pan out, but this week felt like a turning point, even if on paper in a text editor, I hadn’t learned that much. I came to terms that I won’t become a compiler expert, and that as a result I don’t need to learn C. I timeboxed the project and committed to finishing it by Thursday next week, which pushed me to take a more general view at the topic. I’ll be presenting to a few people who know much more about this topic than I will have learned, and that’s okay – I’ll also hopefully share some new info with Recursers who don’t. Moreover, my goal is to have learned enough to feel comfortable having answered the question – “what makes programming languages different?” After, I decided can focus on learning and building in Rust, which’ll be a lot more practical than C. I can also focus on learning React, Vim, and maybe building in Swift or Electron – skills that’ll help my portfolio.

Also, after Hack Week, Pierogie Night, tea with Rachel (one of RC faculty members), another game night, and singing with other Recursers, I feel more settled in, more comfortable in the space. It’s not that I didn’t feel like I belonged before, but I am feeling more okay taking things at my own pace.

My goal this week was to be able to say – look at this thing; I’ve made real progress on it. Other than the hackathon project, which I did not plan for, I didn’t really accomplish that. Even though I really cut back on my coffee dates, having a Monday holiday and a slow Friday, with a 2-day hackathon in the middle, kept me from focusing on a single thing.

Next week, I look forward to giving a non-technical talk about either movie music or Learning How to Learn, and hopefully my first technical talk about how compilers work. We also have an informal job fair-type thing, so I’ll probably be doing a bit of prep for that. Can’t believe it’s been 3 weeks already! I feel good; excited for what comes next.

Advertisements

Recurse Center: Week 2

My second week at the Recurse Center was quieter and less productive than my first. I did a good job exposing myself to environments that are new and uncomfortable. I’m also slowly zeroing in on things that are interesting to me. I did a bad job sticking with any one thing or making significant progress on any of my goals, and I’am questioning some the goals I came in with.

In general, I did two things consistently: I worked on LeetCode problems almost every day, and I’ve been going through touch typing lessons, which I practice whenever I can’t handle any intellectually challenging work. I also continued to grab coffee with lots of interesting people.

On Monday, I spend an hour fixing up Tinylogger, so I could blog more comfortably (hoping to get more work done this weekend), read the Rust book, paired on a LeetCode problem that involved learning what a trie is, and helped Margo work on Game of Life in jQuery (with the constraint of reading cell state from the DOM, not a data structure). In the evening, I joined Victoria and others for a noodle soup dinner in Chinatown, and we walked the Brooklyn Bridge after, which was really fun. 

On Tuesday, I read a cool article about compilers and researched what the heck LLVM is, which I sort-of-vaguely understand. I also added a bunch of words to Hackterms as I learned new concepts. I chatted briefly with David, who’s done some great work on language & type theory and compilers, and he suggested that to understand memory operations, I might be better off learning C rather than Rust, since C code maps more closely to machine operations, and that unlike Rust (which is generally considered a more elegant language), C won’t try to prevent precisely the kind of memory errors I can learn from. We also had non-technical talks, and I wish I had presented. People gave talks about a Nazi-era German film, wilderness first aid, polyamory, Prasek’s Smokehouse Big H mascot, and ethical dilemmas. It felt like a mini Demo Day. I definitely want to contribute in a few weeks.

Wednesday, I came in planning to work on Nand2Tetris and Rust, but ended up pairing with Adelle on a basic React app – I reasoned I should keep jumping into spontaneous, new territory. I worked on a LeetCode recursion problem, which made my head hurt – I was able to solve it, but didn’t really understand why the solution worked. I then had a great coffee chat with Noah, and then a long and very enlightening walk with David, talking about compilers, low-level processes, and speculative execution.

Thursday, things slowed down. I spent a while trying to wrap my head around the LeetCode problem from yesterday, and finally cracked and looked up the answer, learning about memoization in the process. I then paired on another LeetCode problem, in Python (which I don’t know) using heaps (which I don’t understand). Again, trying to jump into the deep end everywhere. By this point, I was doubting whether I should learn Rust and all (also new languages are hard), so I avoided it. In the afternoon, we had a great feelings check-in. Afterwards, I felt exhausted, so after touch-typing through a few exercises, I went for a very early dinner by myself. It was nice to leave the space for 45 minutes and not have to worry for even a moment about having to be back. At RC, I can take the space for myself and do what feels right when it feels right.

After I came back, I watched a set of cool technical presentations, and lamented not contributing one of my own – but I’m not even close to having anything to share. Liz did an awesome presentation about unexpectedly deriving the harmonic series on a frequency graph while trying to identify a pitch from her microphone. I intentionally wanted to step away from product-driven work (where I build to make a cool product) at RC, but I think it’s a good idea for me to still tackle and present technically challenging and interesting projects. I am thinking about looking at D3.js for the music star map I’ve been thinking about forever (and we’ve been encouraged to follow our White Whale projects).

After the presentations, I went to my first-ever BrooklynJS and had a blast. It felt like a natural transition from RC, and of course I ran into 2 different RC alums there.

Friday was a slow and unproductive day. I spent the morning with Lee, pairing on Nand2Tetris Project 1, where we derived and connected common logic gates from NAND gates. I expected this to be fun, but it was challenging and new, and forced my brain to work in weird, uncomfortably hard ways. Lee, thankfully, was super patient and helpful in explaining the basics to me. After touch typing for a bit to feel a little more productive (I could now do the whole home row!), I grabbed a very long lunch with Jenn. After, I reconnected with the Nand2Tetris group and powered through a meeting about boolean algebra identities, and then worked on writing. the blog. The day felt slow and unproductive, so I wrapped up early to go home.

Overall, this week has been just okay. Everyone continues to be very nice and extra kind, but it definitely feels like people are settling into the projects and being productive. I, on the flip side, am not. I am glad I exposed myself to so many new and uncomfortable technical challenges, but I felt utterly, uh,dumb, in most of them – carried, fortunately, by kind and helpful batchmates. Rust was hard, but now it seems like C might be a better path, and I’m doubting whether either language is the right way for me to spend time. C will teach me to work with memory, but Rust is a hyped language that people are actually writing in. But, perhaps I should focus on React, JS/Ruby, and interview prep – skills that I think help me get a job.Although these individual decisions seem hard, I am absolutely loving being surrounded by code 10 hours a day, and I’m confident I can get better at LeetCode/algorithms/interview-type problems if I keep working on them.

Next week, I want to (1) continue learning to touch type (2) settle into a consistent schedule with a project I could present in the next week or two (3) grab less coffee with people 😦 (4) continue to solve LeetCode problems (4) start working through Cracking the Coding interview (which I finally ordered for myself!) and actually understanding the algorithms.  Most importantly, by the end of  next week, I want to be able to say – look at thing thing (whatever it is); I made real progress on it.

Recurse Center: Week 1

I’ve finished my first week at the Recurse Center, and what a week it has been! Week 1 has been inspiring, overwhelming, exhausting, and fun. Overall, I’ve been more productive than I expected to be – though, scatterbrained – and I feel excited to head into Week 2.

Perhaps the biggest surprise so far is how extraverted the environment has been. From the moment I got in on Monday morning, I’ve been talking to or working with someone non-stop. I’ve had to pull away from people and force myself work on the “quiet” 5th floor to get work done. Everyone’s just so damn interesting. For example, I was in the middle of pairing with Pam today and took a restroom break. On the way there, I said hello to a returning alum, and found myself chatting with him for a five minutes – when I nervously realized my break from pairing was over and ran back to keep coding.

Many participants from the previous batch still have 6 weeks to go, so there is already a structure of meetings in place, and our incoming batch is encouraged to set up a meeting for anyone interested in basically anything.

As a result, our communal calendar has been overwhelmed with super interesting meetings about Rust, writing together, music, VIM, philosophy, machine learning, mid-day exercises, pairing on LeetCode problems – you name it. Finally, on Zulip – our Slack-like internal messenger – people are always announcing exciting bubble-tea outings, outside-of-RC meetups, lunch plans, etc. So, I’ve been involved in a million things, and haven’t even had much time to look at my phone while I’m here.  As a result, I’ve been scatterbrained and flighty: trying a million things, but not sticking to anything except the week-long WebAudioAPI project (more on this in a moment.)

All these meetings, and conversations are very, very interesting and the connections genuine – so, they take a lot of energy. Even though I consider myself to be definite extravert, the first 3 days have been some of the most extraverted I’ve ever had. I’ve come home utterly exhausted each day. Our schedule is 10-6, but I’ve caught myself thinking that unlike a typical workday (where I’d try to be out the door shortly after 6), I want to be here. So, some days I’ve stayed till 8, and felt good about it. I’m doing things that are genuinely fun – so, why rush home?

Though I’m spending a lot of time at the space, how much I’m getting done is another matter. The facilitators, returning alums, and older batchmates are all encouraging us not to worry too much about how much code we write, as long as we’re having meaningful and enlightening connections. A common refrain is: “if you’re learning from your batchmates, you’re spending your time productively.”

Over the course of the week, I’ve been chiseling my plan for my time at RC, adjusting it based on what feels interesting to work on, what others are working on, and what I’m genuinely curious about. “What are you working on” is a common conversation starter (right after “so, where are you from?”), and answering it 37 times gives you a chance to try out variations and see how they feel. An answer I feel good about is: (1) low-level programming, likely in Rust, (2) NAND2Tetris, ideally culminating in working with an Arduino or RaspberryPi, (3) understanding how programs go from syntax to machine code, (4) interview prep.

My batch is large, very smart, and very diverse – which is wonderful. I’ve been pair programming a lot, which has been great. It’s validating and confidence-building to both successfully communicate programming ideas and see how different people think about code. On Tuesday, I paired with Nikhil to code Game of Life in Rust (which was intimidating and awesome have his help with), on Wednesday with Marko and Adelle on a tricky LeetCode problem, and throughout the week with Pam and Liz on WebAudio and Python.

While I haven’t made much progress in my my Rust, NAND2Tetris, and algorithms ambitions, I have gotten to work with 3 other awesome Recursers – Liz, Pam, and Jamie – on a WebAudioAPI/MIDI/predictive algorithm project that we even got to present for 5 minutes at the end of the batch. I learned a bit about generating sounds with the Javascript WebAudioAPI (which James has mastered and has been building cool things with).

On Thrusday, we had a feelings check in. It was nice to share how my week has been going, and validating to hear about the general feelings of uncertainty and being overwhelmed others were experiencing. I walked out feeling calmer and more peaceful, and the meeting impacted me more than I expected it to.

Later that day, during Game Night, I successfully introduced my wicked-smaht batchmates to Avalon, and we played two fun rounds. I felt particularly good teaching the game, which I’ve now done enough times to anticipate breakdowns in understanding, and try to involve people in play before they get lost on the minutia of voting mechanics. They kept playing after I left, which is a great sign!

Whew – so much to share. I caught myself returning to the thought that RC doesn’t feel like work – or school – and I think I subconsciously expected it to. In those environments, I’ve been wired to want to go home and do things that are fun – coding my own projects, or composing music. RC feels like I’m hanging out with the smartest people who are also going out of their way to be extra nice. As a result, we can smoothly transition from pairing/teaching/learning to game night and beer. Unlike work, the connections I have here are genuine, so it’s fun to go from learning together to playing together.

At the same time, I haven’t challenged myself too much this week. It occurred to me that I’m still falling into the habit of trying to seem like I know what I’m doing – trying to seem smart, in conversations. The WebAudioAPI project has been fun, but mostly within my comfort zone – I know how to whip up a UI, or read MDN Javascript docs. The hardest thing I touched this week was Rust, and I didn’t touch it again all week. Also, I’ve done a bit of everything, but haven’t gone deep on anything – I’ve been scatterbrained, manic, and flighty.

Next week, my goal is to settle into more of a schedule, and get more discerning about how I spend my time. I want to start (1) learning Rust, (2) working on NAND2Tetris, (3) daily touch typing, (4) VIM ? (5) interview prep.

All in all: I feel good, I feel humble, I feel accepted, I feel capable. Week 1 has been great.

Recurse Center: Expectations

In a few days, on 1/7/2018, I’m going to start a 3-month batch at the Recurse Center. I am beyond excited. I’ve written previously not getting in on my first try, and you may have stumbled on this post while googling everything you could find about RC – I know I did! I’ll be blogging weekly about my journey for the next 12 weeks, so I hope you find this helpful.

In this post, I want to cover what I plan to do, hope to achieve, and expect to experience RC. I imagine I’ll be hilariously inaccurate with my predictions, so this should be fun to read in a few months

Here are my programming goals for Recurse, roughly by priority:

  1. Pair program and learn from others as much as I can!
  2. Get hired as a software developer. The fundamental goal of RC is to help me improve as a programmer. A promise I made myself is that if I dedicated 3 months to this, I’d come out with a career I can depend on (which has been my biggest source of stress for a while). I see getting hired both as a financial imperative, and as validation that I’ve become a better programmer, to the point I can depend on my craft financially.
  3. Gain a deeper understanding of how code works when it’s run. I want to deeply understand what happens from when you run code to the point it becomes machine code. I’ve heard many reasonable explanations for why different languages are suitable for different tasks, but I don’t think I’ll really understand this until I trace how syntax becomes machine code.
  4. Gain a deep, under-the-hood understanding of Javascript (and Ruby, if I have time)  I want to finally go through [YDKJS](https://github.com/getify/You-Dont-Know-JS), finish [Principles of Object Oriented JS](https://www.amazon.com/Principles-Object-Oriented-JavaScript-Nicholas-Zakas/dp/1593275404), learn ES6, dig into Promises, Async/Await. I’d like to get to a point where I can, for example, make sense of how [Vue reactivity](https://vuejs.org/v2/guide/reactivity.html) works.
  5. Learn design patterns, and practice data structures and algorithms. I think there are usually study groups that form at RC to do this, so I’m excited to explore with fellow Recursers.
  6. Learn a new language with a new paradigm: Scala, Rust, Go. Both my RC interviewer and alums I’ve spoken to gave me the advice to learn something with a _totally different_ paradigm from what I’m used to.
  7. Stretch goals: use D3.js, build a project using the [WebAudio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API), build a MacOS app with Electron or Swift, learn React and build a small Rails app. I really don’t think I’ll have time for these things, but who knows!

Here are things I expect to be hard:

1. Learning so much complex information in a dense, short period of time
2. Learning to work with people from multiple backgrounds/communication styles
3. Prioritizing what exactly I should work on on a daily basis
4. Balancing my own projects with collaborating with other people
5. Prepping for interviews and learning algorithms and data structure questions
6. Balancing writing code with learning from/socializing with others
7. Writing and thinking about code 8-10 hours a day, non-stop

Here are things I’m really looking forward to:

1. Collaborating and learning from engineers from all walks of life
2. Being in a supportive, welcoming environment geared towards learning
3. The constraint of solely focusing on code for 3 months
4. Learning material that I’m genuinely excited to learn, and knowing that my trade can reward me with financial stability.

Recurse Center: TRUE

A year ago, I applied to the Recurse Center. I loved everything I read about it; it sounded like the Interlochen for code. I had a really pleasant interview process, and the application forced me to reflect on my ambitions and career in code in a meaningful way. And then, I didn’t get in. I was disappointed and didn’t try to hide it. But then, it dawned on me that I still loved to code. So, to cheer myself up, I built Space Squares, and then tackled my most ambitious project yet: Hackterms.

It’s been a year since, and I once again found myself at a crossroads. My “career” has been up in the air, but the unifying pattern in the last year has been writing code. For work and for myself, when I got sad or wanted to put something useful out in the world, I wrote code.

So, when I saw that applications were open, it just made sense to apply again. Whereas last year the app took me 2 weeks, this time around it only took a few hours. It was easy to answer the questions in earnest. I had a better idea for what my coding career might look like and what I would study at RC. I talked about how much I learned from collaborating with James and Esther. For my code sample, I submitted a project I whipped up for a reddit comment the day before. My interview process was accommodating, fast, and engaging, and within a week, I got the most exciting email I’ve seen in a year. I GOT IN!!

Screen Shot 2018-11-05 at 9.55.41 AM
I’m going to write another post in the future on why I think I got in this time and not last time (spoiler: ~60% luck), but for the time being, I’ve decided to start  with the next batch, on Jan 7th (2019 😅) , and couldn’t be more excited! I’ll definitely blog more about my plans before the batch, and plan document my experience throughout.

 

I’m a better dev than I was a year ago

I was refactoring an old project when it dawned on me that I’m a better developer today than I was a year ago.  There are very few places in my life I could say I’ve improved with such confidence. Are my friendships and relationships stronger? Am I a more empathetic person, a better musician, a more effective product manager? I vaguely feel better, but I can’t be sure.

But with code (and running), where there are concrete benchmarks to measure my progress by, I am sure. I am confident that I am writing cleaner, more maintainable, and more efficient code today than I was a year ago. Of course, improvement =/= mastery, and the more I learn, the more I realize how much is left to learn, but I wanted to take a moment to reflect. Compared to a year ago:

  1. I structure my code better

    I’ve often succumbed to jumping into my code head-first. It’s easy (and fun) to solve the problems in front of me, and hard to think through the repercussions and edge cases. This approach has bitten me in the tuchus a bunch of times, and in response, I’ve made a consistent effort to plan more. Before I tackle a big project, like Hackterms, I sit down and set up a Kanban-style Trello board, where I make myself prioritized tickets. Before I write complex functions, I write out my logic, and force myself to consider the general purpose of the function and the edge cases. I wireframe, I think through user flows, I sketch out relationships between pages, and design database schemas.

    I’ve got a long way to go, but I’m becoming more organized, and run into fewer surprises down the road. And, when I skimp on this process (by convincing myself  that “it’s just a small project”), I run into all my old problems, which only motivates me to plan further 
  2. I am writing cleaner, more efficient logic

    Thanks to my collaborations and pair programming with James and Esther, I have learned more optimal, cleverer ways to solve common projects: operate on and iterate through objects and arrays, keep track of my application state, break up my functions, operate on strings. Problems that used to take me twenty lines of code and multiple loops now take me ten. I haven’t gotten smarter – I’ve just seen more code. 
  3. I am using core language features

    James often pushes me, actively in our collaborations and indirectly through his work, to consider the core language features before looking at libraries. Influenced by this approach, I now frequently use the ternary operator, regex, flexbox, CSS animations and variable names, map and filter functions, just to name a few. 
  4. I am writing better functions and variable names

    Thanks to Esther,  Clean Code, and my work on the engineering team at the NYC Mayor’s Office, I am making an effort to write more maintainable code. An important realization was that writing clean code isn’t just for others – I found, with some surprise, that I couldn’t make sense of projects I wrote a year ago. Now, I think hard about my variable names. I try to break up my functions to handle a single responsibility. I split up my application into self-sufficient modules and components. 
  5. I am designing better interfaces

    After working to improve Hackterms, I am paying way more active attention to web design principles and patterns. For years, I’ve pulled up Chrome inspector to check out cool web design effects are achieved. Now, I take time to ask why. After brainstorming my own ideas, I check Dribbble for how other designers tackle common web elements. I’ve used Coolors enough to develop a better sense for what makes a good color palette (hint: it’s often multiple shades of the same color). I’ve got a long way to go, but I think I make better looking projects than I used to. 
  6. I am using git more effectively

    Kim Peng over at the NYC Mayor’s Office spent lots of time helping me make sense of git. The Atlassian documentation is also pretty great. My git experience used to  consist of add | commit | push, and occasionally frantically search for how to hard reset. I now use branches, and know how to handle fetching, merge conflict resolutions, moving the HEAD to a different commit, stash, cherrypick, and reset. 
  7. I have more tools to draw on, and know when to use them

    Over the last year, I’ve used flexbox and Vue.js, Mongoose, Handlebars.js, Socket.io, and Firebase hosting and data store. I understand what each of these tools do, and why they’re used. As I’ll never tire of saying, connecting the dots has always been the hardest part of web development for me, and I tended to grab popular off-the-shelf solutions without really asking why. Using Vue has been a breath of fresh air, for example, now that I’ve experienced trying to and parse state from the DOM. 
  8. I’ve seen more code and read more documentation

    At the Mayor’s Office, I had my code reviewed, and helped my teammates debug their code, and read the in-house codebase and documentation, and even contributed to it. I’ve taken Udemy courses. I coded with James and Esther. I read Vue.js and other library docs, and studied algorithms. Although I spent years helping design effective coding educational programs at Codecademy, most of that time was spent helping users just get off the ground. Now, I feel like I’ve leveled up; I’ve even helped beginners in my life write more efficient (not just functioning!) code.

It’s been a good and impactful year for me as a developer, but there’s so much still to learn. Looking forward to writing another post like this in a year!

The Node/Vue ecosystem

I’m learning Vue.js for a project at work, and I’m once again reminded how much of learning to code is about connecting the dots. I think of coding, in say, JS, as coming up with clever functions, refactoring, debugging, optimizing, writing beautiful algorithms. But, I’m going through Vue tutorials, and I feel like when I first learned Rails. Before I can even think about logic, I need to understand that (I’m oversimplifying):

  • Node is a back-end JS runtime
  • Express makes writing Node code easier
  • Mongo is a noSQL database, meaning it stores
  • Mongoose makes it easy to create and store and validate objects by using models
  • package.json keeps track of my dependencies and environment
  • NPM allows me to fetch libraries or dependencies for my app
  • Node allows me to write and export modules, including code from one file in others
  • Middleware is anything that happens to my request once a server receives it
  • Axios is the npm package we use to send requests because it supports promises out of the box
  • Babel compiles my code to ES6 on the front endd for older browsers
  • ES6 is the a more current, widely-adopted version of JS that includes important syntax updates; I don’t have to use it, but it’s important to understand. Vue runs on features (like import) found in ES6, I think.
  • Webpack compiles my JS files into one… I think?
  • Vue is a front-end JS framework that allows me to bind data and reuse components
  • Vue-cli is a tool that creates a Vue app scaffold and sets up my transpilation (with Babel) and compiles my files (with Webpack)
  • Vue instances and components are… let me get back to you on that.
  • BootstrapBulma, Skeleton or the NYC Opportunity Pattern Library are CSS libraries that helps me write pretty-looking elements – buttons, navbars, and so on quickly

This is the stuff that’s always been hardest for me, and the inspiration for Hackterms (which has been helpful, but definitely not sufficient). Each of the tools above has neat and expansive tutorials, but very few sources explain how the hell all these concepts connect – what fundamental purpose each solves. Maybe I just never realized that webdev is about understanding these connections as much as it is about writing beautiful functions. Anyway, I’m in the thick of it now, and once I get the flow of things, I’ll never cease trying to explain it in the simplest way possible. And in the short run, I’ll write an update post on, maybe even with an infographic to help illustrate how it all works.

Reading a CSV with Node.js

Here’s a really straightforward way to read a CSV with Node.js & Express. We’ll be using the following modules:

  • fs: “file system” included by default with Node.js, used to interact with files on your computer – or server, in this case
  • path: also included by default with Node, it is used to extract the filename from a path string. Basically, allows our app to work with string paths (“/server/data.csv”)
  • csv-parse: part of the larger CSV node module, this allows us to actually parse the CSV data into arrays.

As usual, here’s a disclaimer: is this the cleanest or best way to parse CSV files? Probably not – but it’ll hopefully give you a starting point.

Let’s say that we have a sample.csv file that looks like this:

Screen Shot 2018-08-02 at 4.00.27 PM

First, let’s get the data. Assuming your file lives in the same directory as your script (if it doesn’t, you’ll need to set your path starting from the root… somehow):

const fs = require("fs");       // access the file system
var path = require('path');     // read paths

console.log("dirname: " + __dirname);     // see your current directory
// create a "/sample.csv" path in the same directory as your script
var filePath = path.join(__dirname, 'sample.csv'); 

// read the file
fs.readFile(filePath, function read(err, data) {
    if (err) {
        console.log(err);
        callback(err);
    } else {
        // parse the file
        parse(data, {delimiter: ','}, function(err, parsedOutput){
            if(err){
                console.log(err);
            } else {
                console.log(parsedOutput);
                // do stuff with your output here
            }
        });
    }
});

Note this line:


parse(data, {delimiter: ','}, function(err, parsedOutput){ ... }));

The bit in {} are options. In this case, we specify that our data is separated by commas (hence Comma Separated Values), but there are other neat ones you can check out in the documentation under “Parse Options”.

Now, parsedOutput will contain your data as a multi-dimensional array, with one array per row, like this:

  [ 
    [ 'number', 'letter', 'planet' ],
    [ '1', 'a', 'mercury' ],
    [ '2', 'b', 'venus' ],
    [ '3', 'c', 'earth' ],
    [ '4', 'd', 'mars' ],
    [ '5', 'e', 'saturn' ],
    [ '6', 'f', 'jupiter' ],
    [ '7', 'g', 'neptune' ] 
  ]

 

Now you can play with your data – slice it up, rearrange it, send it to your front end, convert it to a JSON, and so on!

Hope this helps 🙂

Webtrends API authentication with Node.js

As a product engineering apprentice with the NYC Mayor’s Office digital products team (I guess I haven’t updated in a little a while), I am currently working on building an Analytics dashboard that draws from Google Analytics and Webtrends, an older analytics solution. Both have APIs that allow you to request relevant metrics. The Google Analytics API took me some time to set up, but my previous work on oAuth with Hackterms really helped wrap my head around it. Webtrends, however, was a different story. Their documentation is… not great… at all., and merely states that Webtrends uses basic authentication – which, as I’ve learned, isn’t simple authentication, but an actual, rather-outdated type of authenticating users.

Webtrends comes with a neat Generator tool that allows you to select the data you need, and then gives you a corresponding GET query to use. However, you are meant to plug this query into a browser, which then presents you with w a sign-in module:

Screen Shot 2018-07-17 at 1.55.29 PM

Of course, that’s not usable for API requests, which should be performed automatically from your back-end. So, the account info needs to be passed in via the headers. I started searching for how to construct a basic authentication header for Webtrends, but couldn’t find any up-to-date info, let alone in JS. So, here is a basic Webtrends connection, with Node.js and the npm request package, which simplifies sending requests.

The Webtrends username is constructed with Username and Account, separated by a backslash.

username: username\account

What nobody mentions is that the backslash needs to be escaped. This is really important!

username: username\\account

So, for example, if your username is TakeshiKovacs, your account is Envoy, and your password is Resolution653 , your combined credentials would read:

TakeshiKovacs\\Envoy:Resolution653

According to these helpful MDN docs, you construct a basic authorization header like this:

{
  Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
}

The YWxhZGRpbjpvcGVuc2VzYW1l bit is actually your username:password (literally, username + “:” + password), encoded in Base64. In Node.js, in order to encode in base64, we use the Buffer object, which performs all sorts on encoding and decoding operations. In order to encode a string as Base64, we use new Buffer.from( some string ).toString(‘base64’);

So, to sum up, the basic authorization header is:

{
  Authorization: Basic + new Buffer.from(username + ":" + password).toString('base64');
}

Once you have the URL from the Webtrends generator, the complete GET request for data (with the dummy credentials from above) looks like this:


var request = require('request');
var auth = "Basic " + new Buffer.from(username + ":" + password).toString('base64');
// var auth = "Basic " + new Buffer.from("TakeshiKovacs\\Envoys:Proposition613").toString('base64');

var webtrendsURL = "https://ws.webtrends.com/v3/.../"; // your webtrends URL from generator;

request.get({
    uri: webtrendsUrl,
    headers: {
        Authorization: auth
    }
 },
    function(err, response, body) {
        if (err) {
            console.log("ERROR!");
            console.log(err);
        } else {
            console.log("Got a response from Webtrends!");
            console.log(body);
        }
})

PS: you should store your credentials as environmental variables so they don’t get exposed. I used dotnev, which was straightforward and easy to implement.

Hackterms, Pt II

I had spent some time trying to get Hackterms off the ground, and then stalled and left the project sit for a month. I had spent days agonizing over small design decisions – lining up icons and such –  and then had a single, successful push for my first 20 users.

And then I stalled. Interestingly, this slowdown didn’t come from negative feedback or a lack of interest. I expected harsh user feedback, trolls, needing to cut/revamp features, user churn – in a word, users not caring about the site and not giving it the time of day. I was prepared for it. However, none of that really happened. A few of my users were moderately interested, and then I ran into a few pretty complex bugs – for example, the Submit Definition button wouldn’t work on iOS. Early adopters were still responding on my Slack channel. Though I always responded, I often didn’t come through. I kept promising to return to fix the bugs, and then kept stalling and kicking the ball down the road.

However, unlike some of my past projects, I never considered abandoning Hackterms. Even after about a month of inactivity, I thought about the site frequently, and – between encouragement from friends and belief that this project should be out in the world – was itching for a chance to come back to it. Stepping away from working on the problem daily gave me space to think deeply and reconsider my approach.

When I started, I attacked Hackterms enthusiastically, jumping into the fray (as I tend to) and building, designing, and planning all in one. Although I  wireframed and set up a kanban-style Trello board, prioritized features, and otherwise tried to plan ahead, the truth was, my structure was convoluted, and I had made a lot of imperfect technical decisions. For example, I was using a mix of EJS and Handlebars.js to render definitions and comments. When a Slack user asked how he could try to contribute to the code, I attempted to explain the data flow to him and realized it was anything but intuitive. To be honest, I myself was a little worried about revamping parts of the site because I couldn’t remember how I built them myself.

Sloppiness like this is the tradeoff for building quickly, but I had gotten to a point where my core features were up, and it was time to do two things:

  1. get some serious users (I arbitrarily decided on 100 unique users and a 1000 definitions as my goal). I was at 20 users thus far.
  2. revamp my code to make it readable, accessible, and ready for collaboration. Esther suggested open-sourcing the project (which was also the top-comment Reddit request), and I wanted to be able to get James’s help with my code.  I was anxious about this, but I knew that it was important to clean the code up.

I was reading the excellent Lean Product Playbook (highly recommend!) and kept thinking about how I could apply my learning on Hackterms. The book explained a lot of the topics I sort-of-intuitively half-assed in a very structured and insightful way. No matter how much it sucked to admit, I was making the fatal mistake – I was coding a massive project (telling myself it was an MVP) before getting real user feedback. My sort-of proof of concept was a massive encouraging reddit thread, and a few initial users. I was kind of following a lot of Lean principles, but not in any structured way. The book encouraged me to come up with hypotheses about who’d use the site, brainstorm a set of features, select my top features, categorize them using the Kano model, and then test them.

I had done  this, kind-of, sort-of.

  • I had come up with a value prop based on my own experience: users want to quickly identify what a coding term does and where it fits in
  • I came up with a minimal feature set: users need to be able to search for and view definitions, and also add new definitions for a given term
  • I then added with what Kano calls a “delighter”: instant search (search/display with every letter you type, just like Google!)
  • After that, I went off the deep end, and decided to build a moderation system that queues up new posts for approval. This was not necessary for an MVP at all. I was anticipating a problem that might come with scaling – trolling and irrelevant content. However, I actually spent forever building this.
  • My proof of concept was effectively marketing: lots of Redditors said “this is a great idea!” I then got a few of them to join after I built the product.
  • I conducted pretty extensive qualitative research with my closest friends. I sat next to them and watched them used

In my last job at Codecademy, one of my managers repeatedly disparaged me from relying too much on intuition in decision-making. Reading the Lean Product Playbook, along with the time that I stepped away from Hackterms reinforced just how important planning, forming hypotheses, testing them, and using metrics is. Up till this point, I’ve been (quite frankly) a bit confused about the relationship between data and intuition in product. Data seemed like the “right way” to make decisions, but we also glorify brilliant product visionaries (you know exactly where this links leads) and the idea of solving your own problems (which may not be other people’s problems).

The book really set me straight on this, coalescing a lot of the advice I’ve heard (but not understood from others). Early on in the product, you rely on intuition. I used to picture this as closing your eyes and visualizing/brainstorming brilliant ideas – but, really, you form hypotheses based on your (often unconscious) understanding of the space. That’s why solving your own problems makes sense – you don’t have to guess at others’ pain points, because you know your own. Anyway, you come up with hypotheses, and then you build some version of the product ( your MVP), and then you test it – and rely on data to tell you if the product is working (in other words, whether you’ve achieved the mythical product-market fit).

I wasn’t totally wrong – I just attributed way too much mystery and magic to “getting it right with intuition”. I learned that no matter how you come up with your product hypothesis, you need to figure out (1) exactly what you’re testing (2) what core metric represents this – Dan Olsen says that early on, this is usually user retention, and (3) who your target users are. Basically, I needed to create a framework within which I could be creative; direction to my decision-making.

I had a strong personal problem that I wanted to solve with Hackterms, and a lot of intuition around why others might need my product (that I developed spending time around people learning to code), and roughly knew that more users and definitions is good. But, but I never properly formulated my hypothesis, picked a metric to test, and put it in front of users.


Around this time, I stumbled on Courtland Allen’s interview for a YC podcast, which in turn brought me to Indie Hackers, and then IH’s interview with Pieter Levelsand one of Pieter’s own talks. This seriously kicked my ass – especially his advice on validating by launching.

I knew because I spent one year on this Tubelytics app and that didn’t work so I was like, okay I shouldn’t have spent so much time. I should have done more startup stuff just ship, and deploy, and launch, and validate, this is my idea and this was definitely new or my perspective on it was new, validate by launching. You don’t know if the app is going to work but you need to launch it, see if it’s going to work and you need to understand that most apps won’t work. I knew that, so I was like, “Okay I’ll just do a lot and I’ll see what sticks.” like throwing spaghetti at the wall and then I started making one thing a month.

I had spent nearly four months building Hackterms on and off, and I knew strongly that I needed to validate or move on. So, I finally did something I’ve been meaning to do for months: I invited my friends James and Jon to add some more seed content. We sat around a table, ate pizza, and wrote content – and talked about what good content looks like. We ended the evening at ~125 definitions. I decided it was time to share Hackterms with the world, and deal with whatever the consequences are.

If users asked for changes, I’d make them. If the website flopped, I’d move on.

I put the finishing touches on the last muse feature – a list of most searched and most requested terms, and then shared the post on Indie Hackers. I waited eagerly all day, aaaaaaand…. nobody responded. People visited the site, looked up the top searched terms, and then left. No new definitions added, no comments.

The next morning, I got up early, and posted to Indie Hackers again, this time using the “Urban Dictionary for coding terms” tagline, and also posted on r/webdev (which was technically against their subreddit rules due to timing.)

giphyIndiehackers stayed dead silent, but Reddit gave me an enthusiastic welcome back. Despite the fact that I kept waiting for my post to be removed (because you could only show off projects on Saturdays, and it was a Tuesday), I suddenly had more users on my site than I ever had before.

Things got a little wild as I watched the user numbers climb up and more user dots appear on the global map. I was getting a ton of upvotes and a ton of really great comments. Amazingly, people were signing up and adding great definitions. The number one suggestion was “add oAuth”, which I quickly learned meant one-click Google login.

Screen Shot 2018-02-13 at 11.34.29 AM

I hit the top post on r/webdev, and the site briefly went down at about ~80 simultaneous users, which left me absolutely terrified – because, frankly, I had no idea what to do. Fortunately, after I restarted the server, it seemed to continue working on its own, and I thanked my lucky stars. Someone even posted the link to Hacker News, which I was mildly terrified to do myself – they’re serious technical people over there!

Screen Shot 2018-02-13 at 10.41.04 AM

And then… my run for the day was abruptly over. My post was removed, because it wasn’t Show Off Saturday or r/webdev – as I mentioned earlier, it was Tuesday. In a way, though, this was good – it gave me a good taste of what having lots of simultaneous users is like, and I got some great feature suggestions.


The #1 request I got was to implement oAuth in order to allow users to log in with Google/Github, so I got to working on this. Integrating these was a bit of a pain, so I wrote a whole another blog post on this – but managed to get it working! Additionally, I spent more time coding with Esther,  and further tweaked my design based on her feedback. Every time I looked back at my older designs, the site felt more and more out dated – and consequently more modern with every tweak. So, I wondered how outdated the site looked now, and how I could improve it. I kept paying attention to designs I’d see on the web, and integrating little tweaks to my site. James pinged-ponged my own advice back at me – don’t try to reinvent the wheel. How do other dictionary sites handle their design? It was good advice, and I followed it.

Around this time, I was about to start two different jobs – one was a long-term contract, and the other a weekend consulting gig. I knew I wouldn’t have the luxury of working on Hackterms as intensely as I have been, so it was time to get my user #s up. I had received validation from my previous launch, but it still felt like luck – like my users were doing me a favor. A few weeks later, motivated  by an impending deadline, I decided to launch again, I knew I’d have less and less time, so it was now or never. My girlfriend and I were visiting friends in Boston to celebrate a birthday that weekend, and I finished oAuth for Github and and Google that Saturday morning. I knew I’d have little time to participate in the ensuing discussions, but I was slated to spend the next 4-5 weekends working, I didn’t have much of a choice. I decided to launch and trust the site to hold its own.

I once again posted on reddit on both r/learnprogramming and r/webdev, and… once again, the post exploded. Except, this time, it exploded much more on r/learnprogramming than on r/webdev.

Screen Shot 2018-04-02 at 12.22.01 PM

I was sitting in my friend’s living room, and I had my laptop open, trying my best not to get distracted from the joyous hangout. After a while, they became curious about the climbing numbers, and I briefly told them about the site.  We were watching my post climb the rankings, and the user numbers creep towards 50, and then 80 – where the site leveled off before. From my previous crash, I assumed that the reddit hug of death would be me eventually, and I didn’t know why or how to fix it. I was getting more terms and signups, and the post was at maybe 300 upvotes; it was an amazing feeling, and it was great to know my last launch wasn’t a fluke.

As steam picked up, we watched the number climb closer and close to 100. And then, the site crashed. Without skipping a beat, I restarted the servers. We were back up. Except, this time, I glanced at the log. It looked like the crash was cause by a regex parsing error. The site stayed up, and I went back to playing our board game. Except, ten minutes later, the site crashed again. I checked the logs – same error. This was great news. The Hug Of Death wasn’t bringing my site down – a simple code issue was. I excused myself for a few minutes and dug into the code. The issue stemmed from a small search function that converted non-alphanumeric characters into ones digestible by URLs. The simplest thing was to just comment it out – this would impact search results for terms like C++ and A*, but in return, would prevent my site from crashing. Worth it.

I pushed the fix, and held my breath as I went back to playing the board game. No more crashes.

And then, to my disbelief and my friends’ delight,Screen Shot 2018-02-24 at 6.02.05 PM.pngwe crossed 100 simultaneous users. It was a completely arbitrary (vanity) benchmark, but it still felt surreal to see. Over 100 users were on Hackterms, and it wasn’t crashing anymore. The dreaded Hug of Death wasn’t getting me, and I managed to isolate and fix the coding errors that brought me down earlier. Positive comments were pouring in. Lots of users were signing up to create new definitions.

In a flattering move, I even got trolled – which I took as a huge compliment. Users caught wind of the fact that searching things would add them to the “most searched” panel, and … rickrolled me. I got a good laugh out of it; it hurt me to take these down, but I knew I needed to keep the integrity of the content.

Screen Shot 2018-02-25 at 1.53.22 AM

Never gonna run around… and desert you!

 

Two more noteworthy things happened that day.

First, because the population of r/learnprogramming is by design made up of beginners, I got a lot of visits and user signups, but not nearly as many definitions. My user count jumped from 54 to 250+. This stumped (and encouraged) me, because I couldn’t see a reason for people to sign up other than to add definitions. However, due to this huge ratio of learners, I got an influx of searches, but only about ~300 new definitions in the next few days (which was amazing, but also a much smaller ratio than my r/webdev launch).

Second, I got a crash course on internet security. Someone spammed the site with XSS, which I knew nothing about, and users were reporting crashes. Users had injected JS through my definitions, causing all sorts of alerts to run – including one that caused an infinite loop: while(true){ alert() }

I felt totally out of my depth, but with a bit of research, quickly sanitized input and removed the definitions. In the grand scheme of things, this was an important lesson, but (thankfully) didn’t majorly impact the launch. Later, I found that users had been complaining about popups/weird terms on my /all page throughout the day, but I didn’t see it till the evening.

A few users even emailed me to help me fix several security loopholes – including a clever one where a user managed to impersonate me with invisible characters. It was a really nice thing to do.

It was fascinating to watch the change in development priorities. While building the MVP, I tried to focus on validating crucial features, asking do people need this? Now that lots of users were on the site, a very different set of priorities was becoming relevant. Where is your privacy policy? Can I delete my past submissions? Is the input sanitized/secured? Why aren’t you running an HTTPS site? Do you have a docker image I can contribute to?

All in all, I ended the weekend with ~350 definitions and lots of new users. The launch was clearly a success, and contributors – if not learners – were eager to share their knowledge.


Over the next few days, residual definitions kept coming in. I launched on Saturday, and the following Sunday to Tuesday, users continued to frequent the site, catching up on reddit threads from the weekend. A few days later, I was out to dinner with James, and was telling him about the launch. I told him that I got a bunch of Twitter mentions I didn’t know about, and was showing those to him, when an article – posted just hours before – caught my eye. Dice, a job search site, had written about Hackterms. Reading through the review, I was floored. It was positive press, and it was spot on with what the site was trying to do:

… the crowdsourced definitions are far easier to grasp than Wikipedia or general web searches. Written by developers and engineers who probably have to explain these terms regularly seems to be a winning strategy.

I was amazed and humbled and floored. I wrote the author to thank him for the article (and  not-so-subtly asked if hew knew anybody else who might want to write about the site), and I continued personally emailing each new Hackterms contributor. A few days later, we got another writeup by JAXenter, a java-focused tech publication – again, spot on about the mission.

Obviously, programmers have personal preferences about what tools and frameworks they uses. However, Hackterms makes no judgement calls as to the superiority of one system or another. They also don’t go over code snippets or examples. This is a dictionary, not a how-to explainer. The goal here is to provide definitions as clear and concise as possible.

I was elated, and took a few days to think about what happens next. 1000 terms seemed like a good short-term goal to aim for. It was clear that devs want to teach – but would Hackterms be helpful to learners? I needed to figure this out.


James suggested a great thing, which was echoed by the Dice article. He said I should tap into individual coding communities – Swift, and Haskell, and Rails, for example. My job start date got pushed back a week, so I had another Saturday to launch – and I couldn’t let it go to waste. I looked up the top programming subreddits, and realized I never launched in the biggest one: r/programming. So, a few days later, I posted on a couple more subreddits – r/programming, as well as r/iOS, a WordPress, and a Haskell subreddit. This time, I linked the Dice article, to give the site some legitimacy, and (frankly), to show off a little.

The post started picking up steam in the morning. As new definitions came in, I would routinely go into Mlab (where I was storing my mongo database) and combine/merge certain terms in order to keep the definitions consistent (for example, merging backend and back-end, or node.js  and nodeJS). I was making one of these changes, half-absentmindedly (I was in a pretty bad mood that day), when suddenly I saw my realtime user numbers fall from 80 to 25. I saved a term I was working on in Mlab, which refreshed it, and showed me a snapshot of my database. I glanced at it, and then stared at it in horror as I slowly realized…

… my term count was 0.

I opened the site, and there was no content. Thank god, my definitions seemed safe, but given how I structured my data, definitions couldn’t be pulled up without terms. I had just hit 375 terms (from ~330 at launch an hour ago), and all my terms were all gone. I refreshed the site a few times as the reality set it.

For about two minutes, I genuinely thought Hackterms was done for. For the hundreds of hours I had put into coding the features, the true value of my website was its content. Hundreds of people took the time to write thoughtful definitions, and now there was no way to access them. Never mind that my launch was an embarrassment – there was no longer any content on the site; I had let down all the users who took time to make accounts and contribute. All that work, done for.

(I later found out that I most likely caused my own error. Absentmindedly, instead of deleting one duplicate term record, I deleted all of them.)

crash

I consciously had to grab myself by the back of my shirt (figuratively, of course), and pull myself out of the downward spiral I had entered. I wasn’t going down without a fight. I was tempted to look at the reddit thread – no doubt, dozens of messages about how my site is broken were coming in, but instead, I stopped and thought.

I had no backup. But, thank god, the definitions were safe. The core of my content was fine. And, each definition had a term field. So, if I could somehow pull the terms from the definitions and create 375 new records from them, my site would be up.

I wasn’t going to go down without a fight. I knew there was no instant fix, and the launch was botched – but not over. It was only 10AM; the post would be up for a while. As tempted as I was to look at the repercussions of my crash on reddit and feel bad for myself (it was bad – I was having a bad day, and I just wanted to sulk,) I knew I needed to focus 100% of my attention on fixing this mess – and there was a glimmer of hope. I brought the site down for maintenance on Heroku.

My first thought was to try and rebuild the definitions manually, by brute force, but 375 records would take me forever to create. Plus, each mongo record has a unique ID, and I couldn’t make that up – I’d need to add each record one by one in Terminal. No, that wouldn’t work. A better way would be to cycle through each definition, and create a term based on the term field. I could test for duplicates (since some terms had multiple definitions) as I created the records.

The code would be messy, but not difficult. I knew how to do it. I sat down and began writing code, doing my best to quiet any negative thoughts swirling in my head. At the surface, the code wasn’t difficult:

  1. cycle through each definitions
  2. grab the term attribute and search the database for it
  3. if the term didn’t exists in the DB (search.length == 0), create term
  4. move on to next definition

I went into my local environment, which had ~75 fake definitions, and deleted my terms collection to recreate the error. I wrote the code quickly and with surprisingly few errors. I kept trying the simplest solutions I could think of – to cycle through my definitions, I used a for loop to read each term, and if there was no such term, create it. Mongo threw an error – the for loop was executing almost instantly, so I was creating too many records in a very short time. Simplest solution? SetTimeout. After getting a quick solution to the classic for loop/setTimeout quagmire, I ran the code locally. Amazingly, it worked. I knew I could afford to fuck up a bit – if I accidentally created duplicate terms, or even most terms, I’d be okay. I could clean it up, fill in the holes. I just needed to automate the bulk of the work. I named the trigger button “restore database”, ensured it was only accessible to me, and gave it the id of “Jesus” (to bring my data back from the dead.)

I pushed my code to production, and checked Heroku logs, then turned Heroku maintenance off; the site was live once again, with no content. Very quickly, I started getting a ton of traffic. I took a deep breath, watched the site logs like a hawk, and hit my “restore database” button.

And… nothing. I didn’t know why, but it didn’t seem to work. I ran it (erm, pressed the button) again. This time, I got two terms! I didn’t know what was happening, but guessed that my (empty) Terms collection was getting to many requests from incoming users to process my function. Google Analytics told me there were 30-40 people on the site, and I needed to shut off their access to the DB so I could work on it.

Again, I went for the simplest solution. I redirected anyone on the site to a simple white page that succinctly stated “down for maintenance”.  No DB access. Then I set my routes so that only the user named “Max” (erm, me) could bypass the page.

I pushed the code, navigated to my button, took a deep breath, and hit the Jesus button. I refreshed the Analytics page frantically to see how many terms I had. Within a minute, the number climbed to 375. My fix worked flawlessly. I tested the site, and definitions showed up just fine. I was back.

I turned off maintenance mode, and users came flooding back from Reddit. I had been down for an hour. Nobody cared; nobody knew. The users who saw Hackterms down probably left and never came back, but there were hundreds of other users behind them. I braced myself and checked the threads. It was only 11AM (NYC time) in the morning, and the SF crowd was just waking up, and the NY crowd was just getting to brunch. I knew the bulk of my users would be visiting later, when the site was running.

Needless to say, I didn’t touch the definitions for the rest of the day.


 

r/Programming loved Hackterms, and I was on top of the subreddit once again. Visitor number hovered between 80-100, and the site wasn’t crashing!

Screen Shot 2018-03-03 at 5.16.47 AM.png

I was getting lots of positive feedback, and users were adding terms from my “most searched” list, which was a nice positive – the feature was appealing to users, and more importantly, guided eager new contributors. I continued to invite the most passionate contributors to a Slack channel, which gave me an opportunity to run ideas by (and gather ideas from) a group of dedicated followers.

Over the next few weeks, I obsessively checked Twitter for mentions of Hackterms, responded to every single user who signed up, and kept stirring the pot in the Slack community, getting some great feedback. I also became more active on Indiehackers, offering advice where I could, looking out for similar products, and asking for advice in return. One user even generously drafted a Hackterms redesign (which I continued to tweak, with Esther’s help).

header comparrison

Redesigned header (old header – top, new header – bottom)

I added a number of new features based off the user feedback, including this changelog to help my users (and, as it turns out, me!) keep track of the changes. Most significantly, I added cross-definition linking, automatically connecting terms to other definition on the website – I got a brilliant solution from my ex-Codecademy colleague, Reed (“just let the browser do the work!”).  I also added support for markdown and redesigned the search page header.

Screen Shot 2018-04-15 at 1.34.34 PM

Automatic cross-term linking


Screenshot_20180402-082033_Chrome.jpgOn April 1st, I was browsing the web, looking at all the awesome April Fool’s pranks, and thought to myself – I could do this next year! And then I thought – why wait till next year? I have 7 users total, four of which are my friends – I can afford to take a risk! So, within a few hours, Cluckterms was born.

Somewhere around this mark, to my amazement, the site crossed 1000 terms (~1100 definitions). The last nearly 100 came from a particularly enthusiastic user, and I challenged the Slack community (and prodded my close friends) to help get us over the finish line. 1000 is a completely arbitrary number, but it sounded significant to potentially talk to reporters. “Yep, our website is at 1000 terms.”

I also applied to YC. This was a scary thought, but a pretty straightforward process, and one that I felt I owed to myself. For years, I idolized YC, loved (and worked at!) YC companies, read YC advice, and dreamt of one day building my own thing. And now, I was able to actually build (with my own knowledge) something – maybe not great – but something that attracted users, something I could apply with. If you’re curious, you can watch my video here.

I didn’t know if I’d get in, and I kept my expectations low. On one hand, I had users and a working prototype. On the other, I didn’t see a billion dollar market and haven’t made a dime. I just built a thing I would have wanted, and it was clear others wanted it too.

My product management apprenticeship at the NYC Mayor’s Office picked up, and I found it harder to motivate myself to work on the site some evenings, though I was challenging myself to write even a little code in the mornings and during lunch. Growth slowed a bit, and I once again found myself in a little bit of a slump. Looking back at this blog post helped – because I was in the same place before I launched on Reddit in ~December/January, sitting around with 25 users.

I now had over a thousand terms, a cool design, and proof of concept. People seemed to dig Hackterms, and even during a total slog, the site grew little by little each day.

Screen Shot 2018-04-15 at 2.09.43 PM

The slow days

I needed to expose the site to a wider audience, get some press, and (gasp) make even a dollar in donations/revenue. If there was a distant feature where my life would involve making products useful to people, than I needed to prove to myself that someone was willing to pay me for my work. I didn’t know the whole path forward, but I knew there were three big (and scary) launches I could target:

  • Product Hunt
  • Hacker News
  • r/dataisbeautiful

Each of there could take my site down technically, and with criticism – but I had to move forward somehow, regardless of what YC said (and frankly, I had no expectation of getting in).