Compare commits

..

10 Commits

Author SHA1 Message Date
SauravDhakal
ab36028ccf fix: syntax
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-03 22:26:33 +05:45
SauravDhakal
c50baca85a test: test ci/cd 2026-04-03 22:07:10 +05:45
SauravDhakal
23a033acc3 feat: Added favicon and CV 2026-04-03 21:29:42 +05:45
SauravDhakal
570afd621d fix: gtag
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-02 09:04:20 +05:45
SauravDhakal
af7e549fc7 fix: hugo specific g-tag
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-02 08:55:15 +05:45
SauravDhakal
12f56ff11f fix: google analytics
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-02 08:36:48 +05:45
SauravDhakal
caca000c7f feat: new post, clean up old placeholders
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-01 21:55:48 +05:45
SauravDhakal
2007e1f7b5 fix: woodpecker event
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-01 18:31:19 +05:45
SauravDhakal
663e8c8d62 fix: test
Some checks are pending
ci/woodpecker/manual/woodpecker Pipeline is pending
2026-04-01 13:28:35 +05:45
SauravDhakal
2dd65b7b48 chore: add woodpecker 2026-04-01 13:10:14 +05:45
9 changed files with 137 additions and 80 deletions

View File

@@ -1,34 +0,0 @@
name: Deploy Hugo Site
on:
push:
branches:
- master
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: "latest"
extended: true
- name: Build site
run: hugo build --minify
- name: Deploy via rsync
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.SSH_PORT }}
source: "public/*"
target: "/var/www/portfolio"
strip_components: 1

12
.woodpecker.yml Normal file
View File

@@ -0,0 +1,12 @@
# Test
when:
event: push
branch: master
steps:
build:
image: hugomods/hugo:latest
commands:
- hugo --minify --destination /site/public
volumes:
- /home/saurav/site:/site # writes directly to where Caddy serves from

BIN
assets/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -1,11 +0,0 @@
---
title: "Sample Note"
date: 2025-08-20
# summary: "This is a sample note to demonstrate the notes section"
tags: ["example"]
draft: false
---
This is a sample note. Notes are meant to be short, quick thoughts or TILs (Today I Learned).
Delete this file and add your own notes here!

View File

@@ -1,26 +0,0 @@
---
title: "The Art of the Digital Garden"
date: 2026-04-01T08:55:00+05:45
draft: false
tags: ["philosophy", "gruvbox", "hugo"]
description: "Exploring the concept of a digital garden and how a refined Gruvbox theme enhances the experience."
---
Welcome to my digital garden. This is a place where I share my thoughts, projects, and lessons learned along the way. Unlike a traditional blog, a digital garden is always growing and evolving.
### Why Gruvbox?
Gruvbox is more than just a color scheme; it's a philosophy of contrast and harmony. By using the "Hard" contrast variant, we achieve a focus that is both easy on the eyes and aesthetically pleasing.
```javascript
const theme = "Gruvbox Dark Hard";
console.log(`Current theme: ${theme}`);
```
### The Beauty of Hugo
Hugo allows for lightning-fast build times and complete control over the structure of our content. Paired with a minimal theme like PaperMod, it provides the perfect canvas for technical writing.
> "A garden is never finished."
I hope you enjoy exploring these notes and posts as much as I enjoy writing them.

View File

