diff options
Diffstat (limited to 'newsletter')
| -rw-r--r-- | newsletter/.editorconfig | 16 | ||||
| -rw-r--r-- | newsletter/.gitignore | 1 | ||||
| -rw-r--r-- | newsletter/campaigns/2020-52.json | 75 | ||||
| -rw-r--r-- | newsletter/campaigns/2020-53.json | 122 | ||||
| -rw-r--r-- | newsletter/campaigns/2021-01.json | 81 | ||||
| -rw-r--r-- | newsletter/campaigns/template.json | 15 | ||||
| -rw-r--r-- | newsletter/generated/2020-52.html | 88 | ||||
| -rw-r--r-- | newsletter/generated/2020-53.html | 326 | ||||
| -rw-r--r-- | newsletter/generated/2021-01.html | 198 | ||||
| -rw-r--r-- | newsletter/generated/index.html | 37 | ||||
| -rw-r--r-- | newsletter/package.json | 20 | ||||
| -rwxr-xr-x | newsletter/send | 129 | ||||
| -rw-r--r-- | newsletter/templates/index.hbs | 37 | ||||
| -rw-r--r-- | newsletter/templates/mailing.hbs | 42 |
14 files changed, 0 insertions, 1187 deletions
diff --git a/newsletter/.editorconfig b/newsletter/.editorconfig deleted file mode 100644 index 29a570e..0000000 --- a/newsletter/.editorconfig +++ /dev/null | |||
| @@ -1,16 +0,0 @@ | |||
| 1 | # EditorConfig is awesome: https://EditorConfig.org | ||
| 2 | |||
| 3 | # top-most EditorConfig file | ||
| 4 | root = true | ||
| 5 | |||
| 6 | [*] | ||
| 7 | indent_style = space | ||
| 8 | indent_size = 2 | ||
| 9 | end_of_line = lf | ||
| 10 | charset = utf-8 | ||
| 11 | trim_trailing_whitespace = true | ||
| 12 | insert_final_newline = true | ||
| 13 | |||
| 14 | [*.sh] | ||
| 15 | indent_style = tab | ||
| 16 | indent_size = 4 | ||
diff --git a/newsletter/.gitignore b/newsletter/.gitignore deleted file mode 100644 index d5a0f97..0000000 --- a/newsletter/.gitignore +++ /dev/null | |||
| @@ -1 +0,0 @@ | |||
| 1 | sendgrid.env | ||
diff --git a/newsletter/campaigns/2020-52.json b/newsletter/campaigns/2020-52.json deleted file mode 100644 index 5990b8d..0000000 --- a/newsletter/campaigns/2020-52.json +++ /dev/null | |||
| @@ -1,75 +0,0 @@ | |||
| 1 | { | ||
| 2 | "categories": [ | ||
| 3 | { | ||
| 4 | "name": "General", | ||
| 5 | "links": [ | ||
| 6 | { | ||
| 7 | "title": "3x3 SEO tips for JavaScript web apps", | ||
| 8 | "url": "https://www.youtube.com/watch?v=y1UzfahXfao&ab_channel=GoogleChromeDevelopers", | ||
| 9 | "excerpt": "Learn three basic SEO tips for Angular, React, and Vue.js web apps.", | ||
| 10 | "source": "Youtube" | ||
| 11 | }, | ||
| 12 | { | ||
| 13 | "title": "Machine Learning & Text Analysis", | ||
| 14 | "url": "https://www.youtube.com/watch?v=y1UzfahXfao&ab_channel=GoogleChromeDevelopers", | ||
| 15 | "excerpt": "Text analysis is the process of obtaining valuable insights from texts. ML can work with different types of textual information such as social media posts, messages, and emails. Special software helps to preprocess and analyze this data.", | ||
| 16 | "source": "Blog" | ||
| 17 | }, | ||
| 18 | { | ||
| 19 | "title": "Break a forEach Loop with JavaScript", | ||
| 20 | "url": "https://davidwalsh.name/javascript-array-tricks-3", | ||
| 21 | "excerpt": "He recently ran into another JavaScript trick that blew my mind: how to break a forEach loop, shared by Andrea Giammarchi!", | ||
| 22 | "source": "Blog" | ||
| 23 | }, | ||
| 24 | { | ||
| 25 | "title": "Flappy Bird in JavaScript with 25 Lines of Code", | ||
| 26 | "url": "https://www.youtube.com/watch?v=M45iFPVdtj0&ab_channel=CodingTech", | ||
| 27 | "excerpt": "In this tutorial he takes you on the callenge to code a flappy bird clone in a few lines of code as possible.The starting point is an empty HTML canvas and you can follow along all the way to a complete game.", | ||
| 28 | "source": "Youtube" | ||
| 29 | }, | ||
| 30 | { | ||
| 31 | "title": "What's new in DevTools", | ||
| 32 | "url": "https://www.youtube.com/watch?v=QsOF9SJJdAA&ab_channel=GoogleChromeDevelopers", | ||
| 33 | "excerpt": "An overview of the latest and greatest features in Chrome DevTools.", | ||
| 34 | "source": "Youtube" | ||
| 35 | }, | ||
| 36 | { | ||
| 37 | "title": "Canvas2D is getting an update", | ||
| 38 | "url": "https://www.youtube.com/watch?v=dfOKFSDG7IM&ab_channel=GoogleChromeDevelopers", | ||
| 39 | "excerpt": "Your good, old friend the Canvas2D API has been improving and is worth another look. Hear about all the new features that have been added to the spec.", | ||
| 40 | "source": "Youtube" | ||
| 41 | }, | ||
| 42 | { | ||
| 43 | "title": "A web framework for building 3D/AR/VR experiences", | ||
| 44 | "url": "https://aframe.io/", | ||
| 45 | "excerpt": "Make 3D worlds with HTML and Entity-Component For Quest, Rift, WMR, SteamVR, mobile, desktop.", | ||
| 46 | "source": "Product" | ||
| 47 | }, | ||
| 48 | { | ||
| 49 | "title": "Introduction to Erlang", | ||
| 50 | "url": "https://serokell.io/blog/introduction-to-erlang", | ||
| 51 | "excerpt": "While Erlang is not as popular as some modern programming languages, it quietly runs applications like WhatsApp and WeChat that serve massive amounts of users every day.", | ||
| 52 | "source": "Blog" | ||
| 53 | }, | ||
| 54 | { | ||
| 55 | "title": "Why is processing a sorted array faster than processing an unsorted array?", | ||
| 56 | "url": "https://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster-than-processing-an-unsorted-array", | ||
| 57 | "excerpt": "Here is a piece of C++ code that shows some very peculiar behavior. For some strange reason, sorting the data miraculously makes the code almost six times faster.", | ||
| 58 | "source": "Nugget" | ||
| 59 | }, | ||
| 60 | { | ||
| 61 | "title": "30-Second Maths: The 50 Most Mind-Expanding Theories in Mathematics, Each Explained in Half a Minute", | ||
| 62 | "url": "https://www.bookdepository.com/30-Second-Maths-Richard-J-Brown/9781785782886?ref=pd_gw_1_pd_gateway_1_1", | ||
| 63 | "excerpt": "30 Second Maths takes the top 50 most engaging mathematical theories, and explains them to the general reader in half a minute, using nothing more than two pages, 200 words and one picture. Read at your own pace, and discover that maths can be more fascinating than you ever imagined.", | ||
| 64 | "source": "Book" | ||
| 65 | }, | ||
| 66 | { | ||
| 67 | "title": "Pomodoro Technique", | ||
| 68 | "url": "https://en.wikipedia.org/wiki/Pomodoro_Technique", | ||
| 69 | "excerpt": "The Pomodoro Technique is a time management method developed by Francesco Cirillo in the late 1980s.", | ||
| 70 | "source": "Nugget" | ||
| 71 | } | ||
| 72 | ] | ||
| 73 | } | ||
| 74 | ] | ||
| 75 | } | ||
diff --git a/newsletter/campaigns/2020-53.json b/newsletter/campaigns/2020-53.json deleted file mode 100644 index de44449..0000000 --- a/newsletter/campaigns/2020-53.json +++ /dev/null | |||
| @@ -1,122 +0,0 @@ | |||
| 1 | { | ||
| 2 | "categories": [ | ||
| 3 | { | ||
| 4 | "name": "General", | ||
| 5 | "links": [ | ||
| 6 | { | ||
| 7 | "title": "Transitioning to modern JavaScript", | ||
| 8 | "excerpt": "Over 90% of web traffic comes from browsers that support modern JavaScript, yet most websites ship legacy syntax in order to support a small number of very old browsers.", | ||
| 9 | "url": "https://youtu.be/cLxNdLK--yI", | ||
| 10 | "tags": [ | ||
| 11 | "Video", | ||
| 12 | "JavaScript" | ||
| 13 | ] | ||
| 14 | }, | ||
| 15 | { | ||
| 16 | "title": "Sign-up form best practices", | ||
| 17 | "excerpt": "Help your users sign up, sign in, and manage their account details with a minimum of fuss.", | ||
| 18 | "url": "https://youtu.be/Ev2mCzJZLtY", | ||
| 19 | "tags": [ | ||
| 20 | "Video", | ||
| 21 | "Accessibility" | ||
| 22 | ] | ||
| 23 | }, | ||
| 24 | { | ||
| 25 | "title": "AutoKeras", | ||
| 26 | "excerpt": "AutoKeras: An AutoML system based on Keras. It is developed by DATA Lab at Texas A&M University. The goal of AutoKeras is to make machine learning accessible for everyone.", | ||
| 27 | "url": "https://autokeras.com/", | ||
| 28 | "tags": [ | ||
| 29 | "Product", | ||
| 30 | "Machine learning" | ||
| 31 | ] | ||
| 32 | }, | ||
| 33 | { | ||
| 34 | "title": "Arduino Weather Station", | ||
| 35 | "excerpt": "This Is An Project To Help View Us The Current Temperature And Humidity In Time.", | ||
| 36 | "url": "https://www.hackster.io/m1cr0s0ft/arduino-weather-station-8ec09e", | ||
| 37 | "tags": [ | ||
| 38 | "Blog", | ||
| 39 | "Hardware", | ||
| 40 | "Arduino" | ||
| 41 | ] | ||
| 42 | }, | ||
| 43 | { | ||
| 44 | "title": "Beyond fast with new performance features", | ||
| 45 | "excerpt": "A whirlwind tour of new features and proposals to improve the performance of your pages.", | ||
| 46 | "url": "https://youtu.be/Z6wjUOSh9Tk", | ||
| 47 | "tags": [ | ||
| 48 | "Video", | ||
| 49 | "Web optimization" | ||
| 50 | ] | ||
| 51 | }, | ||
| 52 | { | ||
| 53 | "title": "How digital identity protects your software", | ||
| 54 | "excerpt": "Digital identity is the online representation of a person, organization, or a machine, and it is what gives us access to the data we use daily. Here’s a brief overview of identity, why it's vital to information security, and why you should know more about it.", | ||
| 55 | "url": "https://stackoverflow.blog/2020/12/21/how-digital-identity-protects-your-software/", | ||
| 56 | "tags": [ | ||
| 57 | "Blog", | ||
| 58 | "Single sign on", | ||
| 59 | "Social login" | ||
| 60 | ] | ||
| 61 | }, | ||
| 62 | { | ||
| 63 | "title": "Podcast 295: Diving into headless automation, active monitoring, Playwright and Puppeteer", | ||
| 64 | "excerpt": "This week we chat with Tim Nolet, whose commentary appeared in a previous episode after he complained about Amazon forking his OS service and presenting it as new product without so much as a thanks. Since then the two parties have worked things out, and Tim came on the show to explain what happened, what he builds in the open source world, and the company he runs.", | ||
| 65 | "url": "https://stackoverflow.blog/2020/12/15/podcast-295-diving-into-headless-automation-active-monitoring-playwright-and-puppeteer/", | ||
| 66 | "tags": [ | ||
| 67 | "Podcast", | ||
| 68 | "Automation", | ||
| 69 | "DevOps" | ||
| 70 | ] | ||
| 71 | }, | ||
| 72 | { | ||
| 73 | "title": "2020 Web Design Year in Review", | ||
| 74 | "excerpt": "A year “like no other” is about to come to a close. 2020 was certainly unique for everyone – web designers included. And it challenged us on several levels.", | ||
| 75 | "url": "https://speckyboy.com/2020-web-design-year-in-review/", | ||
| 76 | "tags": [ | ||
| 77 | "Blog", | ||
| 78 | "Looking back" | ||
| 79 | ] | ||
| 80 | }, | ||
| 81 | { | ||
| 82 | "title": "The 15 Commandments of Front-End Performance", | ||
| 83 | "excerpt": "This list is the product of many years of experience in the front-end web development field. I maintain this list as a reminder to myself to always follow best practices, and to not compromise on performance, even if I’m in a time crunch.", | ||
| 84 | "url": "https://alexsexton.com/blog/2015/02/the-15-commandments-of-front-end-performance/", | ||
| 85 | "tags": [ | ||
| 86 | "Blog", | ||
| 87 | "Front-end", | ||
| 88 | "Best practices" | ||
| 89 | ] | ||
| 90 | }, | ||
| 91 | { | ||
| 92 | "title": "Finding Critical Open Source Projects", | ||
| 93 | "excerpt": "Criticality of an open source project is difficult to define; what might be a critical dependency for one consumer of open source software may be entirely absent for another. However, arriving at a shared understanding and framework allows us to have productive conversations about our dependencies. Simply put, we define criticality to be the influence and importance of a project.", | ||
| 94 | "url": "https://opensource.googleblog.com/2020/12/finding-critical-open-source-projects.html", | ||
| 95 | "tags": [ | ||
| 96 | "Blog", | ||
| 97 | "Open source" | ||
| 98 | ] | ||
| 99 | }, | ||
| 100 | { | ||
| 101 | "title": "HTTP Archive's 10th Anniversary", | ||
| 102 | "excerpt": "Rick meets with Steve Souders, who created the HTTP Archive project 10 years ago this month, to talk about its origins and reflect on it's growth.", | ||
| 103 | "url": "https://www.stitcher.com/show/the-state-of-the-web/episode/http-archives-10th-anniversary-79556890", | ||
| 104 | "tags": [ | ||
| 105 | "Podcast", | ||
| 106 | "Performance" | ||
| 107 | ] | ||
| 108 | }, | ||
| 109 | { | ||
| 110 | "title": "Cosmic Queries – Medieval Science and History", | ||
| 111 | "excerpt": "When you think Middle Ages, does scientific advancement pop into your head? On this episode of StarTalk Radio, we’re exploring the science and history of medieval times as Neil deGrasse Tyson and comic co-host Matt Kirshen answer fan-submitted Cosmic Queries with Seb Falk, Cambridge Historian of Science and author of The Light Ages: The Surprising Story of Medieval Science.", | ||
| 112 | "url": "https://www.startalkradio.net/show/cosmic-queries-medieval-science-and-history/", | ||
| 113 | "tags": [ | ||
| 114 | "Podcast", | ||
| 115 | "Science", | ||
| 116 | "History" | ||
| 117 | ] | ||
| 118 | } | ||
| 119 | ] | ||
| 120 | } | ||
| 121 | ] | ||
| 122 | } | ||
diff --git a/newsletter/campaigns/2021-01.json b/newsletter/campaigns/2021-01.json deleted file mode 100644 index d3756c9..0000000 --- a/newsletter/campaigns/2021-01.json +++ /dev/null | |||
| @@ -1,81 +0,0 @@ | |||
| 1 | { | ||
| 2 | "categories": [ | ||
| 3 | { | ||
| 4 | "name": "General", | ||
| 5 | "links": [ | ||
| 6 | { | ||
| 7 | "title": "Fast Inverse Square Root — A Quake III Algorithm", | ||
| 8 | "excerpt": "In this video we will take an in depth look at the fast inverse square root and see where the mysterious number 0x5f3759df comes from. This algorithm became famous after id Software open sourced the engine for Quake III. On the way we will also learn about floating point numbers and newton's method.", | ||
| 9 | "url": "https://www.youtube.com/watch?v=p8u_k2LIZyo", | ||
| 10 | "tags": [ | ||
| 11 | "Video", | ||
| 12 | "Quake III" | ||
| 13 | ] | ||
| 14 | }, | ||
| 15 | { | ||
| 16 | "title": "Goodbye, Adobe Flash", | ||
| 17 | "excerpt": "A thrice-weekly news show about tech + gaming culture.", | ||
| 18 | "url": "https://www.youtube.com/watch?v=zV2VEOHNCJU", | ||
| 19 | "tags": [ | ||
| 20 | "Video", | ||
| 21 | "Tech news" | ||
| 22 | ] | ||
| 23 | }, | ||
| 24 | { | ||
| 25 | "title": "The Year's Biggest Breakthroughs in Math and Computer Science", | ||
| 26 | "excerpt": "For mathematicians and computer scientists, 2020 was full of discipline-spanning discoveries and celebrations of creativity. We'd like to take a moment to recognize some of these achievements.", | ||
| 27 | "url": "https://www.youtube.com/watch?v=HL7DEkXV_60", | ||
| 28 | "tags": [ | ||
| 29 | "Video", | ||
| 30 | "Math and Computer Science" | ||
| 31 | ] | ||
| 32 | }, | ||
| 33 | { | ||
| 34 | "title": "20 Award-Winning 13-Kilobyte JavaScript Games You Can Play in Your Browser", | ||
| 35 | "excerpt": "In this article, I am going to show you 20 award-winning JavaScript games from the JS13kGames competition. So in other words, you're going to see 20 great examples of code from 20 insanely talented developers.", | ||
| 36 | "url": "https://www.freecodecamp.org/news/20-award-winning-games-explained-code-breakdown/", | ||
| 37 | "tags": [ | ||
| 38 | "Blog", | ||
| 39 | "Games" | ||
| 40 | ] | ||
| 41 | }, | ||
| 42 | { | ||
| 43 | "title": "Espressif's New ESP32-S3 Adds AI Features for IoT Devices", | ||
| 44 | "excerpt": "The very last day of 2020 came with great news for ESP32 fans. The ubiquitous IoT microcontroller is getting a new family member — the ESP32-S3! Espressif's latest introduction includes an updated dual-core MCU, expanded GPIO, AI-focused instructions, and hardware-accelerated security features.", | ||
| 45 | "url": "https://www.hackster.io/news/espressif-s-new-esp32-s3-adds-ai-features-for-iot-devices-b42b902abdf5", | ||
| 46 | "tags": [ | ||
| 47 | "Product", | ||
| 48 | "IoT" | ||
| 49 | ] | ||
| 50 | }, | ||
| 51 | { | ||
| 52 | "title": "Radioactive materials were once sold in a STORE in the USSR!", | ||
| 53 | "excerpt": "‘Izotopy’ was the name of a specialist store in Moscow that sold radioactive materials. And demand for them was very high. But how was such a thing possible?", | ||
| 54 | "url": "https://www.rbth.com/history/333230-radioactive-materials-sold-ussr", | ||
| 55 | "tags": [ | ||
| 56 | "Blog", | ||
| 57 | "Russia" | ||
| 58 | ] | ||
| 59 | }, | ||
| 60 | { | ||
| 61 | "title": "Welcome to 2021 with Joel Spolsky", | ||
| 62 | "excerpt": "We are stepping into a new year with a very special guest, Stack Overflow's co-founder and chairman, Joel Spolsky. We chat programming, social networks, and what comes next.", | ||
| 63 | "url": "https://stackoverflow.blog/2021/01/01/podcast-300-welcome-to-2021-with-joel-spolsky/", | ||
| 64 | "tags": [ | ||
| 65 | "Podcast", | ||
| 66 | "Stack Overflow" | ||
| 67 | ] | ||
| 68 | }, | ||
| 69 | { | ||
| 70 | "title": "The AI companion who cares", | ||
| 71 | "excerpt": "Replika is a #1 chatbot companion powered by artificial intelligence.", | ||
| 72 | "url": "https://replika.ai/", | ||
| 73 | "tags": [ | ||
| 74 | "Product", | ||
| 75 | "AI Chatbot" | ||
| 76 | ] | ||
| 77 | } | ||
| 78 | ] | ||
| 79 | } | ||
| 80 | ] | ||
| 81 | } | ||
diff --git a/newsletter/campaigns/template.json b/newsletter/campaigns/template.json deleted file mode 100644 index 56b33c9..0000000 --- a/newsletter/campaigns/template.json +++ /dev/null | |||
| @@ -1,15 +0,0 @@ | |||
| 1 | { | ||
| 2 | "categories": [ | ||
| 3 | { | ||
| 4 | "name": "General", | ||
| 5 | "links": [ | ||
| 6 | { | ||
| 7 | "title": "", | ||
| 8 | "url": "", | ||
| 9 | "excerpt": "", | ||
| 10 | "source": "" | ||
| 11 | } | ||
| 12 | ] | ||
| 13 | } | ||
| 14 | ] | ||
| 15 | } | ||
diff --git a/newsletter/generated/2020-52.html b/newsletter/generated/2020-52.html deleted file mode 100644 index 73f79da..0000000 --- a/newsletter/generated/2020-52.html +++ /dev/null | |||
| @@ -1,88 +0,0 @@ | |||
| 1 | <html> | ||
| 2 | |||
| 3 | <head> | ||
| 4 | <title>2020: Week #52 Links</title> | ||
| 5 | </head> | ||
| 6 | |||
| 7 | <body style="background: #f2f2f2; padding: 60px; color: #222222; line-height: 22px; font-family: sans-serif, system-ui, -apple-system; font-size: 16px;"> | ||
| 8 | |||
| 9 | <div style="width: 650px; background: #ffffff; text-align: left; padding: 40px; margin: 0 auto; border-radius: 10px;"> | ||
| 10 | |||
| 11 | <div style="margin-bottom: 30px;"> | ||
| 12 | <a href="https://www.youtube.com/watch?v=y1UzfahXfao&ab_channel=GoogleChromeDevelopers" style="color: #3252a8; font-weight: bold;">3x3 SEO tips for JavaScript web apps</a> | ||
| 13 | <div style="margin-block-start: 5px; font-size: 90%;">Learn three basic SEO tips for Angular, React, and Vue.js web apps.</div> | ||
| 14 | <div> | ||
| 15 | </div> | ||
| 16 | </div> | ||
| 17 | <div style="margin-bottom: 30px;"> | ||
| 18 | <a href="https://www.youtube.com/watch?v=y1UzfahXfao&ab_channel=GoogleChromeDevelopers" style="color: #3252a8; font-weight: bold;">Machine Learning & Text Analysis</a> | ||
| 19 | <div style="margin-block-start: 5px; font-size: 90%;">Text analysis is the process of obtaining valuable insights from texts. ML can work with different types of textual information such as social media posts, messages, and emails. Special software helps to preprocess and analyze this data.</div> | ||
| 20 | <div> | ||
| 21 | </div> | ||
| 22 | </div> | ||
| 23 | <div style="margin-bottom: 30px;"> | ||
| 24 | <a href="https://davidwalsh.name/javascript-array-tricks-3" style="color: #3252a8; font-weight: bold;">Break a forEach Loop with JavaScript</a> | ||
| 25 | <div style="margin-block-start: 5px; font-size: 90%;">He recently ran into another JavaScript trick that blew my mind: how to break a forEach loop, shared by Andrea Giammarchi!</div> | ||
| 26 | <div> | ||
| 27 | </div> | ||
| 28 | </div> | ||
| 29 | <div style="margin-bottom: 30px;"> | ||
| 30 | <a href="https://www.youtube.com/watch?v=M45iFPVdtj0&ab_channel=CodingTech" style="color: #3252a8; font-weight: bold;">Flappy Bird in JavaScript with 25 Lines of Code</a> | ||
| 31 | <div style="margin-block-start: 5px; font-size: 90%;">In this tutorial he takes you on the callenge to code a flappy bird clone in a few lines of code as possible.The starting point is an empty HTML canvas and you can follow along all the way to a complete game.</div> | ||
| 32 | <div> | ||
| 33 | </div> | ||
| 34 | </div> | ||
| 35 | <div style="margin-bottom: 30px;"> | ||
| 36 | <a href="https://www.youtube.com/watch?v=QsOF9SJJdAA&ab_channel=GoogleChromeDevelopers" style="color: #3252a8; font-weight: bold;">What's new in DevTools</a> | ||
| 37 | <div style="margin-block-start: 5px; font-size: 90%;">An overview of the latest and greatest features in Chrome DevTools.</div> | ||
| 38 | <div> | ||
| 39 | </div> | ||
| 40 | </div> | ||
| 41 | <div style="margin-bottom: 30px;"> | ||
| 42 | <a href="https://www.youtube.com/watch?v=dfOKFSDG7IM&ab_channel=GoogleChromeDevelopers" style="color: #3252a8; font-weight: bold;">Canvas2D is getting an update</a> | ||
| 43 | <div style="margin-block-start: 5px; font-size: 90%;">Your good, old friend the Canvas2D API has been improving and is worth another look. Hear about all the new features that have been added to the spec.</div> | ||
| 44 | <div> | ||
| 45 | </div> | ||
| 46 | </div> | ||
| 47 | <div style="margin-bottom: 30px;"> | ||
| 48 | <a href="https://aframe.io/" style="color: #3252a8; font-weight: bold;">A web framework for building 3D/AR/VR experiences</a> | ||
| 49 | <div style="margin-block-start: 5px; font-size: 90%;">Make 3D worlds with HTML and Entity-Component For Quest, Rift, WMR, SteamVR, mobile, desktop.</div> | ||
| 50 | <div> | ||
| 51 | </div> | ||
| 52 | </div> | ||
| 53 | <div style="margin-bottom: 30px;"> | ||
| 54 | <a href="https://serokell.io/blog/introduction-to-erlang" style="color: #3252a8; font-weight: bold;">Introduction to Erlang</a> | ||
| 55 | <div style="margin-block-start: 5px; font-size: 90%;">While Erlang is not as popular as some modern programming languages, it quietly runs applications like WhatsApp and WeChat that serve massive amounts of users every day.</div> | ||
| 56 | <div> | ||
| 57 | </div> | ||
| 58 | </div> | ||
| 59 | <div style="margin-bottom: 30px;"> | ||
| 60 | <a href="https://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster-than-processing-an-unsorted-array" style="color: #3252a8; font-weight: bold;">Why is processing a sorted array faster than processing an unsorted array?</a> | ||
| 61 | <div style="margin-block-start: 5px; font-size: 90%;">Here is a piece of C++ code that shows some very peculiar behavior. For some strange reason, sorting the data miraculously makes the code almost six times faster.</div> | ||
| 62 | <div> | ||
| 63 | </div> | ||
| 64 | </div> | ||
| 65 | <div style="margin-bottom: 30px;"> | ||
| 66 | <a href="https://www.bookdepository.com/30-Second-Maths-Richard-J-Brown/9781785782886?ref=pd_gw_1_pd_gateway_1_1" style="color: #3252a8; font-weight: bold;">30-Second Maths: The 50 Most Mind-Expanding Theories in Mathematics, Each Explained in Half a Minute</a> | ||
| 67 | <div style="margin-block-start: 5px; font-size: 90%;">30 Second Maths takes the top 50 most engaging mathematical theories, and explains them to the general reader in half a minute, using nothing more than two pages, 200 words and one picture. Read at your own pace, and discover that maths can be more fascinating than you ever imagined.</div> | ||
| 68 | <div> | ||
| 69 | </div> | ||
| 70 | </div> | ||
| 71 | <div style="margin-bottom: 30px;"> | ||
| 72 | <a href="https://en.wikipedia.org/wiki/Pomodoro_Technique" style="color: #3252a8; font-weight: bold;">Pomodoro Technique</a> | ||
| 73 | <div style="margin-block-start: 5px; font-size: 90%;">The Pomodoro Technique is a time management method developed by Francesco Cirillo in the late 1980s.</div> | ||
| 74 | <div> | ||
| 75 | </div> | ||
| 76 | </div> | ||
| 77 | |||
| 78 | </div> | ||
| 79 | |||
| 80 | <div style="text-align: center; font-size: 80%; margin-top: 20px;"> | ||
| 81 | <a style="color: #666; margin: auto 10px" href="https://mitjafelicijan.com/weekly-newsletter-archive/">weekly links archive</a> | ||
| 82 | <a style="color: #666; margin: auto 10px" href="https://mitjafelicijan.com">mitjafelicijan.com</a> | ||
| 83 | <a style="color: #666; margin: auto 10px" href="https://github.com/mitjafelicijan">github.com/mitjafelicijan</a> | ||
| 84 | </div> | ||
| 85 | |||
| 86 | </body> | ||
| 87 | |||
| 88 | </html> | ||
diff --git a/newsletter/generated/2020-53.html b/newsletter/generated/2020-53.html deleted file mode 100644 index 60c6cef..0000000 --- a/newsletter/generated/2020-53.html +++ /dev/null | |||
| @@ -1,326 +0,0 @@ | |||
| 1 | <html> | ||
| 2 | |||
| 3 | <head> | ||
| 4 | <title>2020: Week #53 Links</title> | ||
| 5 | </head> | ||
| 6 | |||
| 7 | <body style="background: #f2f2f2; padding: 60px; color: #222222; line-height: 22px; font-family: sans-serif, system-ui, -apple-system; font-size: 16px;"> | ||
| 8 | |||
| 9 | <div style="width: 650px; background: #ffffff; text-align: left; padding: 40px; margin: 0 auto; border-radius: 10px;"> | ||
| 10 | |||
| 11 | <div style="margin-bottom: 30px;"> | ||
| 12 | <a href="https://youtu.be/cLxNdLK--yI" style="color: #3252a8; font-weight: bold;">Transitioning to modern JavaScript</a> | ||
| 13 | <div style="margin-block-start: 5px; font-size: 90%;">Over 90% of web traffic comes from browsers that support modern JavaScript, yet most websites ship legacy syntax in order to support a small number of very old browsers.</div> | ||
| 14 | <div> | ||
| 15 | <span style="background: #e6e6e6; | ||
| 16 | color: #777; | ||
| 17 | border-radius: 3px; | ||
| 18 | padding: 0px 10px; | ||
| 19 | font-size: 70%; | ||
| 20 | display: inline-block; | ||
| 21 | margin-top: 5px; | ||
| 22 | font-weight: 600;">Video</span> | ||
| 23 | <span style="background: #e6e6e6; | ||
| 24 | color: #777; | ||
| 25 | border-radius: 3px; | ||
| 26 | padding: 0px 10px; | ||
| 27 | font-size: 70%; | ||
| 28 | display: inline-block; | ||
| 29 | margin-top: 5px; | ||
| 30 | font-weight: 600;">JavaScript</span> | ||
| 31 | </div> | ||
| 32 | </div> | ||
| 33 | <div style="margin-bottom: 30px;"> | ||
| 34 | <a href="https://youtu.be/Ev2mCzJZLtY" style="color: #3252a8; font-weight: bold;">Sign-up form best practices</a> | ||
| 35 | <div style="margin-block-start: 5px; font-size: 90%;">Help your users sign up, sign in, and manage their account details with a minimum of fuss.</div> | ||
| 36 | <div> | ||
| 37 | <span style="background: #e6e6e6; | ||
| 38 | color: #777; | ||
| 39 | border-radius: 3px; | ||
| 40 | padding: 0px 10px; | ||
| 41 | font-size: 70%; | ||
| 42 | display: inline-block; | ||
| 43 | margin-top: 5px; | ||
| 44 | font-weight: 600;">Video</span> | ||
| 45 | <span style="background: #e6e6e6; | ||
| 46 | color: #777; | ||
| 47 | border-radius: 3px; | ||
| 48 | padding: 0px 10px; | ||
| 49 | font-size: 70%; | ||
| 50 | display: inline-block; | ||
| 51 | margin-top: 5px; | ||
| 52 | font-weight: 600;">Accessibility</span> | ||
| 53 | </div> | ||
| 54 | </div> | ||
| 55 | <div style="margin-bottom: 30px;"> | ||
| 56 | <a href="https://autokeras.com/" style="color: #3252a8; font-weight: bold;">AutoKeras</a> | ||
| 57 | <div style="margin-block-start: 5px; font-size: 90%;">AutoKeras: An AutoML system based on Keras. It is developed by DATA Lab at Texas A&M University. The goal of AutoKeras is to make machine learning accessible for everyone.</div> | ||
| 58 | <div> | ||
| 59 | <span style="background: #e6e6e6; | ||
| 60 | color: #777; | ||
| 61 | border-radius: 3px; | ||
| 62 | padding: 0px 10px; | ||
| 63 | font-size: 70%; | ||
| 64 | display: inline-block; | ||
| 65 | margin-top: 5px; | ||
| 66 | font-weight: 600;">Product</span> | ||
| 67 | <span style="background: #e6e6e6; | ||
| 68 | color: #777; | ||
| 69 | border-radius: 3px; | ||
| 70 | padding: 0px 10px; | ||
| 71 | font-size: 70%; | ||
| 72 | display: inline-block; | ||
| 73 | margin-top: 5px; | ||
| 74 | font-weight: 600;">Machine learning</span> | ||
| 75 | </div> | ||
| 76 | </div> | ||
| 77 | <div style="margin-bottom: 30px;"> | ||
| 78 | <a href="https://www.hackster.io/m1cr0s0ft/arduino-weather-station-8ec09e" style="color: #3252a8; font-weight: bold;">Arduino Weather Station</a> | ||
| 79 | <div style="margin-block-start: 5px; font-size: 90%;">This Is An Project To Help View Us The Current Temperature And Humidity In Time.</div> | ||
| 80 | <div> | ||
| 81 | <span style="background: #e6e6e6; | ||
| 82 | color: #777; | ||
| 83 | border-radius: 3px; | ||
| 84 | padding: 0px 10px; | ||
| 85 | font-size: 70%; | ||
| 86 | display: inline-block; | ||
| 87 | margin-top: 5px; | ||
| 88 | font-weight: 600;">Blog</span> | ||
| 89 | <span style="background: #e6e6e6; | ||
| 90 | color: #777; | ||
| 91 | border-radius: 3px; | ||
| 92 | padding: 0px 10px; | ||
| 93 | font-size: 70%; | ||
| 94 | display: inline-block; | ||
| 95 | margin-top: 5px; | ||
| 96 | font-weight: 600;">Hardware</span> | ||
| 97 | <span style="background: #e6e6e6; | ||
| 98 | color: #777; | ||
| 99 | border-radius: 3px; | ||
| 100 | padding: 0px 10px; | ||
| 101 | font-size: 70%; | ||
| 102 | display: inline-block; | ||
| 103 | margin-top: 5px; | ||
| 104 | font-weight: 600;">Arduino</span> | ||
| 105 | </div> | ||
| 106 | </div> | ||
| 107 | <div style="margin-bottom: 30px;"> | ||
| 108 | <a href="https://youtu.be/Z6wjUOSh9Tk" style="color: #3252a8; font-weight: bold;">Beyond fast with new performance features</a> | ||
| 109 | <div style="margin-block-start: 5px; font-size: 90%;">A whirlwind tour of new features and proposals to improve the performance of your pages.</div> | ||
| 110 | <div> | ||
| 111 | <span style="background: #e6e6e6; | ||
| 112 | color: #777; | ||
| 113 | border-radius: 3px; | ||
| 114 | padding: 0px 10px; | ||
| 115 | font-size: 70%; | ||
| 116 | display: inline-block; | ||
| 117 | margin-top: 5px; | ||
| 118 | font-weight: 600;">Video</span> | ||
| 119 | <span style="background: #e6e6e6; | ||
| 120 | color: #777; | ||
| 121 | border-radius: 3px; | ||
| 122 | padding: 0px 10px; | ||
| 123 | font-size: 70%; | ||
| 124 | display: inline-block; | ||
| 125 | margin-top: 5px; | ||
| 126 | font-weight: 600;">Web optimization</span> | ||
| 127 | </div> | ||
| 128 | </div> | ||
| 129 | <div style="margin-bottom: 30px;"> | ||
| 130 | <a href="https://stackoverflow.blog/2020/12/21/how-digital-identity-protects-your-software/" style="color: #3252a8; font-weight: bold;">How digital identity protects your software</a> | ||
| 131 | <div style="margin-block-start: 5px; font-size: 90%;">Digital identity is the online representation of a person, organization, or a machine, and it is what gives us access to the data we use daily. Here’s a brief overview of identity, why it's vital to information security, and why you should know more about it.</div> | ||
| 132 | <div> | ||
| 133 | <span style="background: #e6e6e6; | ||
| 134 | color: #777; | ||
| 135 | border-radius: 3px; | ||
| 136 | padding: 0px 10px; | ||
| 137 | font-size: 70%; | ||
| 138 | display: inline-block; | ||
| 139 | margin-top: 5px; | ||
| 140 | font-weight: 600;">Blog</span> | ||
| 141 | <span style="background: #e6e6e6; | ||
| 142 | color: #777; | ||
| 143 | border-radius: 3px; | ||
| 144 | padding: 0px 10px; | ||
| 145 | font-size: 70%; | ||
| 146 | display: inline-block; | ||
| 147 | margin-top: 5px; | ||
| 148 | font-weight: 600;">Single sign on</span> | ||
| 149 | <span style="background: #e6e6e6; | ||
| 150 | color: #777; | ||
| 151 | border-radius: 3px; | ||
| 152 | padding: 0px 10px; | ||
| 153 | font-size: 70%; | ||
| 154 | display: inline-block; | ||
| 155 | margin-top: 5px; | ||
| 156 | font-weight: 600;">Social login</span> | ||
| 157 | </div> | ||
| 158 | </div> | ||
| 159 | <div style="margin-bottom: 30px;"> | ||
| 160 | <a href="https://stackoverflow.blog/2020/12/15/podcast-295-diving-into-headless-automation-active-monitoring-playwright-and-puppeteer/" style="color: #3252a8; font-weight: bold;">Podcast 295: Diving into headless automation, active monitoring, Playwright and Puppeteer</a> | ||
| 161 | <div style="margin-block-start: 5px; font-size: 90%;">This week we chat with Tim Nolet, whose commentary appeared in a previous episode after he complained about Amazon forking his OS service and presenting it as new product without so much as a thanks. Since then the two parties have worked things out, and Tim came on the show to explain what happened, what he builds in the open source world, and the company he runs.</div> | ||
| 162 | <div> | ||
| 163 | <span style="background: #e6e6e6; | ||
| 164 | color: #777; | ||
| 165 | border-radius: 3px; | ||
| 166 | padding: 0px 10px; | ||
| 167 | font-size: 70%; | ||
| 168 | display: inline-block; | ||
| 169 | margin-top: 5px; | ||
| 170 | font-weight: 600;">Podcast</span> | ||
| 171 | <span style="background: #e6e6e6; | ||
| 172 | color: #777; | ||
| 173 | border-radius: 3px; | ||
| 174 | padding: 0px 10px; | ||
| 175 | font-size: 70%; | ||
| 176 | display: inline-block; | ||
| 177 | margin-top: 5px; | ||
| 178 | font-weight: 600;">Automation</span> | ||
| 179 | <span style="background: #e6e6e6; | ||
| 180 | color: #777; | ||
| 181 | border-radius: 3px; | ||
| 182 | padding: 0px 10px; | ||
| 183 | font-size: 70%; | ||
| 184 | display: inline-block; | ||
| 185 | margin-top: 5px; | ||
| 186 | font-weight: 600;">DevOps</span> | ||
| 187 | </div> | ||
| 188 | </div> | ||
| 189 | <div style="margin-bottom: 30px;"> | ||
| 190 | <a href="https://speckyboy.com/2020-web-design-year-in-review/" style="color: #3252a8; font-weight: bold;">2020 Web Design Year in Review</a> | ||
| 191 | <div style="margin-block-start: 5px; font-size: 90%;">A year “like no other” is about to come to a close. 2020 was certainly unique for everyone – web designers included. And it challenged us on several levels.</div> | ||
| 192 | <div> | ||
| 193 | <span style="background: #e6e6e6; | ||
| 194 | color: #777; | ||
| 195 | border-radius: 3px; | ||
| 196 | padding: 0px 10px; | ||
| 197 | font-size: 70%; | ||
| 198 | display: inline-block; | ||
| 199 | margin-top: 5px; | ||
| 200 | font-weight: 600;">Blog</span> | ||
| 201 | <span style="background: #e6e6e6; | ||
| 202 | color: #777; | ||
| 203 | border-radius: 3px; | ||
| 204 | padding: 0px 10px; | ||
| 205 | font-size: 70%; | ||
| 206 | display: inline-block; | ||
| 207 | margin-top: 5px; | ||
| 208 | font-weight: 600;">Looking back</span> | ||
| 209 | </div> | ||
| 210 | </div> | ||
| 211 | <div style="margin-bottom: 30px;"> | ||
| 212 | <a href="https://alexsexton.com/blog/2015/02/the-15-commandments-of-front-end-performance/" style="color: #3252a8; font-weight: bold;">The 15 Commandments of Front-End Performance</a> | ||
| 213 | <div style="margin-block-start: 5px; font-size: 90%;">This list is the product of many years of experience in the front-end web development field. I maintain this list as a reminder to myself to always follow best practices, and to not compromise on performance, even if I’m in a time crunch.</div> | ||
| 214 | <div> | ||
| 215 | <span style="background: #e6e6e6; | ||
| 216 | color: #777; | ||
| 217 | border-radius: 3px; | ||
| 218 | padding: 0px 10px; | ||
| 219 | font-size: 70%; | ||
| 220 | display: inline-block; | ||
| 221 | margin-top: 5px; | ||
| 222 | font-weight: 600;">Blog</span> | ||
| 223 | <span style="background: #e6e6e6; | ||
| 224 | color: #777; | ||
| 225 | border-radius: 3px; | ||
| 226 | padding: 0px 10px; | ||
| 227 | font-size: 70%; | ||
| 228 | display: inline-block; | ||
| 229 | margin-top: 5px; | ||
| 230 | font-weight: 600;">Front-end</span> | ||
| 231 | <span style="background: #e6e6e6; | ||
| 232 | color: #777; | ||
| 233 | border-radius: 3px; | ||
| 234 | padding: 0px 10px; | ||
| 235 | font-size: 70%; | ||
| 236 | display: inline-block; | ||
| 237 | margin-top: 5px; | ||
| 238 | font-weight: 600;">Best practices</span> | ||
| 239 | </div> | ||
| 240 | </div> | ||
| 241 | <div style="margin-bottom: 30px;"> | ||
| 242 | <a href="https://opensource.googleblog.com/2020/12/finding-critical-open-source-projects.html" style="color: #3252a8; font-weight: bold;">Finding Critical Open Source Projects</a> | ||
| 243 | <div style="margin-block-start: 5px; font-size: 90%;">Criticality of an open source project is difficult to define; what might be a critical dependency for one consumer of open source software may be entirely absent for another. However, arriving at a shared understanding and framework allows us to have productive conversations about our dependencies. Simply put, we define criticality to be the influence and importance of a project.</div> | ||
| 244 | <div> | ||
| 245 | <span style="background: #e6e6e6; | ||
| 246 | color: #777; | ||
| 247 | border-radius: 3px; | ||
| 248 | padding: 0px 10px; | ||
| 249 | font-size: 70%; | ||
| 250 | display: inline-block; | ||
| 251 | margin-top: 5px; | ||
| 252 | font-weight: 600;">Blog</span> | ||
| 253 | <span style="background: #e6e6e6; | ||
| 254 | color: #777; | ||
| 255 | border-radius: 3px; | ||
| 256 | padding: 0px 10px; | ||
| 257 | font-size: 70%; | ||
| 258 | display: inline-block; | ||
| 259 | margin-top: 5px; | ||
| 260 | font-weight: 600;">Open source</span> | ||
| 261 | </div> | ||
| 262 | </div> | ||
| 263 | <div style="margin-bottom: 30px;"> | ||
| 264 | <a href="https://www.stitcher.com/show/the-state-of-the-web/episode/http-archives-10th-anniversary-79556890" style="color: #3252a8; font-weight: bold;">HTTP Archive's 10th Anniversary</a> | ||
| 265 | <div style="margin-block-start: 5px; font-size: 90%;">Rick meets with Steve Souders, who created the HTTP Archive project 10 years ago this month, to talk about its origins and reflect on it's growth.</div> | ||
| 266 | <div> | ||
| 267 | <span style="background: #e6e6e6; | ||
| 268 | color: #777; | ||
| 269 | border-radius: 3px; | ||
| 270 | padding: 0px 10px; | ||
| 271 | font-size: 70%; | ||
| 272 | display: inline-block; | ||
| 273 | margin-top: 5px; | ||
| 274 | font-weight: 600;">Podcast</span> | ||
| 275 | <span style="background: #e6e6e6; | ||
| 276 | color: #777; | ||
| 277 | border-radius: 3px; | ||
| 278 | padding: 0px 10px; | ||
| 279 | font-size: 70%; | ||
| 280 | display: inline-block; | ||
| 281 | margin-top: 5px; | ||
| 282 | font-weight: 600;">Performance</span> | ||
| 283 | </div> | ||
| 284 | </div> | ||
| 285 | <div style="margin-bottom: 30px;"> | ||
| 286 | <a href="https://www.startalkradio.net/show/cosmic-queries-medieval-science-and-history/" style="color: #3252a8; font-weight: bold;">Cosmic Queries – Medieval Science and History</a> | ||
| 287 | <div style="margin-block-start: 5px; font-size: 90%;">When you think Middle Ages, does scientific advancement pop into your head? On this episode of StarTalk Radio, we’re exploring the science and history of medieval times as Neil deGrasse Tyson and comic co-host Matt Kirshen answer fan-submitted Cosmic Queries with Seb Falk, Cambridge Historian of Science and author of The Light Ages: The Surprising Story of Medieval Science.</div> | ||
| 288 | <div> | ||
| 289 | <span style="background: #e6e6e6; | ||
| 290 | color: #777; | ||
| 291 | border-radius: 3px; | ||
| 292 | padding: 0px 10px; | ||
| 293 | font-size: 70%; | ||
| 294 | display: inline-block; | ||
| 295 | margin-top: 5px; | ||
| 296 | font-weight: 600;">Podcast</span> | ||
| 297 | <span style="background: #e6e6e6; | ||
| 298 | color: #777; | ||
| 299 | border-radius: 3px; | ||
| 300 | padding: 0px 10px; | ||
| 301 | font-size: 70%; | ||
| 302 | display: inline-block; | ||
| 303 | margin-top: 5px; | ||
| 304 | font-weight: 600;">Science</span> | ||
| 305 | <span style="background: #e6e6e6; | ||
| 306 | color: #777; | ||
| 307 | border-radius: 3px; | ||
| 308 | padding: 0px 10px; | ||
| 309 | font-size: 70%; | ||
| 310 | display: inline-block; | ||
| 311 | margin-top: 5px; | ||
| 312 | font-weight: 600;">History</span> | ||
| 313 | </div> | ||
| 314 | </div> | ||
| 315 | |||
| 316 | </div> | ||
| 317 | |||
| 318 | <div style="text-align: center; font-size: 80%; margin-top: 20px;"> | ||
| 319 | <a style="color: #666; margin: auto 10px" href="https://mitjafelicijan.com/weekly-newsletter-archive/">weekly links archive</a> | ||
| 320 | <a style="color: #666; margin: auto 10px" href="https://mitjafelicijan.com">mitjafelicijan.com</a> | ||
| 321 | <a style="color: #666; margin: auto 10px" href="https://github.com/mitjafelicijan">github.com/mitjafelicijan</a> | ||
| 322 | </div> | ||
| 323 | |||
| 324 | </body> | ||
| 325 | |||
| 326 | </html> | ||
diff --git a/newsletter/generated/2021-01.html b/newsletter/generated/2021-01.html deleted file mode 100644 index 440f0db..0000000 --- a/newsletter/generated/2021-01.html +++ /dev/null | |||
| @@ -1,198 +0,0 @@ | |||
| 1 | <html> | ||
| 2 | |||
| 3 | <head> | ||
| 4 | <title>2021: Week #01 Links</title> | ||
| 5 | </head> | ||
| 6 | |||
| 7 | <body style="background: #f2f2f2; padding: 60px; color: #222222; line-height: 22px; font-family: sans-serif, system-ui, -apple-system; font-size: 16px;"> | ||
| 8 | |||
| 9 | <div style="width: 650px; background: #ffffff; text-align: left; padding: 40px; margin: 0 auto; border-radius: 10px;"> | ||
| 10 | |||
| 11 | <div style="margin-bottom: 30px;"> | ||
| 12 | <a href="https://www.youtube.com/watch?v=p8u_k2LIZyo" style="color: #3252a8; font-weight: bold;">Fast Inverse Square Root — A Quake III Algorithm</a> | ||
| 13 | <div style="margin-block-start: 5px; font-size: 90%;">In this video we will take an in depth look at the fast inverse square root and see where the mysterious number 0x5f3759df comes from. This algorithm became famous after id Software open sourced the engine for Quake III. On the way we will also learn about floating point numbers and newton's method.</div> | ||
| 14 | <div> | ||
| 15 | <span style="background: #e6e6e6; | ||
| 16 | color: #777; | ||
| 17 | border-radius: 3px; | ||
| 18 | padding: 0px 10px; | ||
| 19 | font-size: 70%; | ||
| 20 | display: inline-block; | ||
| 21 | margin-top: 5px; | ||
| 22 | font-weight: 600;">Video</span> | ||
| 23 | <span style="background: #e6e6e6; | ||
| 24 | color: #777; | ||
| 25 | border-radius: 3px; | ||
| 26 | padding: 0px 10px; | ||
| 27 | font-size: 70%; | ||
| 28 | display: inline-block; | ||
| 29 | margin-top: 5px; | ||
| 30 | font-weight: 600;">Quake III</span> | ||
| 31 | </div> | ||
| 32 | </div> | ||
| 33 | <div style="margin-bottom: 30px;"> | ||
| 34 | <a href="https://www.youtube.com/watch?v=zV2VEOHNCJU" style="color: #3252a8; font-weight: bold;">Goodbye, Adobe Flash</a> | ||
| 35 | <div style="margin-block-start: 5px; font-size: 90%;">A thrice-weekly news show about tech + gaming culture.</div> | ||
| 36 | <div> | ||
| 37 | <span style="background: #e6e6e6; | ||
| 38 | color: #777; | ||
| 39 | border-radius: 3px; | ||
| 40 | padding: 0px 10px; | ||
| 41 | font-size: 70%; | ||
| 42 | display: inline-block; | ||
| 43 | margin-top: 5px; | ||
| 44 | font-weight: 600;">Video</span> | ||
| 45 | <span style="background: #e6e6e6; | ||
| 46 | color: #777; | ||
| 47 | border-radius: 3px; | ||
| 48 | padding: 0px 10px; | ||
| 49 | font-size: 70%; | ||
| 50 | display: inline-block; | ||
| 51 | margin-top: 5px; | ||
| 52 | font-weight: 600;">Tech news</span> | ||
| 53 | </div> | ||
| 54 | </div> | ||
| 55 | <div style="margin-bottom: 30px;"> | ||
| 56 | <a href="https://www.youtube.com/watch?v=HL7DEkXV_60" style="color: #3252a8; font-weight: bold;">The Year's Biggest Breakthroughs in Math and Computer Science</a> | ||
| 57 | <div style="margin-block-start: 5px; font-size: 90%;">For mathematicians and computer scientists, 2020 was full of discipline-spanning discoveries and celebrations of creativity. We'd like to take a moment to recognize some of these achievements.</div> | ||
| 58 | <div> | ||
| 59 | <span style="background: #e6e6e6; | ||
| 60 | color: #777; | ||
| 61 | border-radius: 3px; | ||
| 62 | padding: 0px 10px; | ||
| 63 | font-size: 70%; | ||
| 64 | display: inline-block; | ||
| 65 | margin-top: 5px; | ||
| 66 | font-weight: 600;">Video</span> | ||
| 67 | <span style="background: #e6e6e6; | ||
| 68 | color: #777; | ||
| 69 | border-radius: 3px; | ||
| 70 | padding: 0px 10px; | ||
| 71 | font-size: 70%; | ||
| 72 | display: inline-block; | ||
| 73 | margin-top: 5px; | ||
| 74 | font-weight: 600;">Math and Computer Science</span> | ||
| 75 | </div> | ||
| 76 | </div> | ||
| 77 | <div style="margin-bottom: 30px;"> | ||
| 78 | <a href="https://www.freecodecamp.org/news/20-award-winning-games-explained-code-breakdown/" style="color: #3252a8; font-weight: bold;">20 Award-Winning 13-Kilobyte JavaScript Games You Can Play in Your Browser</a> | ||
| 79 | <div style="margin-block-start: 5px; font-size: 90%;">In this article, I am going to show you 20 award-winning JavaScript games from the JS13kGames competition. So in other words, you're going to see 20 great examples of code from 20 insanely talented developers.</div> | ||
| 80 | <div> | ||
| 81 | <span style="background: #e6e6e6; | ||
| 82 | color: #777; | ||
| 83 | border-radius: 3px; | ||
| 84 | padding: 0px 10px; | ||
| 85 | font-size: 70%; | ||
| 86 | display: inline-block; | ||
| 87 | margin-top: 5px; | ||
| 88 | font-weight: 600;">Blog</span> | ||
| 89 | <span style="background: #e6e6e6; | ||
| 90 | color: #777; | ||
| 91 | border-radius: 3px; | ||
| 92 | padding: 0px 10px; | ||
| 93 | font-size: 70%; | ||
| 94 | display: inline-block; | ||
| 95 | margin-top: 5px; | ||
| 96 | font-weight: 600;">Games</span> | ||
| 97 | </div> | ||
| 98 | </div> | ||
| 99 | <div style="margin-bottom: 30px;"> | ||
| 100 | <a href="https://www.hackster.io/news/espressif-s-new-esp32-s3-adds-ai-features-for-iot-devices-b42b902abdf5" style="color: #3252a8; font-weight: bold;">Espressif's New ESP32-S3 Adds AI Features for IoT Devices</a> | ||
| 101 | <div style="margin-block-start: 5px; font-size: 90%;">The very last day of 2020 came with great news for ESP32 fans. The ubiquitous IoT microcontroller is getting a new family member — the ESP32-S3! Espressif's latest introduction includes an updated dual-core MCU, expanded GPIO, AI-focused instructions, and hardware-accelerated security features.</div> | ||
| 102 | <div> | ||
| 103 | <span style="background: #e6e6e6; | ||
| 104 | color: #777; | ||
| 105 | border-radius: 3px; | ||
| 106 | padding: 0px 10px; | ||
| 107 | font-size: 70%; | ||
| 108 | display: inline-block; | ||
| 109 | margin-top: 5px; | ||
| 110 | font-weight: 600;">Product</span> | ||
| 111 | <span style="background: #e6e6e6; | ||
| 112 | color: #777; | ||
| 113 | border-radius: 3px; | ||
| 114 | padding: 0px 10px; | ||
| 115 | font-size: 70%; | ||
| 116 | display: inline-block; | ||
| 117 | margin-top: 5px; | ||
| 118 | font-weight: 600;">IoT</span> | ||
| 119 | </div> | ||
| 120 | </div> | ||
| 121 | <div style="margin-bottom: 30px;"> | ||
| 122 | <a href="https://www.rbth.com/history/333230-radioactive-materials-sold-ussr" style="color: #3252a8; font-weight: bold;">Radioactive materials were once sold in a STORE in the USSR!</a> | ||
| 123 | <div style="margin-block-start: 5px; font-size: 90%;">‘Izotopy’ was the name of a specialist store in Moscow that sold radioactive materials. And demand for them was very high. But how was such a thing possible?</div> | ||
| 124 | <div> | ||
| 125 | <span style="background: #e6e6e6; | ||
| 126 | color: #777; | ||
| 127 | border-radius: 3px; | ||
| 128 | padding: 0px 10px; | ||
| 129 | font-size: 70%; | ||
| 130 | display: inline-block; | ||
| 131 | margin-top: 5px; | ||
| 132 | font-weight: 600;">Blog</span> | ||
| 133 | <span style="background: #e6e6e6; | ||
| 134 | color: #777; | ||
| 135 | border-radius: 3px; | ||
| 136 | padding: 0px 10px; | ||
| 137 | font-size: 70%; | ||
| 138 | display: inline-block; | ||
| 139 | margin-top: 5px; | ||
| 140 | font-weight: 600;">Russia</span> | ||
| 141 | </div> | ||
| 142 | </div> | ||
| 143 | <div style="margin-bottom: 30px;"> | ||
| 144 | <a href="https://stackoverflow.blog/2021/01/01/podcast-300-welcome-to-2021-with-joel-spolsky/" style="color: #3252a8; font-weight: bold;">Welcome to 2021 with Joel Spolsky</a> | ||
| 145 | <div style="margin-block-start: 5px; font-size: 90%;">We are stepping into a new year with a very special guest, Stack Overflow's co-founder and chairman, Joel Spolsky. We chat programming, social networks, and what comes next.</div> | ||
| 146 | <div> | ||
| 147 | <span style="background: #e6e6e6; | ||
| 148 | color: #777; | ||
| 149 | border-radius: 3px; | ||
| 150 | padding: 0px 10px; | ||
| 151 | font-size: 70%; | ||
| 152 | display: inline-block; | ||
| 153 | margin-top: 5px; | ||
| 154 | font-weight: 600;">Podcast</span> | ||
| 155 | <span style="background: #e6e6e6; | ||
| 156 | color: #777; | ||
| 157 | border-radius: 3px; | ||
| 158 | padding: 0px 10px; | ||
| 159 | font-size: 70%; | ||
| 160 | display: inline-block; | ||
| 161 | margin-top: 5px; | ||
| 162 | font-weight: 600;">Stack Overflow</span> | ||
| 163 | </div> | ||
| 164 | </div> | ||
| 165 | <div style="margin-bottom: 30px;"> | ||
| 166 | <a href="https://replika.ai/" style="color: #3252a8; font-weight: bold;">The AI companion who cares</a> | ||
| 167 | <div style="margin-block-start: 5px; font-size: 90%;">Replika is a #1 chatbot companion powered by artificial intelligence.</div> | ||
| 168 | <div> | ||
| 169 | <span style="background: #e6e6e6; | ||
| 170 | color: #777; | ||
| 171 | border-radius: 3px; | ||
| 172 | padding: 0px 10px; | ||
| 173 | font-size: 70%; | ||
| 174 | display: inline-block; | ||
| 175 | margin-top: 5px; | ||
| 176 | font-weight: 600;">Product</span> | ||
| 177 | <span style="background: #e6e6e6; | ||
| 178 | color: #777; | ||
| 179 | border-radius: 3px; | ||
| 180 | padding: 0px 10px; | ||
| 181 | font-size: 70%; | ||
| 182 | display: inline-block; | ||
| 183 | margin-top: 5px; | ||
| 184 | font-weight: 600;">AI Chatbot</span> | ||
| 185 | </div> | ||
| 186 | </div> | ||
| 187 | |||
| 188 | </div> | ||
| 189 | |||
| 190 | <div style="text-align: center; font-size: 80%; margin-top: 20px;"> | ||
| 191 | <a style="color: #666; margin: auto 10px" href="https://mitjafelicijan.com/weekly-newsletter-archive/">weekly links archive</a> | ||
| 192 | <a style="color: #666; margin: auto 10px" href="https://mitjafelicijan.com">mitjafelicijan.com</a> | ||
| 193 | <a style="color: #666; margin: auto 10px" href="https://github.com/mitjafelicijan">github.com/mitjafelicijan</a> | ||
| 194 | </div> | ||
| 195 | |||
| 196 | </body> | ||
| 197 | |||
| 198 | </html> | ||
diff --git a/newsletter/generated/index.html b/newsletter/generated/index.html deleted file mode 100644 index bc73a5e..0000000 --- a/newsletter/generated/index.html +++ /dev/null | |||
| @@ -1,37 +0,0 @@ | |||
| 1 | <!DOCTYPE html> | ||
| 2 | <html lang="en"> | ||
| 3 | |||
| 4 | <head> | ||
| 5 | |||
| 6 | <meta charset="utf-8"> | ||
| 7 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
| 8 | <meta http-equiv="X-UA-Compatible" content="ie=edge"> | ||
| 9 | |||
| 10 | <meta name="theme-color" content="#ffffff"> | ||
| 11 | <meta name="generator" content="https://github.com/mitjafelicijan/staticgen"> | ||
| 12 | |||
| 13 | <title>Mitja Felicijan - Weekly links archive</title> | ||
| 14 | |||
| 15 | <link rel="stylesheet" href="https://mitjafelicijan.com/static/style.css"> | ||
| 16 | <link rel="icon" type="image/png" href="https://mitjafelicijan.com/static/avatar-64x64.png"> | ||
| 17 | |||
| 18 | </head> | ||
| 19 | |||
| 20 | <body> | ||
| 21 | |||
| 22 | <main> | ||
| 23 | |||
| 24 | <a href="/">⬅ Back home</a> | ||
| 25 | |||
| 26 | <h2>Weekly links archive</h2> | ||
| 27 | <ul class="article-list"> | ||
| 28 | <li><a href="/weekly-newsletter-archive/2021-01.html">2021, 01</a></li> | ||
| 29 | <li><a href="/weekly-newsletter-archive/2020-53.html">2020, 53</a></li> | ||
| 30 | <li><a href="/weekly-newsletter-archive/2020-52.html">2020, 52</a></li> | ||
| 31 | </ul> | ||
| 32 | |||
| 33 | </main> | ||
| 34 | |||
| 35 | </body> | ||
| 36 | |||
| 37 | </html> | ||
diff --git a/newsletter/package.json b/newsletter/package.json deleted file mode 100644 index c4c5bc3..0000000 --- a/newsletter/package.json +++ /dev/null | |||
| @@ -1,20 +0,0 @@ | |||
| 1 | { | ||
| 2 | "name": "weekly-mailing", | ||
| 3 | "version": "1.0.0", | ||
| 4 | "description": "", | ||
| 5 | "main": "index.js", | ||
| 6 | "scripts": { | ||
| 7 | "test": "echo \"Error: no test specified\" && exit 1" | ||
| 8 | }, | ||
| 9 | "keywords": [], | ||
| 10 | "author": "", | ||
| 11 | "license": "ISC", | ||
| 12 | "dependencies": { | ||
| 13 | "@sendgrid/mail": "^7.4.0", | ||
| 14 | "axios": "^0.21.1", | ||
| 15 | "dayjs": "^1.9.7", | ||
| 16 | "handlebars": "^4.7.6", | ||
| 17 | "meow": "^8.1.0", | ||
| 18 | "yesno": "^0.3.1" | ||
| 19 | } | ||
| 20 | } | ||
diff --git a/newsletter/send b/newsletter/send deleted file mode 100755 index 66bdeb9..0000000 --- a/newsletter/send +++ /dev/null | |||
| @@ -1,129 +0,0 @@ | |||
| 1 | #!/usr/bin/env node | ||
| 2 | |||
| 3 | const fs = require('fs'); | ||
| 4 | const path = require('path'); | ||
| 5 | const axios = require('axios'); | ||
| 6 | const dayjs = require('dayjs'); | ||
| 7 | const weekOfYear = require('dayjs/plugin/weekOfYear'); | ||
| 8 | const handlebars = require('handlebars'); | ||
| 9 | const yesno = require('yesno'); | ||
| 10 | const meow = require('meow'); | ||
| 11 | const { reverse } = require('dns'); | ||
| 12 | |||
| 13 | dayjs.extend(weekOfYear); | ||
| 14 | |||
| 15 | (async function () { | ||
| 16 | |||
| 17 | const cli = meow(` | ||
| 18 | Usage | ||
| 19 | $ ./send <input> | ||
| 20 | |||
| 21 | Options | ||
| 22 | --production, -p Uses production mailing list | ||
| 23 | |||
| 24 | Examples | ||
| 25 | $ ./send campaigns/2020-51.json --production | ||
| 26 | `, { | ||
| 27 | flags: { | ||
| 28 | production: { | ||
| 29 | type: 'boolean', | ||
| 30 | alias: 'p' | ||
| 31 | } | ||
| 32 | } | ||
| 33 | }); | ||
| 34 | |||
| 35 | if (cli.input.length === 0) { | ||
| 36 | console.log('You must provide campagin JSON file.'); | ||
| 37 | process.exit(1); | ||
| 38 | } | ||
| 39 | |||
| 40 | const campaignJSONFile = cli.input[0]; | ||
| 41 | const year = path.basename(cli.input[0]).split('.')[0].split('-')[0]; | ||
| 42 | const week = path.basename(cli.input[0]).split('.')[0].split('-')[1]; | ||
| 43 | const from = { name: 'Mitja Felicijan', email: 'weekly@mitjafelicijan.com' }; | ||
| 44 | const mailingList = cli.flags.production | ||
| 45 | ? { env: 'production', id: 'b03de6fc-ff95-40a0-8707-c0706b3c0b31' } | ||
| 46 | : { env: 'testing', id: '2bbcdedb-49d8-48f3-9f33-df6e04c9e5bf' }; | ||
| 47 | |||
| 48 | const headers = { | ||
| 49 | 'Authorization': 'Bearer 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', | ||
| 50 | 'Content-Type': 'application/json', | ||
| 51 | }; | ||
| 52 | |||
| 53 | // gets current week | ||
| 54 | let campaign = null; | ||
| 55 | try { | ||
| 56 | campaign = require(`./${campaignJSONFile}`); | ||
| 57 | } catch (err) { | ||
| 58 | console.error(err); | ||
| 59 | process.exit(1); | ||
| 60 | } | ||
| 61 | |||
| 62 | // gets list subscribers | ||
| 63 | const personalizations = []; | ||
| 64 | const contacts = await axios.get('https://api.sendgrid.com/v3/marketing/contacts', { headers: headers }).catch(error => { console.log(error) }); | ||
| 65 | if (contacts) { | ||
| 66 | for (const contact of contacts.data.result) { | ||
| 67 | if (contact.list_ids.includes(mailingList.id)) { | ||
| 68 | personalizations.push({ to: [{ email: contact.email }] }); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | // gets handlebars template contents | ||
| 74 | let template = null; | ||
| 75 | try { | ||
| 76 | template = handlebars.compile(fs.readFileSync('templates/mailing.hbs', 'utf8')); | ||
| 77 | template = template({ title: `${year}: Week #${week} Links`, campaign }); | ||
| 78 | } catch (e) { | ||
| 79 | console.error(err); | ||
| 80 | process.exit(1); | ||
| 81 | } | ||
| 82 | |||
| 83 | fs.writeFileSync(`generated/${year}-${week}.html`, template); | ||
| 84 | |||
| 85 | // asks for user input to allow sending emails | ||
| 86 | console.log(`\nWill send to ${personalizations.length} subscribers from list "${mailingList.env}":`) | ||
| 87 | for (const subscriber of personalizations) { | ||
| 88 | console.log(' - ', subscriber.to[0].email) | ||
| 89 | } | ||
| 90 | |||
| 91 | const consent = await yesno({ | ||
| 92 | question: '\nAre you sure you want to continue?' | ||
| 93 | }); | ||
| 94 | |||
| 95 | if (consent) { | ||
| 96 | // send actual emails | ||
| 97 | await axios.post('https://api.sendgrid.com/v3/mail/send', { | ||
| 98 | from, | ||
| 99 | subject: `Week #${week} Links`, | ||
| 100 | personalizations, | ||
| 101 | content: [{ | ||
| 102 | type: 'text/html', | ||
| 103 | value: template | ||
| 104 | }] | ||
| 105 | }, { headers: headers }).catch(error => { console.log(error) }); | ||
| 106 | } | ||
| 107 | |||
| 108 | console.log('\nAnd we are done.\n'); | ||
| 109 | |||
| 110 | // generates index file | ||
| 111 | |||
| 112 | const HTMLFiles = fs.readdirSync('./generated/'); | ||
| 113 | const indexFile = HTMLFiles.indexOf('index.html'); | ||
| 114 | if (indexFile > -1) HTMLFiles.splice(indexFile, 1); | ||
| 115 | |||
| 116 | HTMLFiles.forEach((item, idx) => { | ||
| 117 | const parts = item.split('.')[0].split('-'); | ||
| 118 | HTMLFiles[idx] = { | ||
| 119 | year: parts[0], | ||
| 120 | week: parts[1], | ||
| 121 | file: item, | ||
| 122 | } | ||
| 123 | }); | ||
| 124 | |||
| 125 | let indexTemplate = handlebars.compile(fs.readFileSync('templates/index.hbs', 'utf8')); | ||
| 126 | indexTemplate = indexTemplate({ files: HTMLFiles.reverse() }); | ||
| 127 | fs.writeFileSync(`generated/index.html`, indexTemplate); | ||
| 128 | |||
| 129 | }()); | ||
diff --git a/newsletter/templates/index.hbs b/newsletter/templates/index.hbs deleted file mode 100644 index 8a96125..0000000 --- a/newsletter/templates/index.hbs +++ /dev/null | |||
| @@ -1,37 +0,0 @@ | |||
| 1 | <!DOCTYPE html> | ||
| 2 | <html lang="en"> | ||
| 3 | |||
| 4 | <head> | ||
| 5 | |||
| 6 | <meta charset="utf-8"> | ||
| 7 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
| 8 | <meta http-equiv="X-UA-Compatible" content="ie=edge"> | ||
| 9 | |||
| 10 | <meta name="theme-color" content="#ffffff"> | ||
| 11 | <meta name="generator" content="https://github.com/mitjafelicijan/staticgen"> | ||
| 12 | |||
| 13 | <title>Mitja Felicijan - Weekly links archive</title> | ||
| 14 | |||
| 15 | <link rel="stylesheet" href="https://mitjafelicijan.com/static/style.css"> | ||
| 16 | <link rel="icon" type="image/png" href="https://mitjafelicijan.com/static/avatar-64x64.png"> | ||
| 17 | |||
| 18 | </head> | ||
| 19 | |||
| 20 | <body> | ||
| 21 | |||
| 22 | <main> | ||
| 23 | |||
| 24 | <a href="/">⬅ Back home</a> | ||
| 25 | |||
| 26 | <h2>Weekly links archive</h2> | ||
| 27 | <ul class="article-list"> | ||
| 28 | {{#each files}} | ||
| 29 | <li><a href="/weekly-newsletter-archive/{{ this.file }}">{{ this.year }}, {{ this.week }}</a></li> | ||
| 30 | {{/each}} | ||
| 31 | </ul> | ||
| 32 | |||
| 33 | </main> | ||
| 34 | |||
| 35 | </body> | ||
| 36 | |||
| 37 | </html> | ||
diff --git a/newsletter/templates/mailing.hbs b/newsletter/templates/mailing.hbs deleted file mode 100644 index d1c8cf4..0000000 --- a/newsletter/templates/mailing.hbs +++ /dev/null | |||
| @@ -1,42 +0,0 @@ | |||
| 1 | <html> | ||
| 2 | |||
| 3 | <head> | ||
| 4 | <title>{{ title }}</title> | ||
| 5 | </head> | ||
| 6 | |||
| 7 | <body style="background: #f2f2f2; padding: 60px; color: #222222; line-height: 22px; font-family: sans-serif, system-ui, -apple-system; font-size: 16px;"> | ||
| 8 | |||
| 9 | <div style="width: 650px; background: #ffffff; text-align: left; padding: 40px; margin: 0 auto; border-radius: 10px;"> | ||
| 10 | |||
| 11 | {{#each campaign.categories}} | ||
| 12 | {{#each this.links}} | ||
| 13 | <div style="margin-bottom: 30px;"> | ||
| 14 | <a href="{{this.url}}" style="color: #3252a8; font-weight: bold;">{{this.title}}</a> | ||
| 15 | <div style="margin-block-start: 5px; font-size: 90%;">{{this.excerpt}}</div> | ||
| 16 | <div> | ||
| 17 | {{#each this.tags}} | ||
| 18 | <span style="background: #e6e6e6; | ||
| 19 | color: #777; | ||
| 20 | border-radius: 3px; | ||
| 21 | padding: 0px 10px; | ||
| 22 | font-size: 70%; | ||
| 23 | display: inline-block; | ||
| 24 | margin-top: 5px; | ||
| 25 | font-weight: 600;">{{.}}</span> | ||
| 26 | {{/each}} | ||
| 27 | </div> | ||
| 28 | </div> | ||
| 29 | {{/each}} | ||
| 30 | {{/each}} | ||
| 31 | |||
| 32 | </div> | ||
| 33 | |||
| 34 | <div style="text-align: center; font-size: 80%; margin-top: 20px;"> | ||
| 35 | <a style="color: #666; margin: auto 10px" href="https://mitjafelicijan.com/weekly-newsletter-archive/">weekly links archive</a> | ||
| 36 | <a style="color: #666; margin: auto 10px" href="https://mitjafelicijan.com">mitjafelicijan.com</a> | ||
| 37 | <a style="color: #666; margin: auto 10px" href="https://github.com/mitjafelicijan">github.com/mitjafelicijan</a> | ||
| 38 | </div> | ||
| 39 | |||
| 40 | </body> | ||
| 41 | |||
| 42 | </html> | ||
