-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrss.xml
More file actions
7404 lines (7161 loc) · 502 KB
/
rss.xml
File metadata and controls
7404 lines (7161 loc) · 502 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
<channel>
<title><![CDATA[Fezcodex]]></title>
<description><![CDATA[A personal blog by Ahmed Samil Bulbul]]></description>
<link>https://fezcode.com</link>
<image>
<url>https://fezcode.com/logo512.png</url>
<title>Fezcodex</title>
<link>https://fezcode.com</link>
</image>
<generator>RSS for Node</generator>
<lastBuildDate>Thu, 12 Feb 2026 22:23:32 GMT</lastBuildDate>
<atom:link href="https://fezcode.com/rss.xml" rel="self" type="application/rss+xml"/>
<pubDate>Thu, 12 Feb 2026 22:23:32 GMT</pubDate>
<copyright><![CDATA[2026 Ahmed Samil Bulbul]]></copyright>
<language><![CDATA[en]]></language>
<managingEditor><![CDATA[samil.bulbul@gmail.com (Ahmed Samil Bulbul)]]></managingEditor>
<webMaster><![CDATA[samil.bulbul@gmail.com (Ahmed Samil Bulbul)]]></webMaster>
<ttl>60</ttl>
<item>
<title><![CDATA[Linux vs. Unix: The Kernel Wars and the Philosophy of Modular Design]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/linux-vs-unix-the-kernel-wars</link>
<guid isPermaLink="false">https://fezcode.com/blog/linux-vs-unix-the-kernel-wars</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Sun, 08 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Linux vs. Unix: The Kernel Wars and the Philosophy of Modular Design</h1>
<p><a href="https://fezcode.com/blog/linux-vs-unix-the-kernel-wars">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[The Halo Effect: Why We Trust Idiots with Good Hair]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/the-halo-effect</link>
<guid isPermaLink="false">https://fezcode.com/blog/the-halo-effect</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Sun, 08 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<blockquote>
<p><strong>⚠️ Warning: Objects in Mirror Are Less Perfect Than They Appear</strong></p>
<p>If you think this blog post is genius just because the font is nice and the layout is clean, you are currently being blinded by the very thing I'm about to roast.
Welcome to the glow.</p>
</blockquote>
<p><a href="https://fezcode.com/blog/the-halo-effect">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Mastering Git Worktrees: Parallel Development with AI Agents]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/mastering-git-worktrees-and-ai</link>
<guid isPermaLink="false">https://fezcode.com/blog/mastering-git-worktrees-and-ai</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Sun, 08 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Mastering Git Worktrees: Parallel Development with AI Agents</h1>
<p><a href="https://fezcode.com/blog/mastering-git-worktrees-and-ai">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Sartre & Camus - Existentialism and Absurdism]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/existentialism</link>
<guid isPermaLink="false">https://fezcode.com/blog/existentialism</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Sat, 07 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Philosophy 101: Sartre & Camus - Existentialism and Absurdism</h1>
<p><a href="https://fezcode.com/blog/existentialism">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Wittgenstein - The Fly in the Fly-Bottle]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/wittgenstein</link>
<guid isPermaLink="false">https://fezcode.com/blog/wittgenstein</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Sat, 07 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Philosophy 101: Wittgenstein - The Fly in the Fly-Bottle</h1>
<p><a href="https://fezcode.com/blog/wittgenstein">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Nietzsche - The Death of God and the Übermensch]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/nietzsche</link>
<guid isPermaLink="false">https://fezcode.com/blog/nietzsche</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Fri, 06 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Philosophy 101: Nietzsche - The Death of God and the Übermensch</h1>
<p><a href="https://fezcode.com/blog/nietzsche">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Heidegger - Being and Time]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/heidegger</link>
<guid isPermaLink="false">https://fezcode.com/blog/heidegger</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Fri, 06 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Philosophy 101: Heidegger - Being and Time</h1>
<p><a href="https://fezcode.com/blog/heidegger">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Understanding Database Normalization: The Path to Third Normal Form (3NF)]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/understanding-database-normalization-3nf</link>
<guid isPermaLink="false">https://fezcode.com/blog/understanding-database-normalization-3nf</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Fri, 06 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Database Normalization: A Clear Guide to 1NF, 2NF, and 3NF</h1>
<p><a href="https://fezcode.com/blog/understanding-database-normalization-3nf">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[CQRS: Command Query Responsibility Segregation in Modern Architecture]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/cqrs-in-go-for-geniuses</link>
<guid isPermaLink="false">https://fezcode.com/blog/cqrs-in-go-for-geniuses</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Fri, 06 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>CQRS: Command Query Responsibility Segregation in Modern Architecture</h1>
<p><a href="https://fezcode.com/blog/cqrs-in-go-for-geniuses">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Kierkegaard - The Leap of Faith]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/kierkegaard</link>
<guid isPermaLink="false">https://fezcode.com/blog/kierkegaard</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Thu, 05 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Philosophy 101: Kierkegaard - The Leap of Faith</h1>
<p><a href="https://fezcode.com/blog/kierkegaard">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Hyrum's Law: Why Your Bug Fix Broke My Spacebar Heating Workflow]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/hyrums-law</link>
<guid isPermaLink="false">https://fezcode.com/blog/hyrums-law</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Thu, 05 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<blockquote>
<p><strong>⚠️ Warning: Behavioral Changes Ahead</strong></p>
<p>If you rely on the specific way this blog post is formatted to scrape it for your AI training data, I apologize in advance.
By reading this, you are effectively becoming an example of the very law I am about to explain.</p>
</blockquote>
<p><a href="https://fezcode.com/blog/hyrums-law">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Hegel - The Dialectic and World Spirit]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/hegel</link>
<guid isPermaLink="false">https://fezcode.com/blog/hegel</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Wed, 04 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Philosophy 101: Hegel - The Dialectic and World Spirit</h1>
<p><a href="https://fezcode.com/blog/hegel">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Schopenhauer - The Will and Pessimism]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/schopenhauer</link>
<guid isPermaLink="false">https://fezcode.com/blog/schopenhauer</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Wed, 04 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Philosophy 101: Schopenhauer - The Will and Pessimism</h1>
<p><a href="https://fezcode.com/blog/schopenhauer">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[René Descartes - The Father of Modern Philosophy]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/descartes</link>
<guid isPermaLink="false">https://fezcode.com/blog/descartes</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Tue, 03 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Philosophy 101: René Descartes - The Father of Modern Philosophy</h1>
<p><a href="https://fezcode.com/blog/descartes">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Immanuel Kant - The Thing-in-Itself]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/kant</link>
<guid isPermaLink="false">https://fezcode.com/blog/kant</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Tue, 03 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Philosophy 101: Immanuel Kant - The Thing-in-Itself</h1>
<p><a href="https://fezcode.com/blog/kant">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Ethics - What Should We Do?]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/ethics</link>
<guid isPermaLink="false">https://fezcode.com/blog/ethics</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Mon, 02 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Philosophy 101: Ethics - What Should We Do?</h1>
<p><a href="https://fezcode.com/blog/ethics">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[The Big Three - Socrates, Plato, Aristotle]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/the-big-three</link>
<guid isPermaLink="false">https://fezcode.com/blog/the-big-three</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Mon, 02 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Philosophy 101: The Big Three - Socrates, Plato, Aristotle</h1>
<p><a href="https://fezcode.com/blog/the-big-three">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Al-Ghazali - The Incoherence of the Philosophers]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/al-ghazali</link>
<guid isPermaLink="false">https://fezcode.com/blog/al-ghazali</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Mon, 02 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Philosophy 101: Al-Ghazali - The Incoherence of the Philosophers</h1>
<p><a href="https://fezcode.com/blog/al-ghazali">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Introduction - The Examined Life]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/introduction</link>
<guid isPermaLink="false">https://fezcode.com/blog/introduction</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Sun, 01 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Philosophy 101: Introduction - The Examined Life</h1>
<p><a href="https://fezcode.com/blog/introduction">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Logic - The Toolbox]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/logic-and-arguments</link>
<guid isPermaLink="false">https://fezcode.com/blog/logic-and-arguments</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Sun, 01 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Philosophy 101: Logic - The Toolbox</h1>
<p><a href="https://fezcode.com/blog/logic-and-arguments">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Epistemology - How Do You Know That?]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/epistemology</link>
<guid isPermaLink="false">https://fezcode.com/blog/epistemology</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Sun, 01 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Philosophy 101: Epistemology - How Do You Know That?</h1>
<p><a href="https://fezcode.com/blog/epistemology">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Metaphysics - What is Real?]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/metaphysics</link>
<guid isPermaLink="false">https://fezcode.com/blog/metaphysics</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Sun, 01 Feb 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Philosophy 101: Metaphysics - What is Real?</h1>
<p><a href="https://fezcode.com/blog/metaphysics">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Architecting Trust: 5 Patterns to Prevent Insider Threats]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/architecting-trust-preventing-insider-threats</link>
<guid isPermaLink="false">https://fezcode.com/blog/architecting-trust-preventing-insider-threats</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Fri, 23 Jan 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Architecting Trust: 5 Patterns to Prevent Insider Threats</h1>
<p><a href="https://fezcode.com/blog/architecting-trust-preventing-insider-threats">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Deep Link Configuration: Achieving a Global Parameter Observer in React]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/deep-link-configuration-with-url-parameters</link>
<guid isPermaLink="false">https://fezcode.com/blog/deep-link-configuration-with-url-parameters</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Wed, 21 Jan 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Deep Link Configuration: Achieving a Global Parameter Observer in React</h1>
<p><a href="https://fezcode.com/blog/deep-link-configuration-with-url-parameters">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Introducing Fezluxe: A Study in Refined Architectural Elegance]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/introducing-fezluxe-refined-architectural-elegance</link>
<guid isPermaLink="false">https://fezcode.com/blog/introducing-fezluxe-refined-architectural-elegance</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Tue, 20 Jan 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Introducing Fezluxe: A Study in Refined Architectural Elegance</h1>
<p><a href="https://fezcode.com/blog/introducing-fezluxe-refined-architectural-elegance">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[The FIFA Paradox: Why We Spend 14 Hours Playing Games We Hate]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/gun-and-ball</link>
<guid isPermaLink="false">https://fezcode.com/blog/gun-and-ball</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Mon, 19 Jan 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<blockquote>
<p><strong>⚠️ Disclaimer: Open Analysis</strong></p>
<p>This post explores game data using statistical analysis. Please note that while I am an experienced engineer,
I am not a specialized Data Scientist. I have made the code and data available <a href="https://github.com/fezcode/Project-Touch-Grass">in GitHub</a> for transparency.
If you find errors in the methodology or want to improve the model, I welcome your feedback and pull requests.</p>
</blockquote>
<p><a href="https://fezcode.com/blog/gun-and-ball">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Dying is Easy, Comedy is Statistically Impossible: An IMDbayes Analysis]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/what-genre-should-i-watch</link>
<guid isPermaLink="false">https://fezcode.com/blog/what-genre-should-i-watch</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Sun, 18 Jan 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<blockquote>
<p>This analysis was built by a Software Engineer relying on 8-year-old university memories of statistics.
If the math looks wrong, just assume it's a feature, not a bug.
You can always contact me.</p>
</blockquote>
<h2>Deconstructing Hollywood: A Data Science Journey from Raw Data to p99 Insights</h2>
<p>As software engineers, we are used to deterministic systems. If <code>a = b</code>, then a equals b.
Data Science, however, deals with probability, distributions, and noise.
It's less about "<strong>what is the answer</strong>" and more about "<strong>how confident are we in this trend?</strong>"</p>
<p>Recently, I wanted to bridge my engineering background with data science to answer a simple pop-culture question:
<strong>How do different movie genres actually perform?</strong></p>
<p>Are "<strong>Action</strong>" movies inherently rated lower than "<strong>Dramas</strong>"? Is it harder to make a masterpiece "<strong>Horror</strong>" movie than a masterpiece "<strong>Biography</strong>"?</p>
<p>To answer this, I didn't just want to run a script; I wanted to build a production-grade Data Science lab?!. (/s)
This post details the entire journey—from choosing the modern Python stack and engineering the data pipeline to defining
the statistical metrics that reveal the "truth" behind average ratings.</p>
<h2>Part 1: The Engineering Foundation</h2>
<p>A data project is only as good as its environment. I wanted a setup that was fast, reproducible, and clean.</p>
<h3>The Stack Decision</h3>
<p>I chose Python because it is the undisputed <strong><a href="/vocab/lingua-franca">lingua franca</a></strong> of data science.
The ecosystem (Pandas for data crunching, Seaborn for visualization) is unmatched.</p>
<h3>The Package Manager: Why <code>uv</code>?</h3>
<p>Traditionally, Python data science relies on Conda because it manages complex C-library dependencies used by
math libraries like NumPy. However, Conda can be slow and bloated.</p>
<p>For this project, I chose <code>uv</code>.</p>
<p><code>uv</code> is a modern, blazing-fast Python package manager written in Rust.
It replaces <code>pip</code>, <code>poetry</code>, and <code>virtualenv</code>. It resolves dependencies in milliseconds and creates deterministic environments instantly.
For a project relying on standard wheels like Pandas, <code>uv</code> provides a vastly superior developer experience.</p>
<pre><code class="language-bash"># Setting up the environment took seconds
$ uv init movie-analysis
$ uv python install 3.10
$ uv add pandas matplotlib seaborn scipy jupyter ipykernel
</code></pre>
<p>Then connected VS Code to this <code>.venv</code> created by <code>uv</code>, giving me a robust Jupyter Notebook experience right in the IDE.</p>
<h2>Part 2: The Data Pipeline (ETL)</h2>
<p>I needed data with genres, votes, and ratings, went straight to the source: the <strong>IMDb Non-Commercial Datasets</strong>.</p>
<p>Then I faced a classic data engineering challenge: these are massive TSV (Tab Separated Values) files.
Loading the entirety of IMDb into RAM on a laptop is a bad idea.</p>
<p>Solution? Build a Python ETL script to handle ingestion smartly:</p>
<ol>
<li><strong>Stream & Filter</strong>: used Pandas to read the raw files in chunks, filtering immediately for <code>titleType == 'movie'</code> and excluding older films. This kept memory usage low.</li>
<li><strong>Merge</strong>: joined the <code>title.basics</code> (genres/names) with <code>title.ratings</code> (scores/votes) on their unique IDs.</li>
<li><strong>The "Explode"</strong>: This was the crucial data transformation step. IMDb lists genres as a single string: "Action,Adventure,Sci-Fi". To analyze by category, I had to split that string and "explode" the dataset, duplicating the movie row for each genre it belongs to.</li>
</ol>
<pre><code class="language-python"># Transforming "Action,Comedy" into two distinct analysis rows
df['genres'] = df['genres'].str.split(',')
df_exploded = df.explode('genres')
</code></pre>
<h2>Part 3: The Science (Beyond Averages)</h2>
<p>With clean data in hand, we moved into a Jupyter Notebook for Exploratory Data Analysis (EDA).</p>
<h3>1. Removing the Noise (The Long Tail)</h3>
<p>If you average every movie on IMDb, your data is polluted by home videos with 5 votes from the director's family.
In statistics, vote counts often follow a <a href="/vocab/power-law">"Power Law"</a> or long-tail distribution.</p>
<p>To analyze global sentiment, we had to filter out the noise. We set a threshold, dropping any movie with fewer than 100 votes.
This ensured our statistical analysis was based on titles with a minimum level of public engagement.</p>
<h3>2. Visualizing the Truth (The Box Plot)</h3>
<p>A simple average rating is misleading. If a genre has many <code>1/10</code>s and many <code>10/10</code>s, the average is <code>5/10</code> - but that doesn't tell the story of how polarizing it is.</p>
<p>I used a <a href="/vocab/box-plot">Box Plot</a> to visualize the distribution. It shows the median (the center line), the Interquartile Range (the colored box containing the middle 50% of data), and outliers (the dots).</p>
<p><img src="/images/posts/wgsiw/boxplot.png" alt="The Box Plot"></p>
<p><strong>Initial Observations:</strong></p>
<ul>
<li><strong>Documentary/Biography</strong>: High medians, compact boxes. They are consistently rated highly.</li>
<li><strong>Horror</strong>: The lowest median and a wide spread. It’s very easy to make a bad horror movie.</li>
</ul>
<h3>3. The Metrics: Weighted Ratings & p99</h3>
<p>To get deeper insights, I needed better math than simple means.</p>
<h4>Metric A: The Weighted Rating (Bayesian Average)</h4>
<p>How do you compare a movie with a 9.0 rating and 105 votes against an 8.2 rating with 500,000 votes? The latter score is more statistically significant.</p>
<p>I adopted IMDb's own <strong>Weighted Rating</strong> formula. This "Bayesian average" pulls a movie's rating toward the global average $C$ if it has few votes $v$,
only allowing it to deviate as it gains more votes over a threshold $m$.</p>
<p>$$
WR = \left( \frac{v}{v+m} \cdot R \right) + \left( \frac{m}{v+m} \cdot C \right)
$$</p>
<p><strong>Where:</strong></p>
<ul>
<li>$R$ = Average Rating of the movie</li>
<li>$v$ = Number of votes for the movie</li>
<li>$m$ = Minimum votes required to be listed (Threshold: 100)</li>
<li>$C$ = Mean vote across the whole dataset</li>
</ul>
<p>This provided a fair "Quality Score" for every movie.</p>
<h4>Metric B: The p99 Ceiling</h4>
<p>I wanted to know the "potential" of a genre. Even if most Action movies are mediocre, how good are the very best ones?</p>
<p>For this, I calculated the <a href="/vocab/p99">99th Percentile (p99)</a> rating for each genre. This is the rating value below which 99% of the genre falls.
It represents the elite tier, the "Masterpiece Ceiling."</p>
<h3>Part 4: The Deductions (The Gap Analysis)</h3>
<p>By combining the Average Weighted Rating (the typical experience) and the p99 Rating (the elite potential), we created a "Gap Analysis" chart.</p>
<p>The dark green bar is the average quality. The total height of the bar is the p99 ceiling. The light green area represents the "Masterpiece Gap".</p>
<p><img src="/images/posts/wgsiw/gap.png" alt="Masterpiece Gap"></p>
<h4>The Data Science Deductions</h4>
<p>This single chart reveals the "personality" of every genre:</p>
<ol>
<li><p><strong>The "Safe Bets" (Documentary, History, Biography)</strong>:
They have very high averages (tall dark bars) and a small gap to the ceiling.
<em>Deduction</em>: It is difficult to make a poorly rated documentary. Audience selection bias likely plays a role here
(people only watch docs on topics they already like).</p>
</li>
<li><p><strong>The "High Risk / High Reward" (Horror, Sci-Fi)</strong>: They have the lowest averages (short dark bars),
indicating the typical output is poor. However, their p99 ceilings remain high.
<em>Deduction</em>: The gap is huge. It is incredibly difficult to execute these genres well, but when it's done right
(e.g., Alien, The Exorcist), they are revered just as highly as dramas.</p>
</li>
<li><p><strong>The Animation Anomaly</strong>: Animation has a high average and a very high ceiling.
<em>Deduction</em>: Statistically, this is perhaps the most consistently high-quality genre in modern cinema.</p>
</li>
</ol>
<h2>Conclusion</h2>
<p>This project demonstrated that with a solid engineering setup using modern tools like <code>uv</code>,
and by applying statistical concepts beyond simple averages, we can uncover nuanced truths hidden in raw data.
Averages tell you what is probable; distributions and percentiles tell you what is possible.</p>
<h3>Question A: Which genre is "easier" to make? (Action vs. Drama vs. Comedy)</h3>
<p><strong>The Data Verdict:</strong> It is significantly "easier" to make an acceptable <strong>Drama</strong> than an acceptable <strong>Action</strong> or <strong>Comedy</strong> movie.</p>
<ul>
<li><strong>Evidence:</strong> Look at the box plot, kindly.<ul>
<li><strong>Drama</strong> has a high median and a "tight" box (smaller Interquartile Range). This means even "average" Dramas are usually rated around 6.5–7.0. The "floor" is high.</li>
<li><strong>Action</strong> has a lower median. Action movies require budget, stunts, and effects. If those look cheap, the rating tanks immediately.
A bad drama is just "boring" (5/10); a bad action movie looks "broken" (3/10).</li>
<li><strong>Comedy</strong> is arguably the <em>hardest</em> to get a high rating for. Humor is subjective.
If a joke lands for 50% of the audience but annoys the other 50%, the rating averages out to a 5.0.
<strong>Drama is universal; Comedy is divisive</strong>.</li>
</ul>
</li>
</ul>
<h3>Question B: Should I use lower search bounds for Comedy compared to Drama?</h3>
<p><strong>The Data Verdict:</strong> <strong>YES. Absolutely.</strong></p>
<ul>
<li><strong>The "Genre Inflation" Factor:</strong> Users rate genres differently. A <strong>7.0</strong> in Horror or Comedy is effectively an <strong>8.0</strong> in Drama or Biography.<ul>
<li><strong>The Strategy:</strong> If you filter for <code>Rating > 7.5</code>, you will see hundreds of Biographies, but you will filter out some of the funniest Comedies ever made (which often sit at 6.8 - 7.2).</li>
<li><strong>Action/Comedy Filter:</strong> Set your threshold to <strong>6.5</strong>.</li>
<li><strong>Drama/Doc Filter:</strong> Set your threshold to <strong>7.5</strong>.</li>
</ul>
</li>
</ul>
<h3>Question C: The "Blindfold Test" (Documentary vs. Sci-Fi)</h3>
<p><strong>The Data Verdict:</strong> You will be statistically safer picking the <strong>Documentary</strong>.</p>
<ul>
<li><p><strong>The "Floor" Concept:</strong> Look at the "Whiskers" (the lines extending from the boxes) on the box plot.</p>
<ul>
<li><strong>Sci-Fi:</strong> The bottom whisker goes deep down (towards 1.0 or 2.0). There is a significant statistical probability that a random Sci-Fi movie is unwatchable <em>garbage</em>.</li>
<li><strong>Documentary:</strong> The bottom whisker rarely dips below 5.0 or 6.0.</li>
</ul>
</li>
<li><p><strong>The Psychology:</strong></p>
<ul>
<li><strong>Documentaries</strong> are usually made by passionate experts about specific topics. They rarely "fail" completely.</li>
<li><strong>Sci-Fi</strong> is high-risk. It attempts to build new worlds. When that fails, it looks ridiculous, leading to "hate-watching" and 1-star reviews.</li>
<li><strong>Conclusion:</strong> If you are tired and just want a "guaranteed decent watch" (Low Variance), pick <strong>Documentary</strong>. If you want to gamble for a potentially mind-blowing experience (High Variance), pick <strong>Sci-Fi</strong>.</li>
</ul>
</li>
</ul>
<p>You can check the project here: <a href="https://github.com/fezcode/IMDbayes">IMDbayes</a></p>
<p><a href="https://fezcode.com/blog/what-genre-should-i-watch">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Upgrading Debian 11 to 13: The Safe Path]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/debian-upgrade-path</link>
<guid isPermaLink="false">https://fezcode.com/blog/debian-upgrade-path</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Mon, 12 Jan 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Upgrading Debian 11 to 13: The Safe Path</h1>
<p>So, you're on Debian 11 (Bullseye) and want to jump to Debian 13 (Trixie). Maybe you saw some shiny new package, or you just want to be on the cutting edge (or as cutting edge as Debian gets).</p>
<p>But here's the catch: <strong>You can't skip a version.</strong></p>
<p>Debian upgrades are designed to be sequential. Jumping from 11 straight to 13 is a recipe for a broken system (frankstein packages, dependency hell, the works). The safe path is <strong>11 → 12 → 13</strong>.</p>
<p>Here is the quick gist of how to do it properly.</p>
<h2>Phase 1: Bullseye (11) to Bookworm (12)</h2>
<p>First, make sure your current system is fully updated and clean.</p>
<pre><code class="language-bash"># Clean up any broken sources first!
# If you have 404 errors on backports, comment them out in /etc/apt/sources.list
sudo apt update
sudo apt full-upgrade -y
</code></pre>
<p>Now, switch your sources to Bookworm.</p>
<pre><code class="language-bash">sudo sed -i 's/bullseye/bookworm/g' /etc/apt/sources.list
</code></pre>
<p>Run the upgrade. This is the big one.</p>
<pre><code class="language-bash">sudo apt update
sudo apt full-upgrade -y
</code></pre>
<p><strong>Reboot your system.</strong></p>
<h2>Phase 2: Bookworm (12) to Trixie (13)</h2>
<p>Welcome back. You are now on Debian 12. Let's keep going.</p>
<p>Update your sources to Trixie.</p>
<pre><code class="language-bash">sudo sed -i 's/bookworm/trixie/g' /etc/apt/sources.list
</code></pre>
<p>Run the upgrade again.</p>
<pre><code class="language-bash">sudo apt update
sudo apt full-upgrade -y
</code></pre>
<h2>Phase 3: Cleanup</h2>
<p>You made it. Now clean up the leftovers.</p>
<pre><code class="language-bash">sudo apt autoremove -y
sudo reboot
</code></pre>
<h2>Verification</h2>
<p>When you're back, check your version:</p>
<pre><code class="language-bash">cat /etc/debian_version
# Should output 13.x (or testing/trixie)
</code></pre>
<p>And that's it. You have successfully time traveled.</p>
<p><a href="https://fezcode.com/blog/debian-upgrade-path">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Steganography: Hiding Secrets in Plain Sight with LSB]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/steganography-lsb-deep-dive</link>
<guid isPermaLink="false">https://fezcode.com/blog/steganography-lsb-deep-dive</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Mon, 12 Jan 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<p>Steganography is the art and science of hiding information within other non-secret data. Unlike cryptography, which scrambles a message so it can't be read, steganography hides the very existence of the message.</p>
<p>In this deep dive, we'll explore the implementation of the <strong>Steganography Tool</strong> added to Fezcodex, focusing on the <strong>Least Significant Bit (LSB)</strong> technique.</p>
<h2>The Core Concept: Least Significant Bit (LSB)</h2>
<p>Digital images are made up of pixels. In a standard 24-bit RGB image, each pixel has three color channels: Red, Green, and Blue. Each channel is represented by 8 bits (a value from 0 to 255).</p>
<p>Example of a pixel's color:</p>
<ul>
<li><strong>Red:</strong> 1011010<strong>1</strong> (181)</li>
<li><strong>Green:</strong> 0110011<strong>0</strong> (102)</li>
<li><strong>Blue:</strong> 1100101<strong>1</strong> (203)</li>
</ul>
<p>The <strong>Least Significant Bit</strong> is the rightmost bit in these binary strings. If we change this single bit, the decimal value of the color channel only changes by 1. For example, changing the Red channel from <code>10110101</code> (181) to <code>10110100</code> (180) is a change so subtle that the human eye cannot detect it in a complex image.</p>
<p>By replacing the LSB of each color channel with a bit from our secret message, we can embed data directly into the image.</p>
<h2>The Protocol: FEZ Steganography</h2>
<p>To make the extraction process reliable, we've implemented a simple protocol:</p>
<ol>
<li><strong>Magic Header (<code>FEZ</code>):</strong> The first 24 bits (3 bytes) of the hidden data always spell "FEZ". This allows the decoder to verify if an image actually contains a hidden message from our tool.</li>
<li><strong>Length (32-bit):</strong> The next 32 bits represent the length of the message in bytes. This tells the decoder exactly when to stop reading.</li>
<li><strong>The Message:</strong> The remaining bits are the actual UTF-8 encoded message.</li>
</ol>
<h3>Tracing the Magic: Encoding "FEZ"</h3>
<p>Let's look at how the magic header <code>FEZ</code> is scattered across the first few pixels.</p>
<p><strong>Step 1: Convert characters to binary</strong></p>
<ul>
<li><strong>F</strong> (70): <code>0 1 0 0 0 1 1 0</code></li>
<li><strong>E</strong> (69): <code>0 1 0 0 0 1 0 1</code></li>
<li><strong>Z</strong> (90): <code>0 1 0 1 1 0 1 0</code></li>
</ul>
<p>Combined Bitstream: <code>01000110</code> + <code>01000101</code> + <code>01011010</code> (24 bits total)</p>
<p><strong>Step 2: Embed into pixels</strong>
Since each pixel has 3 channels (R, G, B), we need 8 pixels to hide these 24 bits.</p>
<table>
<thead>
<tr>
<th align="left">Pixel</th>
<th align="left">Channel</th>
<th align="left">Original Byte</th>
<th align="left">Bit to Hide</th>
<th align="left">Modified Byte</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>Pixel 1</strong></td>
<td align="left">Red</td>
<td align="left"><code>1011010</code><strong><code>1</code></strong></td>
<td align="left"><strong>0</strong> (from F)</td>
<td align="left"><code>1011010</code><strong><code>0</code></strong></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">Green</td>
<td align="left"><code>0110011</code><strong><code>0</code></strong></td>
<td align="left"><strong>1</strong> (from F)</td>
<td align="left"><code>0110011</code><strong><code>1</code></strong></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">Blue</td>
<td align="left"><code>1100101</code><strong><code>1</code></strong></td>
<td align="left"><strong>0</strong> (from F)</td>
<td align="left"><code>1100101</code><strong><code>0</code></strong></td>
</tr>
<tr>
<td align="left"><strong>Pixel 2</strong></td>
<td align="left">Red</td>
<td align="left"><code>0101010</code><strong><code>0</code></strong></td>
<td align="left"><strong>0</strong> (from F)</td>
<td align="left"><code>0101010</code><strong><code>0</code></strong></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">Green</td>
<td align="left"><code>1111001</code><strong><code>1</code></strong></td>
<td align="left"><strong>0</strong> (from F)</td>
<td align="left"><code>1111001</code><strong><code>0</code></strong></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">Blue</td>
<td align="left"><code>0011001</code><strong><code>1</code></strong></td>
<td align="left"><strong>1</strong> (from F)</td>
<td align="left"><code>0011001</code><strong><code>1</code></strong></td>
</tr>
<tr>
<td align="left"><strong>Pixel 3</strong></td>
<td align="left">Red</td>
<td align="left"><code>1010101</code><strong><code>0</code></strong></td>
<td align="left"><strong>1</strong> (from F)</td>
<td align="left"><code>1010101</code><strong><code>1</code></strong></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">Green</td>
<td align="left"><code>1100110</code><strong><code>1</code></strong></td>
<td align="left"><strong>0</strong> (from F)</td>
<td align="left"><code>1100110</code><strong><code>0</code></strong></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">Blue</td>
<td align="left"><code>0001111</code><strong><code>0</code></strong></td>
<td align="left"><strong>0</strong> (from E)</td>
<td align="left"><code>0001111</code><strong><code>0</code></strong></td>
</tr>
<tr>
<td align="left"><strong>Pixel 4</strong></td>
<td align="left">Red</td>
<td align="left"><code>1011001</code><strong><code>0</code></strong></td>
<td align="left"><strong>1</strong> (from E)</td>
<td align="left"><code>1011001</code><strong><code>1</code></strong></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">Green</td>
<td align="left"><code>0110110</code><strong><code>1</code></strong></td>
<td align="left"><strong>0</strong> (from E)</td>
<td align="left"><code>0110110</code><strong><code>0</code></strong></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">Blue</td>
<td align="left"><code>1110001</code><strong><code>1</code></strong></td>
<td align="left"><strong>0</strong> (from E)</td>
<td align="left"><code>1110001</code><strong><code>0</code></strong></td>
</tr>
<tr>
<td align="left"><strong>Pixel 5</strong></td>
<td align="left">Red</td>
<td align="left"><code>0101010</code><strong><code>1</code></strong></td>
<td align="left"><strong>0</strong> (from E)</td>
<td align="left"><code>0101010</code><strong><code>0</code></strong></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">Green</td>
<td align="left"><code>1111001</code><strong><code>0</code></strong></td>
<td align="left"><strong>1</strong> (from E)</td>
<td align="left"><code>1111001</code><strong><code>1</code></strong></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">Blue</td>
<td align="left"><code>0011001</code><strong><code>1</code></strong></td>
<td align="left"><strong>0</strong> (from E)</td>
<td align="left"><code>0011001</code><strong><code>0</code></strong></td>
</tr>
<tr>
<td align="left"><strong>Pixel 6</strong></td>
<td align="left">Red</td>
<td align="left"><code>1010101</code><strong><code>0</code></strong></td>
<td align="left"><strong>1</strong> (from E)</td>
<td align="left"><code>1010101</code><strong><code>1</code></strong></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">Green</td>
<td align="left"><code>1100110</code><strong><code>1</code></strong></td>
<td align="left"><strong>0</strong> (from Z)</td>
<td align="left"><code>1100110</code><strong><code>0</code></strong></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">Blue</td>
<td align="left"><code>0101111</code><strong><code>0</code></strong></td>
<td align="left"><strong>1</strong> (from Z)</td>
<td align="left"><code>0101111</code><strong><code>1</code></strong></td>
</tr>
<tr>
<td align="left"><strong>Pixel 7</strong></td>
<td align="left">Red</td>
<td align="left"><code>1011001</code><strong><code>1</code></strong></td>
<td align="left"><strong>0</strong> (from Z)</td>
<td align="left"><code>1011001</code><strong><code>0</code></strong></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">Green</td>
<td align="left"><code>0110110</code><strong><code>0</code></strong></td>
<td align="left"><strong>1</strong> (from Z)</td>
<td align="left"><code>0110110</code><strong><code>1</code></strong></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">Blue</td>
<td align="left"><code>1110001</code><strong><code>1</code></strong></td>
<td align="left"><strong>1</strong> (from Z)</td>
<td align="left"><code>1110001</code><strong><code>1</code></strong></td>
</tr>
<tr>
<td align="left"><strong>Pixel 8</strong></td>
<td align="left">Red</td>
<td align="left"><code>0101010</code><strong><code>1</code></strong></td>
<td align="left"><strong>0</strong> (from Z)</td>
<td align="left"><code>0101010</code><strong><code>0</code></strong></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">Green</td>
<td align="left"><code>1111001</code><strong><code>0</code></strong></td>
<td align="left"><strong>1</strong> (from Z)</td>
<td align="left"><code>1111001</code><strong><code>1</code></strong></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">Blue</td>
<td align="left"><code>0011001</code><strong><code>1</code></strong></td>
<td align="left"><strong>0</strong> (from Z)</td>
<td align="left"><code>0011001</code><strong><code>0</code></strong></td>
</tr>
</tbody></table>
<p>By the time we reach Pixel 8, all 24 bits of "FEZ" are woven into the image. If you open this in a hex editor, you might see that the color <code>181</code> became <code>180</code>, but the text "FEZ" is nowhere to be found in the raw bytes!</p>
<h3>Why PNG and not JPEG?</h3>
<p>Our tool works best with <strong>PNG</strong> files. Why?</p>
<ul>
<li><strong>PNG (Portable Network Graphics)</strong> is a <em>lossless</em> format. It preserves every single bit exactly as it was saved.</li>
<li><strong>JPEG (Joint Photographic Experts Group)</strong> is a <em>lossy</em> format. It uses compression algorithms that slightly alter pixel values to reduce file size. These tiny changes are fine for human viewing, but they destroy the data we've hidden in the LSBs.</li>
</ul>
<h2>The Implementation (JavaScript/Canvas)</h2>
<p>We use the HTML5 <code><canvas></code> API to access and manipulate image data at the pixel level.</p>
<h3>Encoding Logic</h3>
<pre><code class="language-javascript">const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data; // Uint8ClampedArray [R, G, B, A, R, G, B, A, ...]
// ... transform message to bits ...
let bitIndex = 0;
for (let i = 0; i < data.length && bitIndex < allBits.length; i += 4) {
for (let j = 0; j < 3 && bitIndex < allBits.length; j++) {
// Replace LSB of R, G, or B
// (data[i + j] & 0xfe) clears the last bit
// | allBits[bitIndex++] sets it to our secret bit
data[i + j] = (data[i + j] & 0xfe) | allBits[bitIndex++];
}
}
ctx.putImageData(imageData, 0, 0);
</code></pre>
<h3>Decoding Logic</h3>
<p>Decoding is the reverse process. We iterate through the pixels, extract the LSB of each R, G, and B channel, and rebuild the bitstream until we've parsed the header, the length, and finally the message content.</p>
<h2>Challenges and Limitations</h2>
<ul>
<li><strong>Capacity:</strong> The amount of data you can hide depends on the image resolution. Each pixel can hold 3 bits (1 for each RGB channel). A 1080p image (1920x1080) can theoretically hold about 777 KB of hidden data.</li>
<li><strong>Robustness:</strong> LSB steganography is very fragile. Resizing, cropping, or re-saving the image as a JPEG will likely corrupt the hidden message.</li>
<li><strong>Security:</strong> Pure LSB is "security through obscurity." Anyone who knows the technique can extract the message. For true security, you should encrypt the message <em>before</em> hiding it in the image.</li>
</ul>
<h2>Try it out!</h2>
<p>Check out the <strong>Steganography Tool</strong> in the Applications section and start sending your own cryptic signals through the digital aether.</p>
<p><a href="https://fezcode.com/blog/steganography-lsb-deep-dive">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[The Ultimate Pixel Art Resources Guide]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/pixel-art-resources-guide</link>
<guid isPermaLink="false">https://fezcode.com/blog/pixel-art-resources-guide</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Mon, 12 Jan 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<p>Pixel art is a beautiful and nostalgic medium that has seen a massive resurgence in recent years, especially within the indie game development scene. Whether you're a seasoned artist or just starting, having the right tools and resources can make a world of difference.</p>
<p>In this post, we'll explore some of the best resources for pixel art, inspired by the excellent guide by JuniperDev.</p>
<h3>The Ultimate Video Guide</h3>
<p>First and foremost, if you haven't seen it yet, check out this comprehensive video:
<a href="https://www.youtube.com/watch?v=DKmrBUpd0yw">The ONLY Pixel Art Guide You Need (Beginner to Advanced)</a></p>
<h3>Essential Software: Aseprite</h3>
<p>When it comes to creating pixel art, <strong>Aseprite</strong> is widely considered the industry standard. It's not just a drawing tool; it's a specialized environment for sprites and animation.</p>
<ul>
<li><strong>Why it's great:</strong> Pixel-perfect drawing mode, specialized animation timeline, easy sprite sheet exporting, and a very active community.</li>
<li><strong>Where to get it:</strong> <a href="https://www.aseprite.org/">aseprite.org</a></li>
</ul>
<h3>Mastering Color: Lospec</h3>
<p>Color is everything in pixel art. Since you're often working with a limited palette, choosing the right colors is crucial. <strong>Lospec</strong> is the go-to resource for this.</p>
<ul>
<li><strong>Palette Database:</strong> Thousands of pre-made palettes that you can filter by color count.</li>
<li><strong>Tools:</strong> They also offer web-based tools for checking contrast and creating your own palettes.</li>
<li><strong>Link:</strong> <a href="https://lospec.com/">lospec.com</a></li>
</ul>
<h3>Assets and Inspiration: itch.io</h3>
<p>Sometimes you need a head start, or you just want to see how other artists tackle specific challenges. <strong>itch.io</strong> is a goldmine for pixel art assets.</p>
<ul>
<li><strong>What you'll find:</strong> Character sprites, tilesets, UI elements, and full environmental packs.</li>
<li><strong>Learning from others:</strong> Analyzing high-quality asset packs is one of the best ways to learn techniques like dithering, sub-pixeling, and cluster management.</li>
<li><strong>Link:</strong> <a href="https://itch.io/game-assets/free/tag-pixel-art">itch.io/game-assets/free/tag-pixel-art</a></li>
</ul>
<h3>Quick Tips for Beginners</h3>
<ol>
<li><strong>Start Small:</strong> Don't try to draw a massive 256x256 piece right away. Start with 16x16 or 32x32.</li>
<li><strong>Limit Your Palette:</strong> Using too many colors can make your art look messy. Stick to 4-8 colors initially.</li>
<li><strong>Study Real Life:</strong> Even though it's stylized, good pixel art is often grounded in real-world lighting and anatomy.</li>
<li><strong>Practice Your Lines:</strong> Learn about "jaggies" and how to avoid them to keep your lines looking clean and intentional.</li>
</ol>
<p>Pixel art is as much about what you leave out as what you put in. Happy pixeling!</p>
<p><a href="https://fezcode.com/blog/pixel-art-resources-guide">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Implementing Drag and Drop in React without Libraries]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/implementing-drag-and-drop-in-react</link>
<guid isPermaLink="false">https://fezcode.com/blog/implementing-drag-and-drop-in-react</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Sat, 10 Jan 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<p>When building <strong>Tier Forge</strong>, I needed a flexible way to move items between the "pool" and various "tiers". While libraries like <code>react-beautiful-dnd</code> or <code>dnd-kit</code> are excellent, sometimes you just want full control without the overhead.</p>
<p>Here is how I implemented a robust drag-and-drop system using only the native HTML5 API and React state.</p>
<h2>The State Architecture</h2>
<p>The key to a good DnD system is centralized state. In <code>TierForge</code>, the state is held in the parent component:</p>
<pre><code class="language-javascript">const [tiers, setTiers] = useState(DEFAULT_TIERS); // The board
const [poolItems, setPoolItems] = useState([]); // The unranked items
const [dragData, setDragData] = useState(null); // What are we dragging?
</code></pre>
<p>We track <code>dragData</code> to know <em>what</em> is moving (<code>itemId</code>) and <em>where</em> it came from (<code>sourceId</code>).</p>
<h2>The Handlers</h2>
<p>We need three main handlers: <code>onDragStart</code>, <code>onDragOver</code>, and <code>onDrop</code>.</p>
<h3>1. Starting the Drag</h3>
<p>When a user grabs an item, we store its ID and source container ID. We also set <code>dataTransfer</code> for compatibility.</p>
<pre><code class="language-javascript">const handleDragStart = (e, itemId, sourceId) => {
setDragData({ itemId, sourceId });
e.dataTransfer.effectAllowed = 'move';
// Fallback for some browsers
e.dataTransfer.setData('text/plain', JSON.stringify({ itemId, sourceId }));
};
</code></pre>
<h3>2. Allowing the Drop</h3>
<p>By default, HTML elements don't accept drops. We must prevent the default behavior.</p>
<pre><code class="language-javascript">const handleDragOver = (e) => {
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
};
</code></pre>
<h3>3. Handling the Drop</h3>
<p>This is where the magic happens. When an item is dropped, we:</p>
<ol>
<li>Identify the <strong>Source</strong> (where it came from) and <strong>Target</strong> (where it landed).</li>
<li>If Source === Target, do nothing (or reorder).</li>
<li>Find the item in the Source array.</li>
<li>Remove it from the Source.</li>
<li>Add it to the Target.</li>
</ol>
<pre><code class="language-javascript">const handleDrop = (e, targetId) => {
e.preventDefault();
const data = dragData || JSON.parse(e.dataTransfer.getData('text/plain'));
if (!data) return;
const { itemId, sourceId } = data;
if (sourceId === targetId) return;
// ... Logic to find item, remove from source, add to target ...
// This involves setTiers() and setPoolItems() updates.
};
</code></pre>
<h2>The Components</h2>
<h3>Draggable Item</h3>
<p>The item itself needs the <code>draggable</code> attribute and the start handler.</p>
<pre><code class="language-jsx"><div
draggable
onDragStart={(e) => onDragStart(e, item.id, sourceId)}
className="cursor-grab active:cursor-grabbing ..."
>
{/* Content */}
</div>
</code></pre>
<h3>Drop Zone</h3>
<p>The container (Tier or Pool) listens for drag-over and drop events.</p>
<pre><code class="language-jsx"><div
onDragOver={handleDragOver}
onDrop={(e) => handleDrop(e, containerId)}
className="..."
>
{/* Render Items */}
</div>
</code></pre>
<h2>Why Native API?</h2>
<ol>
<li><strong>Zero Dependencies:</strong> Keeps the bundle size small.</li>
<li><strong>Full Control:</strong> I can define exactly how state updates happen.</li>
<li><strong>Performance:</strong> Direct DOM events are highly performant.</li>
</ol>
<p>This pattern powers the entire Tier Forge experience, allowing smooth transitions of assets between the chaotic pool and the structured tiers.</p>
<p><a href="https://fezcode.com/blog/implementing-drag-and-drop-in-react">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Fixing gh-pages: Resolving spawn ENAMETOOLONG]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/gh-pages-enametoolong-fix</link>
<guid isPermaLink="false">https://fezcode.com/blog/gh-pages-enametoolong-fix</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Thu, 08 Jan 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Resolving <code>spawn ENAMETOOLONG</code> in <code>gh-pages</code> Deployment</h1>
<p>If you've been using the <code>gh-pages</code> package for a while, especially in projects with large build folders or complex structures, you might have encountered the dreaded <code>spawn ENAMETOOLONG</code> error when running your deploy script.</p>
<h2>The Problem</h2>
<p>When executing the standard deployment command:</p>
<pre><code class="language-bash">gh-pages -d build -b gh-pages
</code></pre>
<p>The process fails with a system error indicating that the argument list or the command path itself has exceeded the operating system's limits. This is often related to how the underlying <code>globby</code> or <code>async</code> dependencies handle file lists in older versions of the package (like <code>6.3.0</code>).</p>
<p>The issue is documented and discussed in detail here: <a href="https://github.com/tschaub/gh-pages/issues/585">gh-pages Issue #585</a>.</p>
<h2>The Fix</h2>
<p>The specific fix for this issue was highlighted in <a href="https://github.com/tschaub/gh-pages/issues/585#issuecomment-2585457896">this GitHub comment</a>, which explains that the <code>ENAMETOOLONG</code> error occurs on Windows when the <code>rm</code> command receives an excessively long list of files as arguments.</p>
<pre><code class="language-git">diff --git a/lib/git.js b/lib/git.js
index d4c5724272d00bd1f0d76c47dab47d21ccd094d9..d86ac2b0bd7cbc02f34a50dac6980965102ee964 100644
--- a/lib/git.js
+++ b/lib/git.js
@@ -143,7 +143,7 @@ Git.prototype.rm = function (files) {
if (!Array.isArray(files)) {
files = [files];
}
- return this.exec('rm', '--ignore-unmatch', '-r', '-f', '--', ...files);
+ return this.exec('rm', '--ignore-unmatch', '-r', '-f', '--', '.');
};
/**
</code></pre>
<p>The suggested workarounds included batching the file deletions or simplifying the command to target the current directory (<code>.</code>) instead of individual files. Fortunately, these improvements (including a more robust batching logic and a migration to <code>tinyglobby</code>) have already been merged into the main branch of the repository via PR #607.</p>
<p>While we wait for a stable release on NPM that fully addresses this in all environments, the most effective way to resolve it is to use the latest development version directly from the source.</p>
<p>By updating your <code>package.json</code> to point to the GitHub repository's main branch, you get the latest fixes (including the migration to <code>tinyglobby</code> and updated <code>commander</code> logic) that bypass these system limits.</p>
<h3>Implementation</h3>
<p>Update your <code>package.json</code> dependencies:</p>
<pre><code class="language-json">"devDependencies": {
"gh-pages": "github:tschaub/gh-pages"
}
</code></pre>
<p>Then, refresh your installations:</p>
<pre><code class="language-bash">npm install
</code></pre>
<p>This simple change allowed us to resume our production deployments without hitches, ensuring that our "Brutalist" digital garden stays fresh and accessible.</p>
<p><a href="https://fezcode.com/blog/gh-pages-enametoolong-fix">Read more...</a></p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Git Cheatsheet: From Basics to Time Travel]]></title>
<description><![CDATA[[object Object]]]></description>
<link>https://fezcode.com/blog/git-cheatsheet-gist</link>
<guid isPermaLink="false">https://fezcode.com/blog/git-cheatsheet-gist</guid>
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
<pubDate>Thu, 08 Jan 2026 00:00:00 GMT</pubDate>
<content:encoded><![CDATA[<h1>Git Cheatsheet: From Basics to Time Travel</h1>
<p>A collection of essential Git commands, from daily workflows to digging through the depths of your repository's history.</p>
<h2>🔍 Searching History</h2>
<h3>Find when a file existed (even if deleted)</h3>
<pre><code class="language-bash">git log --all -- [path]
</code></pre>
<h3>Search for content changes (Pickaxe)</h3>
<p>Find commits where a specific string was added or removed:</p>
<pre><code class="language-bash">git log -S "your_search_string"
</code></pre>
<h3>Search content with Regex</h3>
<pre><code class="language-bash">git log -G "your_regex"
</code></pre>
<h3>Find a file in any commit/branch</h3>
<pre><code class="language-bash">git rev-list --all | xargs git grep -l "filename"
</code></pre>
<h3>See the history of a specific function/method</h3>
<pre><code class="language-bash">git log -L :function_name:file_path
</code></pre>
<hr>
<h2>🚀 Daily Workflow</h2>
<h3>Stage and Commit</h3>
<pre><code class="language-bash">git add .
git commit -m "feat: descriptive message"
</code></pre>
<h3>Undo last commit (keep changes)</h3>
<pre><code class="language-bash">git reset --soft HEAD~1
</code></pre>
<h3>Fix the last commit message</h3>
<pre><code class="language-bash">git commit --amend -m "new message"
</code></pre>
<hr>
<h2>🌿 Branching & Merging</h2>
<h3>Switch to a new branch</h3>
<pre><code class="language-bash">git checkout -b feature/cool-stuff
# or the newer way:
git switch -c feature/cool-stuff
</code></pre>
<h3>List all branches (including remote)</h3>
<pre><code class="language-bash">git branch -a
</code></pre>
<h3>Safely delete a branch</h3>
<pre><code class="language-bash">git branch -d branch_name
</code></pre>
<hr>
<h2>🛠️ Cleanup & Maintenance</h2>
<h3>Discard all local changes</h3>
<pre><code class="language-bash">git reset --hard HEAD
</code></pre>
<h3>Clean untracked files</h3>
<pre><code class="language-bash">git clean -fd
</code></pre>
<h3>Stash changes for later</h3>
<pre><code class="language-bash">git stash save "Work in progress"
git stash list
git stash pop
</code></pre>
<hr>
<h2>📤 Remote Operations</h2>
<h3>Update local with remote and rebase</h3>
<pre><code class="language-bash">git pull --rebase origin main
</code></pre>
<h3>Prune old remote tracking branches</h3>
<pre><code class="language-bash">git fetch -p
</code></pre>
<p><a href="https://fezcode.com/blog/git-cheatsheet-gist">Read more...</a></p>]]></content:encoded>