From d4f881c68f9d7b77af408242e3a7bb2367087a3f Mon Sep 17 00:00:00 2001 From: Duyet Le Date: Tue, 12 Nov 2024 00:30:09 +0700 Subject: [PATCH 1/3] feat(ui): add /featured, warn for old posts --- .../_posts/2015/08/cach-su-dung-git-rebase.md | 2 +- ...developer-roadshow-ho-chi-minh-viet-nam.md | 4 +- ...ut-o-dau-ban-cung-song-tot-thu-nhap-cao.md | 52 +++++++++---------- .../blog/_posts/2016/02/sitemapduyetdevcom.md | 20 ------- .../7-thu-thuat-voi-resting-va-spreading.md | 2 +- .../05/phuong-tien-cong-cong-san-francisco.md | 1 + apps/blog/_posts/2019/08/ir-evaluation.md | 1 + .../_posts/2019/08/ir-vector-space-model.md | 1 + .../2019/08/migrate-blogger-to-gatsby.md | 1 + apps/blog/_posts/2020/05/spark-on-k8s.md | 1 + apps/blog/_posts/2020/05/tldr-why-rf.md | 2 +- .../2021/05/migrate-to-cloudflare-pages.md | 2 + .../_posts/2021/11/rust-data-engineering.md | 1 + .../_posts/2021/11/spark-node-decommission.md | 1 + apps/blog/_posts/2022/02/rust-trait.md | 1 + .../2022/03/spark-kubernetes-at-fossil.md | 1 + apps/blog/_posts/2023/01/clickhouse.md | 1 + .../2023/01/data-engineering-rust-tools.md | 1 + .../_posts/2023/05/migrate-blog-to-nextjs.md | 1 + .../06/fossil-data-platform-written-rust.md | 1 + apps/blog/_posts/2023/09/nvim-setup-2023.md | 1 + .../_posts/2024/03/clickhouse-monitoring.md | 1 + .../2024/03/clickhouse-on-kubernetes.md | 1 + ...clickhouse-replicatedreplacingmergetree.md | 1 + .../[year]/[month]/[slug]/content/content.tsx | 5 +- .../[slug]/content/old-post-warning.tsx | 43 +++++++++++++++ apps/blog/app/archives/page.tsx | 8 +-- apps/blog/app/archives2/page.tsx | 40 -------------- .../app/{archives2 => featured}/layout.tsx | 8 +-- apps/blog/app/featured/page.tsx | 36 +++++++++++++ apps/blog/app/page.tsx | 17 +++--- apps/blog/components/year-post.tsx | 25 ++++++--- packages/interfaces/src/post.ts | 1 + packages/libs/getPost.ts | 38 ++++++++++++-- 34 files changed, 202 insertions(+), 120 deletions(-) delete mode 100644 apps/blog/_posts/2016/02/sitemapduyetdevcom.md create mode 100644 apps/blog/app/[year]/[month]/[slug]/content/old-post-warning.tsx delete mode 100644 apps/blog/app/archives2/page.tsx rename apps/blog/app/{archives2 => featured}/layout.tsx (59%) create mode 100644 apps/blog/app/featured/page.tsx diff --git a/apps/blog/_posts/2015/08/cach-su-dung-git-rebase.md b/apps/blog/_posts/2015/08/cach-su-dung-git-rebase.md index 76344f60..20c43cfd 100644 --- a/apps/blog/_posts/2015/08/cach-su-dung-git-rebase.md +++ b/apps/blog/_posts/2015/08/cach-su-dung-git-rebase.md @@ -1,5 +1,5 @@ --- -title: Git - Cách sử dụng git rebase, cách gộp nhiều commit bằng rebase +title: Git rebase, gộp commits bằng rebase date: '2015-08-25' author: Duyet tags: diff --git a/apps/blog/_posts/2015/08/google-cloud-platform-developer-roadshow-ho-chi-minh-viet-nam.md b/apps/blog/_posts/2015/08/google-cloud-platform-developer-roadshow-ho-chi-minh-viet-nam.md index 58bf17f5..fcf3d996 100644 --- a/apps/blog/_posts/2015/08/google-cloud-platform-developer-roadshow-ho-chi-minh-viet-nam.md +++ b/apps/blog/_posts/2015/08/google-cloud-platform-developer-roadshow-ho-chi-minh-viet-nam.md @@ -1,7 +1,5 @@ --- -title: - Google Cloud Platform Developer Roadshow, Ho Chi Minh, Vietnam by GCPUG and - GDG +title: Google Cloud Platform Developer Roadshow date: '2015-08-27' author: Duyet tags: diff --git a/apps/blog/_posts/2015/08/lam-theo-duoc-6-dieu-duoi-day-dam-bao-vut-o-dau-ban-cung-song-tot-thu-nhap-cao.md b/apps/blog/_posts/2015/08/lam-theo-duoc-6-dieu-duoi-day-dam-bao-vut-o-dau-ban-cung-song-tot-thu-nhap-cao.md index 1a6e6817..b7db95fa 100644 --- a/apps/blog/_posts/2015/08/lam-theo-duoc-6-dieu-duoi-day-dam-bao-vut-o-dau-ban-cung-song-tot-thu-nhap-cao.md +++ b/apps/blog/_posts/2015/08/lam-theo-duoc-6-dieu-duoi-day-dam-bao-vut-o-dau-ban-cung-song-tot-thu-nhap-cao.md @@ -1,7 +1,5 @@ --- -title: - Làm theo được 6 điều dưới đây, đảm bảo vứt ở đâu bạn cũng sống tốt thu nhập - cao. +title: 6 lời khuyên date: '2015-08-09' author: Duyet tags: @@ -13,15 +11,13 @@ category: News description: Đây là viết của Dượng Tony - Tony buổi sáng, không liên quan gì đến các bài viết kỹ thuật trên blog này cả. Nhưng bài viết này mỗi lần đọc lại luôn mang cho mình thêm phần động lực. Post lại ở đây để tự nhắc nhở bản thân luôn phấn đấu, cũng như để mọi người cùng đọc đươc. --- -Đây là viết của Dượng Tony - Tony buổi sáng, không liên quan gì đến các bài viết kỹ thuật trên blog này cả. Nhưng bài viết này mỗi lần đọc lại luôn mang cho mình thêm phần động lực. Post lại ở đây để tự nhắc nhở bản thân luôn phấn đấu, cũng như để mọi người cùng đọc đươc. +Đây là viết của Tony buổi sáng, không liên quan gì đến các bài viết kỹ thuật trên blog này cả. Nhưng bài viết này mỗi lần đọc lại luôn mang cho mình thêm phần động lực. Post lại ở đây để tự nhắc nhở bản thân luôn phấn đấu, cũng như để mọi người cùng đọc đươc. -## 1\. Ở: Nếu ở trọ, hãy tìm nhà trọ ở xa nhất mà có thể kết nối với chỗ làm bằng phương tiện công cộng. +## 1. Ở: Nếu ở trọ, hãy tìm nhà trọ ở xa nhất mà có thể kết nối với chỗ làm bằng phương tiện công cộng Lúc ngồi trên xe buýt, tàu điện cũng là lúc quan sát xã hội từ trên cao, người đi xe máy xe hơi đều thấp hơn bạn. Không nên vật lộn với việc tự lái xe. 30 phút lái xe là 30 phút bạn lãng phí cho sự căng thẳng, nguy cơ tai nạn, hít khói bụi làm giảm tuổi thọ. Đi bộ từ trạm xe buýt đến nơi cần đến giúp tim bạn khỏe mạnh. Nếu đi xe buýt mất 1h30 và tự lái xe mất 30 phút, hãy chọn đi xe buýt. Đám đông chỉ đi xe cá nhân, mình ngược lại với đám đông, đã sao? -[![](https://1.bp.blogspot.com/-_AGdPVcTw6c/VcdELg2WkII/AAAAAAAACtw/yvgddlzqydc/s1600/150524-b-lam-tho-dc-5-dieu-duoi-day-1.jpg)](https://1.bp.blogspot.com/-_AGdPVcTw6c/VcdELg2WkII/AAAAAAAACtw/yvgddlzqydc/s1600/150524-b-lam-tho-dc-5-dieu-duoi-day-1.jpg) - -Ảnh: urbanstyle +![Ảnh: urbanstyle](https://1.bp.blogspot.com/-_AGdPVcTw6c/VcdELg2WkII/AAAAAAAACtw/yvgddlzqydc/s1600/150524-b-lam-tho-dc-5-dieu-duoi-day-1.jpg) Tại sao bạn muốn nhảy vô 5% người giàu có mà không từ bỏ được tư duy của 95% còn lại? Có việc nhỏ vậy mà bạn không dám thoát ra, thì việc lớn làm gì được? @@ -31,42 +27,42 @@ Sự sáng tạo mới đem lại cho bạn của cải và sự thú vị. Mà Lim kể, lúc ảnh làm phụ bếp, đang rửa thớt thì buộc miệng nói sau này mở chuỗi nhà hàng 30 cái toàn Đông Nam Á, ông bếp trưởng chửi đòi tạt sốt cà chua vô mặt. Giờ Lim có 100 cái nhà hàng còn ông đầu bếp kia tới gặp Lim nộp đơn xin việc. -## 2\. Ăn: Hãy dậy thật sớm, nấu cơm, xôi, mì. Nấu thêm để mang theo ăn trưa hoặc ăn ổ bánh mì, đĩa cơm bình dân nơi gần nhất. - -Mình nên ăn chay rau củ quả ở mức hấp/luộc, sẽ không có gì cả đâu nếu vài ngày trong tuần bạn không ăn thịt. Người ăn chay vẫn thông minh đẹp đẽ như thường. 90% kỹ sư IT người Ấn Độ ở Silicon Valley ăn chay. Mình ăn chay không phải vì tôn giáo mà vì sức khỏe. Thỉnh thoảng vẫn cứ quất thịt cá…nhưng nếu nấu cho 1 mình mình ăn, đừng tốn thời gian. Cứ cá chiên/trứng luộc, rau củ quả hấp, trái cây là đủ. Không tốn thời gian cho việc ăn. +## 2. Ăn: Hãy dậy thật sớm, nấu cơm, xôi, mì. Nấu thêm để mang theo ăn trưa hoặc ăn ổ bánh mì, đĩa cơm bình dân nơi gần nhất -![](https://4.bp.blogspot.com/-DxPUOCbFwLI/VcdEZo_cUQI/AAAAAAAACt4/TvujbmoTwWA/s1600/150524-b-lam-tho-dc-5-dieu-duoi-day-2.jpg) +Mình nên ăn chay rau củ quả ở mức hấp/luộc, sẽ không có gì cả đâu nếu vài ngày trong tuần bạn không ăn thịt. Người ăn chay vẫn thông minh đẹp đẽ như thường. 90% kỹ sư IT người Ấn Độ ở Silicon Valley ăn chay. Mình ăn chay không phải vì tôn giáo mà vì sức khỏe. Thỉnh thoảng vẫn cứ quất thịt cá ... nhưng nếu nấu cho 1 mình mình ăn, đừng tốn thời gian. Cứ cá chiên/trứng luộc, rau củ quả hấp, trái cây là đủ. Không tốn thời gian cho việc ăn. -## 3\. Chơi: Nên mời bạn bè 2 lần một tháng, ăn bình dân thôi. Nhóm 4 người, mỗi đứa 2 lần, 1 tháng mình có 8 lần gặp gỡ. +![Ăn](https://4.bp.blogspot.com/-DxPUOCbFwLI/VcdEZo_cUQI/AAAAAAAACt4/TvujbmoTwWA/s1600/150524-b-lam-tho-dc-5-dieu-duoi-day-2.jpg) -Hãy chọn những người hiểu biết, giàu có hơn mình, đang làm công ty lớn, đang khởi nghiệp,…để nghe họ nói chuyện đời. Cá mập thì quây quần dưới đáy sâu. Cá lòng tong thì nhao nhao trên mặt nước, cạnh tranh khốc liệt việc đớp bọt. Khoe quần áo, bàn chuyện ca sĩ này diễn viên kia, viết thế này đúng viết thế kia sai…chỉ có ở đám lòng tong. Đám cá lớn sống im lặng. +## 3. Chơi: Nên mời bạn bè 2 lần một tháng, ăn bình dân thôi. Nhóm 4 người, mỗi đứa 2 lần, 1 tháng mình có 8 lần gặp gỡ -![](https://3.bp.blogspot.com/-xSewbWQ2DEQ/VcdEjYwkwuI/AAAAAAAACuA/Hpmv9Vy_iTY/s1600/150524-b-lam-tho-dc-5-dieu-duoi-day-3.jpg) +Hãy chọn những người hiểu biết, giàu có hơn mình, đang làm công ty lớn, đang khởi nghiệp, ... để nghe họ nói chuyện đời. Cá mập thì quây quần dưới đáy sâu. Cá lòng tong thì nhao nhao trên mặt nước, cạnh tranh khốc liệt việc đớp bọt. Khoe quần áo, bàn chuyện ca sĩ này diễn viên kia, viết thế này đúng viết thế kia sai ... chỉ có ở đám lòng tong. Đám cá lớn sống im lặng. -## 4\. Học: Phải dành 10 USD ~ 200 ngàn tiền mua sách/tháng. +![Chơi](https://3.bp.blogspot.com/-xSewbWQ2DEQ/VcdEjYwkwuI/AAAAAAAACuA/Hpmv9Vy_iTY/s1600/150524-b-lam-tho-dc-5-dieu-duoi-day-3.jpg) -Người vĩ đại trên khắp thế giới, ngoài tủ rượu ra, trong nhà họ còn có tủ sách. Hãy đọc sách dạy làm người, làm giàu, sách kinh tế, sách văn chương, sách nấu ăn hoặc bất cứ sách gì ưa thích. Kiến thức rộng sẽ giúp mình làm ăn rộng. Khi đi làm, việc nói giỏi, cái gì cũng biết khiến công việc trôi chảy hơn. Tháng này bạn chưa bỏ ra 200 ngàn mua sách thì coi như thua. Đọc xong sách, kể lại nội dung cho bạn bè. Đừng giấu. Nếu có khóa học nào đó, nên đăng ký, hoặc dồn lại vài tháng làm 1 khóa, nhớ học với người thành đạt thật sự, tức người có điều hành công ty lớn, bậc trí nhân…chứ không phải nhóm mua môi múa mép. +## 4. Học: Phải dành 10 USD ~ 200 ngàn tiền mua sách/tháng -[![](https://4.bp.blogspot.com/-wVdnppbAFcM/VcdEsFBedII/AAAAAAAACuI/rmRwSJ1XeN0/s1600/150524-b-lam-tho-dc-5-dieu-duoi-day-4.jpg)](https://4.bp.blogspot.com/-wVdnppbAFcM/VcdEsFBedII/AAAAAAAACuI/rmRwSJ1XeN0/s1600/150524-b-lam-tho-dc-5-dieu-duoi-day-4.jpg) +Người vĩ đại trên khắp thế giới, ngoài tủ rượu ra, trong nhà họ còn có tủ sách. Hãy đọc sách dạy làm người, làm giàu, sách kinh tế, sách văn chương, sách nấu ăn hoặc bất cứ sách gì ưa thích. Kiến thức rộng sẽ giúp mình làm ăn rộng. Khi đi làm, việc nói giỏi, cái gì cũng biết khiến công việc trôi chảy hơn. Tháng này bạn chưa bỏ ra 200 ngàn mua sách thì coi như thua. Đọc xong sách, kể lại nội dung cho bạn bè. Đừng giấu. Nếu có khóa học nào đó, nên đăng ký, hoặc dồn lại vài tháng làm 1 khóa, nhớ học với người thành đạt thật sự, tức người có điều hành công ty lớn, bậc trí nhân ... chứ không phải nhóm mua môi múa mép. -## 5\. Đi: Tháng để dành 1 triệu, năm sẽ có khoảng 12 triệu cho việc đi chơi. +![Học](https://4.bp.blogspot.com/-wVdnppbAFcM/VcdEsFBedII/AAAAAAAACuI/rmRwSJ1XeN0/s1600/150524-b-lam-tho-dc-5-dieu-duoi-day-4.jpg) -Ban đầu nên đi đường bộ sang các nước lân bang. Hãy tự thưởng mỗi năm một chuyến đi xa. Tết là thời điểm tốt để về thăm gia đình, rồi đi chơi trước khi vô làm trong năm mới. Nhất định phải đi nước ngoài mỗi năm một lần, để coi sông, coi biển, coi đại dương nó ra sao…có cái gì hay ho thì bắt chước, mang về làm ăn +## 5. Đi: Tháng để dành 1 triệu, năm sẽ có khoảng 12 triệu cho việc đi chơi -![](https://4.bp.blogspot.com/-JPIh9NiRB0k/VcdE0dJiW1I/AAAAAAAACuQ/PMiC8gDKj6U/s1600/150524-b-lam-tho-dc-5-dieu-duoi-day-5.jpg) +Ban đầu nên đi đường bộ sang các nước lân bang. Hãy tự thưởng mỗi năm một chuyến đi xa. +Tết là thời điểm tốt để về thăm gia đình, rồi đi chơi trước khi vô làm trong năm mới. +Nhất định phải đi nước ngoài mỗi năm một lần, để coi sông, coi biển, coi đại dương nó ra sao... có cái gì hay ho thì bắt chước, mang về làm ăn. -Trong tay nên có 1 cái smartphone loại bình dân để tra tìm bản đồ, hãy đặt vé máy bay/xe lửa/xe đò.. giá rẻ nhất. +![Đi](https://4.bp.blogspot.com/-JPIh9NiRB0k/VcdE0dJiW1I/AAAAAAAACuQ/PMiC8gDKj6U/s1600/150524-b-lam-tho-dc-5-dieu-duoi-day-5.jpg) -## 6\. Để dành: tháng TỐI THIỂU để dành 1 triệu. Cứ gửi ở ngân hàng, nhiều hơn có thể mua 5 phân hoặc 1 chỉ vàng, đó là vốn khởi nghiệp về sau. +Trong tay nên có 1 cái smartphone loại bình dân để tra tìm bản đồ, hãy đặt vé máy bay/xe lửa/xe đò, ... giá rẻ nhất. -Năm tới, nếu thu nhập vẫn 6 triệu, tự tát vô mặt. Muốn tăng lương, hãy cống hiến. Đừng sợ người khác không thấy nỗ lực của mình. Đừng "khôn" kiểu "tôi có được gì không, làm nhiều cho lắm thì lương cũng vậy". Tư duy này khiến mình nghèo miết. Hãy cố gắng làm thêm giờ. Bạn phải làm thêm việc ở cơ quan, đến sớm hơn, về trễ hơn. Trong lúc làm việc, tập trung cao độ, nhận nhiều việc của công ty giao, tự mở thêm các mối quan hệ trong công việc, tay kẹp ĐT, tay đánh máy, vừa đi vừa chạy...làm ầm ầm, ầm ầm vô. +## 6. Để dành: tháng TỐI THIỂU để dành 1 triệu. Cứ gửi ở ngân hàng, nhiều hơn có thể mua 5 phân hoặc 1 chỉ vàng, đó là vốn khởi nghiệp về sau -[![](https://3.bp.blogspot.com/-uEmqgUkgm_s/VcdFAlaXgEI/AAAAAAAACuY/xvoFMq2Qiko/s1600/150524-b-lam-tho-dc-5-dieu-duoi-day-6.jpg)](https://3.bp.blogspot.com/-uEmqgUkgm_s/VcdFAlaXgEI/AAAAAAAACuY/xvoFMq2Qiko/s1600/150524-b-lam-tho-dc-5-dieu-duoi-day-6.jpg) +Năm tới, nếu thu nhập vẫn 6 triệu, tự tát vô mặt. Muốn tăng lương, hãy cống hiến. Đừng sợ người khác không thấy nỗ lực của mình. Đừng "khôn" kiểu "tôi có được gì không, làm nhiều cho lắm thì lương cũng vậy". Tư duy này khiến mình nghèo miết. Hãy cố gắng làm thêm giờ. Bạn phải làm thêm việc ở cơ quan, đến sớm hơn, về trễ hơn. Trong lúc làm việc, tập trung cao độ, nhận nhiều việc của công ty giao, tự mở thêm các mối quan hệ trong công việc, tay kẹp ĐT, tay đánh máy, vừa đi vừa chạy ... làm ầm ầm, ầm ầm vô. -_Ảnh: nguoiduatin_ +![Ảnh: nguoiduatin](https://3.bp.blogspot.com/-uEmqgUkgm_s/VcdFAlaXgEI/AAAAAAAACuY/xvoFMq2Qiko/s1600/150524-b-lam-tho-dc-5-dieu-duoi-day-6.jpg) -Khi còn trẻ, hãy ra ngoài nhiều hơn ở nhà. Hãy nhào vô xin người khác "bóc hết, lột sạch" khả năng của mình. Chỉ sợ bất tài nộp hồ sơ "xin việc", mà chả ai thèm cho, chả ai thèm bóc lột. Khi đã được bóc và lột hết, dù sau này đi đâu, làm gì, bạn đều cực kỳ thành công. Vì năng lực được trui rèn trong quá trình làm cho người khác. Sự chăm chỉ, tính kỷ luật, quen tay quen chân, quen ngáp, quen lười…cũng từ công việc mà ra. Mọi ông chủ vĩ đại đều từng là những người làm công ở vị trí thấp nhất. Họ đều rẽ trái trong khi mọi người rẽ phải. Họ có những quyết định không theo đám đông, không cam chịu sống một cuộc đời tầm thường, nhạt nhòa…rồi chết. +Khi còn trẻ, hãy ra ngoài nhiều hơn ở nhà. Hãy nhào vô xin người khác "bóc hết, lột sạch" khả năng của mình. Chỉ sợ bất tài nộp hồ sơ "xin việc", mà chả ai thèm cho, chả ai thèm bóc lột. Khi đã được bóc và lột hết, dù sau này đi đâu, làm gì, bạn đều cực kỳ thành công. Vì năng lực được trui rèn trong quá trình làm cho người khác. Sự chăm chỉ, tính kỷ luật, quen tay quen chân, quen ngáp, quen lười ... cũng từ công việc mà ra. Mọi ông chủ vĩ đại đều từng là những người làm công ở vị trí thấp nhất. Họ đều rẽ trái trong khi mọi người rẽ phải. Họ có những quyết định không theo đám đông, không cam chịu sống một cuộc đời tầm thường, nhạt nhòa ... rồi chết. -Còn những bạn thu nhập 6 triệu cũng túng thiếu, 20 triệu cũng đi vay mượn để tiêu dùng, thì thôi, cuộc đời họ chấm dứt giấc mơ lớn. Tiền nong cá nhân quản lý không được, thì làm sao mà quản trị tài chính một cơ nghiệp lớn? " +Còn những bạn thu nhập 6 triệu cũng túng thiếu, 20 triệu cũng đi vay mượn để tiêu dùng, thì thôi, cuộc đời họ chấm dứt giấc mơ lớn. Tiền nong cá nhân quản lý không được, thì làm sao mà quản trị tài chính một cơ nghiệp lớn? Tư duy thế nào thì nó ra số phận thế. Chúc các bạn năm mới Sức khoẻ để cống hiến, để thu nhập nhiều hơn. diff --git a/apps/blog/_posts/2016/02/sitemapduyetdevcom.md b/apps/blog/_posts/2016/02/sitemapduyetdevcom.md deleted file mode 100644 index 7e1e3bc7..00000000 --- a/apps/blog/_posts/2016/02/sitemapduyetdevcom.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: sitemap.duyetdev.com -date: '2016-02-03' -author: Duyet -tags: - - Side Project -modified_time: '2016-02-03T12:32:16.312+07:00' -thumbnail: https://1.bp.blogspot.com/-KdfFcR3DrHY/VrGQVFi50tI/AAAAAAAAPCE/jlt9NUoQTxo/s1600/service-icon.png -slug: /2016/02/sitemapduyetdevcom.html -category: News -description: sitemap.duyet.net được release nhằm mục đích là 1 global sitemap, tương lai sẽ có chức năng tự động scan cross-domain và tự sắp xếp lại hệ thống sitelink. ---- - -duyetdev.com có rất nhiều demo, project, application, chia thành nhiều nhánh, trên nhiều domain và subdomain. Mình cũng không thể nhớ hết được chúng, hiện tại chỉ có thể dựa vào [Google indexes](https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=site:duyet.net). - -[sitemap.duyet.net](https://sitemap.duyet.net) được release nhằm mục đích là 1 global sitemap, tương lai sẽ có chức năng tự động scan cross-domain và tự sắp xếp lại hệ thống sitelink. - -Bản beta: [https://sitemap.duyet.net](https://sitemap.duyet.net) - -[![](https://1.bp.blogspot.com/-KdfFcR3DrHY/VrGQVFi50tI/AAAAAAAAPCE/jlt9NUoQTxo/s320/service-icon.png)](https://sitemap.duyet.net) diff --git a/apps/blog/_posts/2019/03/7-thu-thuat-voi-resting-va-spreading.md b/apps/blog/_posts/2019/03/7-thu-thuat-voi-resting-va-spreading.md index 8ee3e6bb..65f7920d 100644 --- a/apps/blog/_posts/2019/03/7-thu-thuat-voi-resting-va-spreading.md +++ b/apps/blog/_posts/2019/03/7-thu-thuat-voi-resting-va-spreading.md @@ -1,5 +1,5 @@ --- -title: 7 thủ thuật với Resting và Spreading JavaScript Objects +title: Resting và Spreading JavaScript Objects date: '2019-03-27' author: Duyet category: Javascript diff --git a/apps/blog/_posts/2019/05/phuong-tien-cong-cong-san-francisco.md b/apps/blog/_posts/2019/05/phuong-tien-cong-cong-san-francisco.md index 9172c6f8..70c78f98 100644 --- a/apps/blog/_posts/2019/05/phuong-tien-cong-cong-san-francisco.md +++ b/apps/blog/_posts/2019/05/phuong-tien-cong-cong-san-francisco.md @@ -1,6 +1,7 @@ --- title: Đi lại bằng phương tiện công cộng ở San Francisco date: '2019-04-19' +featured: true author: Duyet category: Story tags: diff --git a/apps/blog/_posts/2019/08/ir-evaluation.md b/apps/blog/_posts/2019/08/ir-evaluation.md index ca7ebbc3..b6c124e9 100644 --- a/apps/blog/_posts/2019/08/ir-evaluation.md +++ b/apps/blog/_posts/2019/08/ir-evaluation.md @@ -1,6 +1,7 @@ --- title: Đánh giá hệ thống Information Retrieval date: '2019-08-31' +featured: true category: Data Engineer series: Information Retrieval tags: diff --git a/apps/blog/_posts/2019/08/ir-vector-space-model.md b/apps/blog/_posts/2019/08/ir-vector-space-model.md index c7392696..547c2d8c 100644 --- a/apps/blog/_posts/2019/08/ir-vector-space-model.md +++ b/apps/blog/_posts/2019/08/ir-vector-space-model.md @@ -1,6 +1,7 @@ --- title: Information Retrieval - Vector Space Model date: '2019-08-30' +featured: true category: Data Engineer series: Information Retrieval tags: diff --git a/apps/blog/_posts/2019/08/migrate-blogger-to-gatsby.md b/apps/blog/_posts/2019/08/migrate-blogger-to-gatsby.md index d84afa99..313fe4cd 100644 --- a/apps/blog/_posts/2019/08/migrate-blogger-to-gatsby.md +++ b/apps/blog/_posts/2019/08/migrate-blogger-to-gatsby.md @@ -1,6 +1,7 @@ --- title: Migrate Blogger sang Gatsby date: '2019-08-07' +featured: true author: Duyet category: Story tags: diff --git a/apps/blog/_posts/2020/05/spark-on-k8s.md b/apps/blog/_posts/2020/05/spark-on-k8s.md index 6d8faf3f..7f1de51a 100644 --- a/apps/blog/_posts/2020/05/spark-on-k8s.md +++ b/apps/blog/_posts/2020/05/spark-on-k8s.md @@ -1,6 +1,7 @@ --- title: 3 ways to run Spark on Kubernetes date: '2020-05-24' +featured: true author: Duyet category: Data Engineer tags: diff --git a/apps/blog/_posts/2020/05/tldr-why-rf.md b/apps/blog/_posts/2020/05/tldr-why-rf.md index e798dd51..eddde367 100644 --- a/apps/blog/_posts/2020/05/tldr-why-rf.md +++ b/apps/blog/_posts/2020/05/tldr-why-rf.md @@ -1,5 +1,5 @@ --- -title: TL;DR - khi nào nên sử dụng Random Forest thay vì Neural Network +title: TL;DR - Random Forest thay vì Neural Network date: '2020-05-01' author: Duyet category: Machine Learning diff --git a/apps/blog/_posts/2021/05/migrate-to-cloudflare-pages.md b/apps/blog/_posts/2021/05/migrate-to-cloudflare-pages.md index 085aae13..20fec097 100644 --- a/apps/blog/_posts/2021/05/migrate-to-cloudflare-pages.md +++ b/apps/blog/_posts/2021/05/migrate-to-cloudflare-pages.md @@ -1,10 +1,12 @@ --- title: Migrate to Cloudflare Pages date: '2021-05-01' +featured: true author: Duyet category: Web tags: - Web + - Side Project thumbnail: https://1.bp.blogspot.com/-fv8NJjM23lg/YI2Ontqi9JI/AAAAAAACBJY/u6pVcBulAh8feYttV2-FztBUISKdI8yhwCLcBGAsYHQ/s0/migrate-to-cloudflare-pages-0.png slug: /2021/05/migrate-to-cloudflare-pages.html description: Cloudflare just released the Pages, with the most generous free tier, it is all set to compete with Netlify on this front. I just to try it out in this blog. diff --git a/apps/blog/_posts/2021/11/rust-data-engineering.md b/apps/blog/_posts/2021/11/rust-data-engineering.md index f54b22ef..4d7cb046 100644 --- a/apps/blog/_posts/2021/11/rust-data-engineering.md +++ b/apps/blog/_posts/2021/11/rust-data-engineering.md @@ -1,6 +1,7 @@ --- title: 'Rust và Data Engineering? 🤔' date: '2021-11-27' +featured: true author: Duyet category: Data series: Rust Data Engineering diff --git a/apps/blog/_posts/2021/11/spark-node-decommission.md b/apps/blog/_posts/2021/11/spark-node-decommission.md index 18bf7449..ebfb2612 100644 --- a/apps/blog/_posts/2021/11/spark-node-decommission.md +++ b/apps/blog/_posts/2021/11/spark-node-decommission.md @@ -1,6 +1,7 @@ --- title: Spark on Kubernetes - better handling for node shutdown date: '2021-11-22' +featured: true author: Duyet category: Data tags: diff --git a/apps/blog/_posts/2022/02/rust-trait.md b/apps/blog/_posts/2022/02/rust-trait.md index 2abe699d..853fe3f7 100644 --- a/apps/blog/_posts/2022/02/rust-trait.md +++ b/apps/blog/_posts/2022/02/rust-trait.md @@ -1,6 +1,7 @@ --- title: 'Rust: Trait' date: '2022-02-13' +featured: true author: Duyet category: Rust 🦀 tags: diff --git a/apps/blog/_posts/2022/03/spark-kubernetes-at-fossil.md b/apps/blog/_posts/2022/03/spark-kubernetes-at-fossil.md index e8b83184..618e89ae 100644 --- a/apps/blog/_posts/2022/03/spark-kubernetes-at-fossil.md +++ b/apps/blog/_posts/2022/03/spark-kubernetes-at-fossil.md @@ -1,6 +1,7 @@ --- title: Spark on Kubernetes tại Fossil 🤔 date: '2022-03-09' +featured: true author: Duyet category: Data tags: diff --git a/apps/blog/_posts/2023/01/clickhouse.md b/apps/blog/_posts/2023/01/clickhouse.md index b360ad9d..d78f5098 100644 --- a/apps/blog/_posts/2023/01/clickhouse.md +++ b/apps/blog/_posts/2023/01/clickhouse.md @@ -2,6 +2,7 @@ title: 'Why ClickHouse Should Be the Go-To Choice for Your Next Data Platform?' date: '2023-01-10' author: Duyet +featured: true category: Data tags: - Data diff --git a/apps/blog/_posts/2023/01/data-engineering-rust-tools.md b/apps/blog/_posts/2023/01/data-engineering-rust-tools.md index 53c7ea99..5dc78304 100644 --- a/apps/blog/_posts/2023/01/data-engineering-rust-tools.md +++ b/apps/blog/_posts/2023/01/data-engineering-rust-tools.md @@ -1,6 +1,7 @@ --- title: 'Data Engineering Tools written in Rust' date: '2023-01-22' +featured: true author: Duyet category: Data series: Rust Data Engineering diff --git a/apps/blog/_posts/2023/05/migrate-blog-to-nextjs.md b/apps/blog/_posts/2023/05/migrate-blog-to-nextjs.md index c96e980b..ab98c708 100644 --- a/apps/blog/_posts/2023/05/migrate-blog-to-nextjs.md +++ b/apps/blog/_posts/2023/05/migrate-blog-to-nextjs.md @@ -1,6 +1,7 @@ --- title: 'Migrate (again) to Next.js 13 Pro Max' date: '2023-05-01' +featured: true author: Duyet category: Project tags: diff --git a/apps/blog/_posts/2023/06/fossil-data-platform-written-rust.md b/apps/blog/_posts/2023/06/fossil-data-platform-written-rust.md index a497a06f..fb3e7668 100644 --- a/apps/blog/_posts/2023/06/fossil-data-platform-written-rust.md +++ b/apps/blog/_posts/2023/06/fossil-data-platform-written-rust.md @@ -1,6 +1,7 @@ --- title: Fossil Data Platform Rewritten in Rust 🦀 date: '2023-06-18' +featured: true author: Duyet, Hieu category: Rust 🦀 series: Rust Data Engineering diff --git a/apps/blog/_posts/2023/09/nvim-setup-2023.md b/apps/blog/_posts/2023/09/nvim-setup-2023.md index 5209bce8..c310d2f7 100644 --- a/apps/blog/_posts/2023/09/nvim-setup-2023.md +++ b/apps/blog/_posts/2023/09/nvim-setup-2023.md @@ -1,6 +1,7 @@ --- title: My Neovim Setup in 2023 date: '2023-09-04' +featured: true author: Duyet category: Productivity tags: diff --git a/apps/blog/_posts/2024/03/clickhouse-monitoring.md b/apps/blog/_posts/2024/03/clickhouse-monitoring.md index 998607ec..ea882885 100644 --- a/apps/blog/_posts/2024/03/clickhouse-monitoring.md +++ b/apps/blog/_posts/2024/03/clickhouse-monitoring.md @@ -1,6 +1,7 @@ --- title: Monitoring ClickHouse on Kubernetes date: '2024-03-27' +featured: true author: Duyet category: Data series: ClickHouse on Kubernetes diff --git a/apps/blog/_posts/2024/03/clickhouse-on-kubernetes.md b/apps/blog/_posts/2024/03/clickhouse-on-kubernetes.md index 9faf5c4f..201b9615 100644 --- a/apps/blog/_posts/2024/03/clickhouse-on-kubernetes.md +++ b/apps/blog/_posts/2024/03/clickhouse-on-kubernetes.md @@ -1,6 +1,7 @@ --- title: ClickHouse on Kubernetes date: '2024-03-13' +featured: true author: Duyet category: Data series: ClickHouse on Kubernetes diff --git a/apps/blog/_posts/2024/06/clickhouse-replicatedreplacingmergetree.md b/apps/blog/_posts/2024/06/clickhouse-replicatedreplacingmergetree.md index 3b77736e..e839a6cd 100644 --- a/apps/blog/_posts/2024/06/clickhouse-replicatedreplacingmergetree.md +++ b/apps/blog/_posts/2024/06/clickhouse-replicatedreplacingmergetree.md @@ -1,6 +1,7 @@ --- title: ReplicatedReplacingMergeTree date: '2024-06-23' +featured: true author: Duyet series: ClickHouse on Kubernetes category: Data diff --git a/apps/blog/app/[year]/[month]/[slug]/content/content.tsx b/apps/blog/app/[year]/[month]/[slug]/content/content.tsx index c0ab86d7..a7cc49c9 100644 --- a/apps/blog/app/[year]/[month]/[slug]/content/content.tsx +++ b/apps/blog/app/[year]/[month]/[slug]/content/content.tsx @@ -7,12 +7,13 @@ import { cn } from '@duyet/libs/utils' import 'katex/dist/contrib/mhchem.min.js' import 'katex/dist/katex.min.css' +import { OldPostWarning } from './old-post-warning' import { Snippet } from './snippet' export default function Content({ post }: { post: Post }) { return ( <> -
+

