The task was to build an offline capable site which displayed the latest Hacker News posts, and loaded more lazily when scrolling.
I had to use the official HN API, and I couldn't have any middleware or caching. Everything had to be done client-side.
The app ended up being 1.4kb in total, with support for practically streaming in the items, batching them by network response times and render frames, while keeping the order.
There's an irony about posting in a topic about simple, vanilla, no-framework scripting and then linking to a repository with the following unnecessary ancillary files:
Plus the actual source code is spread over four TypeScript files, JavaScript, CSS, and HTML.
This isn't meant as criticism of your code specifically but of "modern" web development which hypocritically espouses simplicity but actually increases complexity of development.
My point is your app could have been a single HTML file (or HTML, JavaScript, and CSS if you want to split hairs). Instead there's 15+ files because that's the state of modern development.
I really don't like posting in this passive-aggressive quote-answer format, but I feel that I need to address each point specifically.
> no-framework scripting
This isn't a script. It's a project for a mini app.
> My point is your app could have been a single HTML file (or HTML, JavaScript, and CSS if you want to split hairs)
The app has no bundled deps and no framework.
I actually just went on CodeSandbox, started a vanilla TS project (could've just as easily be JS + jsdoc since both CodeSandbox and VScode are using Monaco, but why would I?). 2 clicks. It uses parcel but I could've just used vanilla JS imports. That's what a few of the other artifacts are from.
Lastly, the app was built as a monolith initially and then I split out a few things to make it more readable.
> .gitignore
bruh.
> README.md
BRUH.
> REQUIREMENTS.md
It's there for the people who need more context
> manifest.webmanifest
It needs offline support. That's how the platform works. Same goes for sw.js
You're being a bit dishonest and writing in bad faith. If you work in web development, you know that the times of inline JS and styles in an HTML file, uploaded via FTP to a LAMP server are long gone. Like, 10+ years gone. If you are still romanticizing that, you may have an advanced case of Old Guard™.
If you are a non-web developer, then I hope you don't apply the same reasoning in your everyday work, for your colleagues' sakes.
Right, OP totally should have included the interview question requirements as a commented block at the top of index.html instead of separating it out. It's way too complex as is.
And definitely, .gitignore is well known to be responsible for the "complexity of web development." Maybe we should include .gitignore in index.html too?
That's nice. I myself did try out one too, as a hobby project to serve as an alternative frontend for a local gym https://varjosport.net/ There's a small flicker as the app generates the HTML which still annoys me but I couldn't bother to write a Lambda to server-side render the HTML every time the data is refreshed.
One thing I noticed though was that creating HTML fragments is a major pain in the ass, which I see you've solved with .createContextualFragment Interesting, I might have to try that one out too.
I myself quite immediately after starting to parse my JSON payload and turning it into dynamic HTML elements turned to Preact, which I guess as a lesser version of React is an acceptable choice. One thing which still was left to irk me were the CSS classes. I'm not a big fan of writing them anymore, with BEM syntax or not. Styled Components in my opinion is the future of writing modular React/web components. But since I vowed to myself to keep this simple, I stuck with CSS.
But it's indeed an interesting project to create a minimal modern website without the massive toolings/libraries you normally take for granted with React etc. There's a lesson there to be learnt in how sometimes that complexity is unnecessary, but sadly it's often not in the scope of a project to start optimizing such things. And I can't blame them, since when things get complicated you much rather have your app already written in React than having to rewrite it from custom JS/TS mess.
With styles in components, can you support skinnable components? If so, do you have to accept parameters in the component and modify the component every time you want to change some style to make it fit with your page look and feel?
If you mean theming components, then yes. Skinnable components is not a term I've encountered before but theming is something SC enables and is part of its core functionality. You can either use something like a global theme variable to set styles, which each component can depend on or just the regular props for different styles eg <Button intent="success />
I myself have mostly just remained with a one default theme, although adding a dark-theme has crossed my mind several times. It's just that UI features like this are rarely on top of the to-do list.
That's a nice, clean, simple approach - I learned about `createContextualFragment()`, so thanks!
I wanted to ask, did the company you were interviewing for tell you what they wanted to get out of the assignment on their end - specifically what they were assessing you on?
Thanks! I really appreciate that!
I think I can post the evaluation criteria:
1) App performance. We will be looking at the wait times for reader to see the content — the shorter, the better.
2) We will evaluate your code’s quality. Does your code have good modular design and testability? Is it easy to read?
3) We prefer the project to be lightweight, and all dependencies should be well justified.
I was focusing on #1 and #3. As for #2, they found it too tightly coupled and hard to read.
I thought that the app is simple enough to not warrant extracting modules in the main app logic. The coupling was also there for performance / filesize reasons.
Too tightly coupled? Fuck me. I'd have given them a single .js file. There's a point where decoupling everything is just a complete waste of time. Sounds like the company was run by idealistic developers who have never had to work under real-world deadlines.
Your comment makes me imagine a more nuanced technical interview process - i.e you get to provide feedback to criticisms from the interviewer, you get to escalate/request review from someone else at the employer if you disagree with the interviewer. A platform ensures that the protocols are abided by by both employer and candidate.
These sorts of interactions sound pretty far out now, but a few years ago who would have thought that people would be typing code into a web page in real time as part of a job interview process?
> Sadly, I didn't get a chance to provide feedback to the criticisms
That's a shame. It sounds like the criteria were fairly well defined, but it would be nice if your assignment was used as a starting point for good in person discussion. E.g. "we think the code in index.js was too coupled - what could we do to break that out?"
I distrust any interview that includes something like this.
It's an arbitrary construct that is not indicative of what form the work will take. Only the first three months of working with someone will give any real indication of what'll be like to work with them for another three+ years.
> It's an arbitrary construct that is not indicative of what form the work will take.
Agreed.
I had a similar code challenge and after joining the company, in the first year of work I did little if any JS work which even approached the level of the challenge I was presented with. To this day, I'm still bitter the company gave me the old "bait and switch" tactic to get me to come work there.
Yeah we created a test for our interview but we give it onsite I think requiring people to do work even if its compensated is wrong, its not that hard to put together a small exam based on the source for your projects to analyze whether a candidate can handle the work.
I have had this issue as well with take home projects. Most companies are looking for someone who will follow KISS, so demonstrating ability to do complex things like your render queue is not at all appreciated. They want to see that you can match a spec and write well-factored code.
Adding complexity for performance will be a pure negative unless you can factor that out so the next person can use it on their component.
I would read this code and think I was dealing with a very talented programmer that needs seasoning. Such a programmer can be very dangerous to the wrong company, as the seasoning will have to be added on the company’s dime.
Works here on Firefox Dev. Try refreshing, there was a bug I missed with the api returning 200 for a post, but the content was `null`. Fixed it, but you still might have the old cached JS due to the service workers.
They could also have been articles, probably also better for a11y.
The browser's implementation of numbering ol's is to align them to the right and render them hanging. They don't impact the layout, much like position: absolute, and they grow to the left.
The default ol/ul behaviour leaves some space to the left where the bullets/numbers should fit. This means you need to take into account the maximum width of the number.
I had no idea how much is the limit of the API, could have been thousands of items, and I didn't want to leave space for four digits until you scroll down to item #1234
I could also have implemented this using CSS `counter-increment` and `content`, but this was a better approach for debugging if the articles were rendering in the right order, while the CSS approach only takes into consideration the amount of DOM nodes.
You can see it in action here: https://hn-scroll.netlify.com/
The task was to build an offline capable site which displayed the latest Hacker News posts, and loaded more lazily when scrolling. I had to use the official HN API, and I couldn't have any middleware or caching. Everything had to be done client-side.
The app ended up being 1.4kb in total, with support for practically streaming in the items, batching them by network response times and render frames, while keeping the order.
You can see the batched items in this version: https://codesandbox.io/s/hardcore-stonebraker-8m8fx