aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2020-12-28 06:38:05 +0100
committerMitja Felicijan <mitja.felicijan@gmail.com>2020-12-28 06:38:05 +0100
commitda6a25065b6e300527a392ff66c74bbeb90ba192 (patch)
tree88e092adb9249963667328c5ef1cf561fe2982cf
parent4c066bedb82d4b705d0e60308ceee64daf97388c (diff)
downloadmitjafelicijan.com-da6a25065b6e300527a392ff66c74bbeb90ba192.tar.gz
Added new weekly links
-rw-r--r--Makefile6
-rw-r--r--content/2020-12-25-weekly-links.md2
-rw-r--r--emailing/campaigns/2020-53.json122
-rw-r--r--emailing/generated/2020-52.html87
-rw-r--r--emailing/generated/2020-53.html326
-rw-r--r--emailing/generated/index.html36
-rw-r--r--emailing/package.json1
-rwxr-xr-x[-rw-r--r--]emailing/send (renamed from emailing/send.js)66
-rw-r--r--emailing/template.hbs26
-rw-r--r--emailing/templates/index.hbs37
-rw-r--r--emailing/templates/mailing.hbs42
11 files changed, 715 insertions, 36 deletions
diff --git a/Makefile b/Makefile
index bab75f8..d81f82d 100644
--- a/Makefile
+++ b/Makefile
@@ -14,5 +14,9 @@ clean:
14generate: 14generate:
15 staticgen --generate 15 staticgen --generate
16 16
17deploy: clean generate 17deploy: clean generate copy-weekly-links
18 firebase deploy 18 firebase deploy
19
20copy-weekly-links:
21 mkdir -p public/weekly-links-archive
22 cp -rf emailing/generated/* public/weekly-links-archive/
diff --git a/content/2020-12-25-weekly-links.md b/content/2020-12-25-weekly-links.md
index 161bd4e..876c2f2 100644
--- a/content/2020-12-25-weekly-links.md
+++ b/content/2020-12-25-weekly-links.md
@@ -4,4 +4,6 @@
4~ template: page 4~ template: page
5~ hide: true 5~ hide: true
6 6
7🕵🏼 [You can check old emailing archive sent here.](/weekly-links-archive/)
8
7<iframe src="https://cdn.forms-content.sg-form.com/b9a1dea3-465a-11eb-af61-0e1900a266f8" width="610px" height="700" frameborder="0" scrolling="no"></iframe> 9<iframe src="https://cdn.forms-content.sg-form.com/b9a1dea3-465a-11eb-af61-0e1900a266f8" width="610px" height="700" frameborder="0" scrolling="no"></iframe>
diff --git a/emailing/campaigns/2020-53.json b/emailing/campaigns/2020-53.json
new file mode 100644
index 0000000..de44449
--- /dev/null
+++ b/emailing/campaigns/2020-53.json
@@ -0,0 +1,122 @@
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/emailing/generated/2020-52.html b/emailing/generated/2020-52.html
new file mode 100644
index 0000000..a20531a
--- /dev/null
+++ b/emailing/generated/2020-52.html
@@ -0,0 +1,87 @@
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&#x3D;y1UzfahXfao&amp;ab_channel&#x3D;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&#x3D;y1UzfahXfao&amp;ab_channel&#x3D;GoogleChromeDevelopers" style="color: #3252a8; font-weight: bold;">Machine Learning &amp; 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&#x3D;M45iFPVdtj0&amp;ab_channel&#x3D;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&#x3D;QsOF9SJJdAA&amp;ab_channel&#x3D;GoogleChromeDevelopers" style="color: #3252a8; font-weight: bold;">What&#x27;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&#x3D;dfOKFSDG7IM&amp;ab_channel&#x3D;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&#x3D;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">mitjafelicijan.com</a>
82 <a style="color: #666; margin: auto 10px" href="https://github.com/mitjafelicijan">github.com/mitjafelicijan</a>
83 </div>
84
85 </body>
86
87</html>
diff --git a/emailing/generated/2020-53.html b/emailing/generated/2020-53.html
new file mode 100644
index 0000000..d306ef7
--- /dev/null
+++ b/emailing/generated/2020-53.html
@@ -0,0 +1,326 @@
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&amp;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&#x27;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&#x27;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&#x27;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-links-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/emailing/generated/index.html b/emailing/generated/index.html
new file mode 100644
index 0000000..1e83d9f
--- /dev/null
+++ b/emailing/generated/index.html
@@ -0,0 +1,36 @@
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-links/2020-53.html">2020, 53</a></li>
29 <li><a href="/weekly-links/2020-52.html">2020, 52</a></li>
30 </ul>
31
32 </main>
33
34 </body>
35
36</html>
diff --git a/emailing/package.json b/emailing/package.json
index 6def0f4..c4c5bc3 100644
--- a/emailing/package.json
+++ b/emailing/package.json
@@ -14,6 +14,7 @@
14 "axios": "^0.21.1", 14 "axios": "^0.21.1",
15 "dayjs": "^1.9.7", 15 "dayjs": "^1.9.7",
16 "handlebars": "^4.7.6", 16 "handlebars": "^4.7.6",
17 "meow": "^8.1.0",
17 "yesno": "^0.3.1" 18 "yesno": "^0.3.1"
18 } 19 }
19} 20}
diff --git a/emailing/send.js b/emailing/send
index 3e4aa5a..66bdeb9 100644..100755
--- a/emailing/send.js
+++ b/emailing/send
@@ -1,20 +1,47 @@
1#!/usr/bin/env node
2
1const fs = require('fs'); 3const fs = require('fs');
2// const path = require('path'); 4const path = require('path');
3const axios = require('axios'); 5const axios = require('axios');
4const dayjs = require('dayjs'); 6const dayjs = require('dayjs');
5const weekOfYear = require('dayjs/plugin/weekOfYear'); 7const weekOfYear = require('dayjs/plugin/weekOfYear');
6const handlebars = require('handlebars'); 8const handlebars = require('handlebars');
7const yesno = require('yesno'); 9const yesno = require('yesno');
10const meow = require('meow');
11const { reverse } = require('dns');
8 12
9dayjs.extend(weekOfYear); 13dayjs.extend(weekOfYear);
10 14
11(async function () { 15(async function () {
12 16
13 //const campaignId = 'b03de6fc-ff95-40a0-8707-c0706b3c0b31'; // production 17 const cli = meow(`
14 //const campaignId = '2bbcdedb-49d8-48f3-9f33-df6e04c9e5bf'; // testing 18 Usage
15 const from = { name: 'Mitja Felicijan', email: 'weekly@mitjafelicijan.com' }; 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 }
16 39
17 const mailingList = process.argv[2] == 'production' 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
18 ? { env: 'production', id: 'b03de6fc-ff95-40a0-8707-c0706b3c0b31' } 45 ? { env: 'production', id: 'b03de6fc-ff95-40a0-8707-c0706b3c0b31' }
19 : { env: 'testing', id: '2bbcdedb-49d8-48f3-9f33-df6e04c9e5bf' }; 46 : { env: 'testing', id: '2bbcdedb-49d8-48f3-9f33-df6e04c9e5bf' };
20 47
@@ -26,7 +53,7 @@ dayjs.extend(weekOfYear);
26 // gets current week 53 // gets current week
27 let campaign = null; 54 let campaign = null;
28 try { 55 try {
29 campaign = require(`./campaigns/${dayjs().format('YYYY')}-${dayjs().week()}.json`); 56 campaign = require(`./${campaignJSONFile}`);
30 } catch (err) { 57 } catch (err) {
31 console.error(err); 58 console.error(err);
32 process.exit(1); 59 process.exit(1);
@@ -46,13 +73,15 @@ dayjs.extend(weekOfYear);
46 // gets handlebars template contents 73 // gets handlebars template contents
47 let template = null; 74 let template = null;
48 try { 75 try {
49 template = handlebars.compile(fs.readFileSync('template.hbs', 'utf8')); 76 template = handlebars.compile(fs.readFileSync('templates/mailing.hbs', 'utf8'));
50 template = template(campaign); 77 template = template({ title: `${year}: Week #${week} Links`, campaign });
51 } catch (e) { 78 } catch (e) {
52 console.error(err); 79 console.error(err);
53 process.exit(1); 80 process.exit(1);
54 } 81 }
55 82
83 fs.writeFileSync(`generated/${year}-${week}.html`, template);
84
56 // asks for user input to allow sending emails 85 // asks for user input to allow sending emails
57 console.log(`\nWill send to ${personalizations.length} subscribers from list "${mailingList.env}":`) 86 console.log(`\nWill send to ${personalizations.length} subscribers from list "${mailingList.env}":`)
58 for (const subscriber of personalizations) { 87 for (const subscriber of personalizations) {
@@ -67,7 +96,7 @@ dayjs.extend(weekOfYear);
67 // send actual emails 96 // send actual emails
68 await axios.post('https://api.sendgrid.com/v3/mail/send', { 97 await axios.post('https://api.sendgrid.com/v3/mail/send', {
69 from, 98 from,
70 subject: `Week #${dayjs().week()} Links`, 99 subject: `Week #${week} Links`,
71 personalizations, 100 personalizations,
72 content: [{ 101 content: [{
73 type: 'text/html', 102 type: 'text/html',
@@ -78,4 +107,23 @@ dayjs.extend(weekOfYear);
78 107
79 console.log('\nAnd we are done.\n'); 108 console.log('\nAnd we are done.\n');
80 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
81}()); 129}());
diff --git a/emailing/template.hbs b/emailing/template.hbs
deleted file mode 100644
index 8fe22df..0000000
--- a/emailing/template.hbs
+++ /dev/null
@@ -1,26 +0,0 @@
1<html>
2
3 <head>
4 <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 categories}}
12 {{#each this.links}}
13 <div style="margin-bottom: 30px;">
14 <a href="{{this.url}}" style="color: #3252a8; font-weight: bold;">{{this.title}} ({{this.source}})</a>
15 <div style="margin-block-start: 5px; font-size: 90%;">{{this.excerpt}}</div>
16 </div>
17 {{/each}}
18 {{/each}}
19
20 </div>
21
22 <p style="text-align: center; font-size: 80%;">If you would like to stop receiving these emails reply to this email.</p>
23
24 </body>
25
26</html>
diff --git a/emailing/templates/index.hbs b/emailing/templates/index.hbs
new file mode 100644
index 0000000..50b7bdd
--- /dev/null
+++ b/emailing/templates/index.hbs
@@ -0,0 +1,37 @@
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-links/{{ this.file }}">{{ this.year }}, {{ this.week }}</a></li>
30 {{/each}}
31 </ul>
32
33 </main>
34
35 </body>
36
37</html>
diff --git a/emailing/templates/mailing.hbs b/emailing/templates/mailing.hbs
new file mode 100644
index 0000000..42b464d
--- /dev/null
+++ b/emailing/templates/mailing.hbs
@@ -0,0 +1,42 @@
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-links-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>