{post.title}

+ +
+
+
+ + ) +} diff --git a/apps/blog/app/archives/page.tsx b/apps/blog/app/archives/page.tsx index facdb4ea..e6b83f3b 100644 --- a/apps/blog/app/archives/page.tsx +++ b/apps/blog/app/archives/page.tsx @@ -21,10 +21,10 @@ export default function Archives() { explore by the topics.
- {Object.keys(postsByYear) - .sort((a: string, b: string) => parseInt(b) - parseInt(a)) - .map((year: string) => ( - + {Object.entries(postsByYear) + .sort(([a], [b]) => parseInt(b) - parseInt(a)) + .map(([year, posts]) => ( + ))}
diff --git a/apps/blog/app/archives2/page.tsx b/apps/blog/app/archives2/page.tsx deleted file mode 100644 index 747a52b3..00000000 --- a/apps/blog/app/archives2/page.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import Link from 'next/link' - -import Container from '@duyet/components/Container' -import Grid from '@duyet/components/Grid' -import { getAllPosts } from '@duyet/libs/getPost' - -type Params = Promise> - -async function getPosts(params: Params) { - const { page } = await params - const pageNumber = page ? parseInt(page) - 1 : 0 - - return getAllPosts( - [ - 'date', - 'slug', - 'title', - 'excerpt', - 'thumbnail', - 'category', - 'category_slug', - ], - pageNumber * 10 + 10, - ) -} - -export default async function Archives({ params }: { params: Params }) { - const posts = await getPosts(params) - - return ( - - - -
- See more -
- -
- ) -} diff --git a/apps/blog/app/archives2/layout.tsx b/apps/blog/app/featured/layout.tsx similarity index 59% rename from apps/blog/app/archives2/layout.tsx rename to apps/blog/app/featured/layout.tsx index 51a294a1..d493beb9 100644 --- a/apps/blog/app/archives2/layout.tsx +++ b/apps/blog/app/featured/layout.tsx @@ -1,11 +1,13 @@ -import Header from '@duyet/components/Header' import * as React from 'react' +import Container from '@duyet/components/Container' +import Header from '@duyet/components/Header' + export default function Layout({ children }: { children: React.ReactNode }) { return ( <> -
- {children} +
+ {children} ) } diff --git a/apps/blog/app/featured/page.tsx b/apps/blog/app/featured/page.tsx new file mode 100644 index 00000000..8293df41 --- /dev/null +++ b/apps/blog/app/featured/page.tsx @@ -0,0 +1,36 @@ +import Link from 'next/link' + +import Container from '@duyet/components/Container' +import { getPostsByAllYear } from '@duyet/libs/getPost' +import { YearPost } from '../../components/year-post' + +export default function Archives() { + const postsByYear = getPostsByAllYear( + ['slug', 'title', 'date', 'category', 'featured'], + -1, + true, + ) + + return ( + +
+ This page highlights featured blog posts. You can also explore{' '} + + all posts + {' '} + or{' '} + + by the topics + + . +
+
+ {Object.entries(postsByYear) + .sort(([a], [b]) => parseInt(b) - parseInt(a)) + .map(([year, posts]) => ( + + ))} +
+
+ ) +} diff --git a/apps/blog/app/page.tsx b/apps/blog/app/page.tsx index e26a521b..65282d88 100644 --- a/apps/blog/app/page.tsx +++ b/apps/blog/app/page.tsx @@ -3,7 +3,6 @@ import Link from 'next/link' import Container from '@duyet/components/Container' import Header from '@duyet/components/Header' import { getPostsByAllYear } from '@duyet/libs/getPost' -import { Latest } from '../components/latest' import { YearPost } from '../components/year-post' export default async function Page() { @@ -20,26 +19,28 @@ export default async function Page() { <>
- -
Lists all {postCount} posts of the past {pastYears} years of blogging. You can jump straight to the{' '} /feed {' '} - for latest posts or also explore{' '} + for latest posts, also explore{' '} by the topics + {' '} + or{' '} + + my featured posts .
- {Object.keys(postsByYear) - .sort((a: string, b: string) => parseInt(b) - parseInt(a)) - .map((year: string) => ( - + {Object.entries(postsByYear) + .sort(([a], [b]) => parseInt(b) - parseInt(a)) + .map(([year, posts]) => ( + ))}
diff --git a/apps/blog/components/year-post.tsx b/apps/blog/components/year-post.tsx index 7bbafbbd..559064ed 100644 --- a/apps/blog/components/year-post.tsx +++ b/apps/blog/components/year-post.tsx @@ -1,19 +1,19 @@ +/* eslint-disable @typescript-eslint/no-unsafe-assignment -- IsFeatured */ + import Link from 'next/link' import type { Post } from '@duyet/interfaces' import { dateFormat } from '@duyet/libs/date' -import { getPostsByYear } from '@duyet/libs/getPost' import { cn } from '@duyet/libs/utils' export interface YearPostProps { year: number + posts: Post[] className?: string } -export function YearPost({ year, className }: YearPostProps) { - const posts = getPostsByYear(year, ['slug', 'title', 'date', 'category']) - - if (!posts.length) { +export function YearPost({ year, posts, className }: YearPostProps) { + if (!posts?.length) { return null } @@ -40,10 +40,11 @@ export function YearPost({ year, className }: YearPostProps) { {post.title} +
))} @@ -61,3 +62,15 @@ function IsNewPost({ date }: { date: Date | undefined }) { return New } + +function IsFeatured({ featured }: { featured: boolean }) { + if (!featured) { + return null + } + + return ( + + Featured + + ) +} diff --git a/packages/interfaces/src/post.ts b/packages/interfaces/src/post.ts index 8a04bbca..35d296e6 100644 --- a/packages/interfaces/src/post.ts +++ b/packages/interfaces/src/post.ts @@ -6,6 +6,7 @@ export type Post = { category_slug: string; tags: string[]; tags_slug: string[]; + featured: boolean; thumbnail?: string; author?: string; content?: string; diff --git a/packages/libs/getPost.ts b/packages/libs/getPost.ts index c55c6f85..4be54362 100644 --- a/packages/libs/getPost.ts +++ b/packages/libs/getPost.ts @@ -64,6 +64,7 @@ export function getPostByPath(fullPath: string, fields: string[] = []): Post { tags: [], tags_slug: [], snippet: '', + featured: false, } // Ensure only the minimal needed data is exposed @@ -121,6 +122,10 @@ export function getPostByPath(fullPath: string, fields: string[] = []): Post { post['snippet'] = data.snippet || '' } + if (field === 'featured') { + post['featured'] = Boolean(data.featured) || false + } + if (typeof data[field] !== 'undefined') { post[field] = data[field] } @@ -178,6 +183,16 @@ export function getPostsByCategory( .sort((post1, post2) => (post1.date > post2.date ? -1 : 1)) } +/** + * Retrieves all unique tags from all posts and counts their occurrences. + * + * This function scans through all posts in the blog, extracts their tags, + * and creates a count of how many times each tag appears across all posts. + * + * @returns {TagCount} An object where each key is a unique tag and its value + * is the number of times that tag appears across all posts. The type TagCount + * is defined as Record. + */ export function getAllTags(): TagCount { const paths = getPostPaths() const posts = paths.map((path) => getPostByPath(path, ['tags'])) @@ -198,6 +213,16 @@ export function getAllTags(): TagCount { ) } +/** + * Retrieves posts that have the specified tag. + * + * @param tag - The tag to filter posts by. + * @param fields - An optional array of fields to include in the returned posts. + * + * @returns An array of posts that have the specified tag. The posts are sorted by date in descending order. + * + * @throws Will throw an error if the tag format is invalid. + */ export function getPostsByTag(tag: string, fields: string[] = []): Post[] { const paths = getPostPaths() @@ -211,10 +236,15 @@ export function getPostsByTag(tag: string, fields: string[] = []): Post[] { export function getPostsByAllYear( fields: string[] = [], - yearLimit: number = -1 + yearLimit: number = -1, + featured?: boolean ): Record { - const extraFields = [...fields, 'date'] - const allPosts = getAllPosts(extraFields) + const extraFields = [...fields, 'date', 'featured'] + let allPosts = getAllPosts(extraFields) + + if (featured !== undefined) { + allPosts = allPosts.filter((post) => post.featured === true) + } // Post by year const postsByYear = allPosts.reduce( @@ -258,7 +288,7 @@ export function getPostsByAllYear( } export function getPostsByYear(year: number, fields: string[] = []) { - const extraFields = [...fields, 'date'] + const extraFields = [...fields, 'date', 'featured'] const postByYears = getPostsByAllYear(extraFields) return postByYears[year] || [] From 8e23b264adf6abc6ae745295c39b65dfb6a662bb Mon Sep 17 00:00:00 2001 From: Duyet Le Date: Tue, 12 Nov 2024 01:36:44 +0700 Subject: [PATCH 2/3] chore(ui): temp remove year page --- apps/blog/app/[year]/page.tsx | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 apps/blog/app/[year]/page.tsx diff --git a/apps/blog/app/[year]/page.tsx b/apps/blog/app/[year]/page.tsx deleted file mode 100644 index f8435464..00000000 --- a/apps/blog/app/[year]/page.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import YearList from '@duyet/components/YearList' -import { getPostsByAllYear } from '@duyet/libs/getPost' -import { YearPost } from '../../components/year-post' - -// Dynamic segments not included in generateStaticParams will return a 404. -// https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams -export const dynamicParams = false - -interface YearProps { - params: Promise<{ - year: number - }> -} - -export default async function YearPage({ params }: YearProps) { - const { year } = await params - - return ( - <> - - -
- -
- - ) -} - -export async function generateStaticParams() { - const posts = getPostsByAllYear() - - return Object.keys(posts).map((year) => ({ - year, - })) -} From 9e1c6609a4c4039fea2cb3ea88b3f045729c9119 Mon Sep 17 00:00:00 2001 From: Duyet Le Date: Tue, 12 Nov 2024 01:40:05 +0700 Subject: [PATCH 3/3] fix(blog): unnecessary optional chain on a non-nullish value --- apps/blog/components/year-post.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/blog/components/year-post.tsx b/apps/blog/components/year-post.tsx index 559064ed..9524385a 100644 --- a/apps/blog/components/year-post.tsx +++ b/apps/blog/components/year-post.tsx @@ -13,7 +13,7 @@ export interface YearPostProps { } export function YearPost({ year, posts, className }: YearPostProps) { - if (!posts?.length) { + if (!posts.length) { return null }