@@ -0,0 +1,105 @@
---
title: "The Likes Table Problem: Why We Went Polymorphic."
date: 2026-04-01T21:50:00+05:45
draft: false
tags: ["architecture", "backend", "PSQL"]
description: "Concept of polymorphic table in an SQL database"
---
A few days ago, I was working on adding a **Community** section to an application. The idea was simple, users should be able to:
- Create posts
- Leave comments
- Like posts
- Like comments
We also had a separate News section. The new requirement was users should be able to like news articles as well.
Building model for `posts` and `comments` was pretty straight forward. The real challenge was to model the`likes`table.
## The Problem: How Do We Store Likes?
Were using PostgreSQL, so enforcing relationships with foreign keys is easy and clean.
If only **one** thing could be liked (say, News), the schema would be simple, we would have a `news_like` table which could look something like this:
| user_id | news_id | timestamp |
| --- | --- | --- |
| (foreign key) | (foreign key) | 1775059642 |
But we didnt have one entity. We had three. `posts`, `comments` and `news`.
We had to decide:
> Do we create three separate like tables? Or do we design one flexible solution?
## Option 1: Three Separate Tables
We could create three tables: `post_likes` , `comment_likes` and `news_likes` . Each table would have proper foreign key relationships. This approach would be a clean relational way of doing things. It:
- Keeps strong relational integrity
- Makes joins easy
- Keeps structure explicit
This is the most “pure relational” approach. But it felt repetitive. The schema grows horizontally.
And if tomorrow we add something else that can be liked, wed need yet another table.
It works, but it doesnt scale elegantly.
## Option 2: A Polymorphic Table (What We Chose)
Instead of multiple tables, we created a **single polymorphic likes table**.
### What is a Polymorphic Table?
A polymorphic table can reference multiple types of resources using a shared structure.
We designed our `likes` table to look something like this:
| user_id | resource_id | resource_type | timestamp |
| --- | --- | --- | --- |
| (foreign key) | (uuid) | (POST / COMMENT / NEWS) | |
Heres how it works:
- `user_id`: who liked, foreign key to `users` table.
- `resource_id` : the UUID of the item, just the uuid, no foreign key relation.
- `resource_type` : what type of item it is
- `timestamp` : timestamp
Instead of a strict foreign key to one table, we store:
- The ID
- The type of resource
Together, they uniquely identify what was liked.
With this approach, we had one clean and centralized table to store all kinds of likes. Its much easier to expand and flexible. Since “like” is a feature common to many parts of the system, this design keeps it generic and reusable.
But it does has a major downside. We lose direct foreign key enforcement on `resource_id`. Because PostgreSQL cant enforce a foreign key that dynamically points to multiple tables, referential integrity must be handled at the application level. We cannot write a simple join query to join from `comments` table or `posts` table.
For example, to fetch likes for a resource:
```tsx
SELECT COUNT(*)
FROM likes
WHERE resource_id = 'some-uuid'
AND resource_type = 'POST';
```
Now, if we need resource details plus likes, we may need separate queries or application-side logic.
For our use case though, that trade-off was acceptable. We dont perform heavy cross-entity joins on likes, so the downside was minimal.
## Why This Design Felt Right
The key insight was this:
> “Like” is not tightly coupled to Posts, Comments, or News. Its a behavior shared across resources.
>
By modeling it polymorphically, we treated “like” as a reusable system capability rather than a feature embedded in each entity.
And as our application grows, this decision will likely save us refactoring time.

View File

@@ -32,6 +32,7 @@ params:
DateFormat: "January 2, 2006"
defaultTheme: dark # dark, light
disableThemeToggle: true
googleAnalytics: "G-V0CXG8ZEG2"
ShowReadingTime: true
ShowShareButtons: true
@@ -51,11 +52,11 @@ params:
assets:
# disableHLJS: true # to disable highlight.js
# disableFingerprinting: true
favicon: "<link / abs url>"
favicon16x16: "<link / abs url>"
favicon32x32: "<link / abs url>"
apple_touch_icon: "<link / abs url>"
safari_pinned_tab: "<link / abs url>"
favicon: ./favicon.png
favicon16x16: ./favicon.png
favicon32x32: ./favicon.png
apple_touch_icon: ./favicon.png
safari_pinned_tab: ./favicon.png
label:
text: "SauravDhakal"
@@ -81,17 +82,23 @@ params:
Content: >
Im a software engineer who enjoys building thoughtful systems and learning how things really work.
<br /><br />
This is my digital garden - notes, projects, and lessons along the way.
Here I write about things I learn, find interesting, or want to remember. I'm a self-hosting and cloud enthusiast, actively experimenting with both.
<br /><br />
Checkout my [CV](files/CV.pdf) for my works and projects.
In my free time, I'm either reading or tinkering with something.
<br /><br />
Checkout my [CV](CV.pdf) for my works and projects.
#demo
socialIcons:
- name: github
url: "https://github.com/sauravdhakal12"
- name: gitea
url: "https://gitea.sauravdhakal.com.np/explore"
- name: linkedin
url: "https://www.linkedin.com/in/saurav-dhakal-9a8b27220/"
- name: x
url: "https://x.com/s0x1495"
- name: dev
url: "https://dev.to/sauravdhakal12/"
analytics:
google:
@@ -150,3 +157,7 @@ markup:
# lineNos: true
# style: monokai
googleAnalytics: "G-V0CXG8ZEG2"
services:
googleAnalytics:
id: "G-V0CXG8ZEG2"

BIN
static/CV.pdf Normal file

Binary file not shown.

BIN
static/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB