TIL: I reduced my Cloudflare Worker bundle size from ~46 MiB (~ 4MiB gzip) to ~700 KiB gzip.
Root cause: calling astro:content (getCollection) inside an SSR route. In my case, a dashboard SSR page used getCollection('course'), and Astro pulled content data layer into _worker.js (including unrelated blog content 330+ posts)
Fixed:
1. I fixed it by keeping SSR data minimal (dashboard only need slug, title and cover image)
2. Keep content-collection routes static (prerender)
Anthropic is acquiring @bunjavascript to further accelerate Claude Codeโs growth.
We're delighted that Bunโwhich has dramatically improved the JavaScript and TypeScript developer experienceโis joining us to make Claude Code even better.
Read more: https://t.co/aQd3XRdUfR
๐จ UPDATE: Full Post-Mortem On Cursor Security Incident
In yesterdayโs thread I explained how I got drained after installing a malicious extension in @cursor_ai.
This is the deeper dive into what I found, what I did, and how you can avoid it.
๐งต ๐
Zak was attacked by installing this extension:
"juanbIanco.solidity"
instead of:
"juanblanco.solidity"
See the difference? Let's put them into a code block:
Today I launched @contextcol
AI Agent to help you find and execute opportunities in financial market.
You can analyze any financial markets focused on quantitative data.
You also able to create trading bot to place order on Binance.
#AiAgent#crypto#trading
Today I learned: this git command to clean up local branches! only the merged ones while protecting master/main/develop:
```
git branch --merged | grep -v '\*\|master\|main\|develop' | xargs -n 1 git branch -d
```
Agreed. The value of PR descriptions is often in things that are NOT directly inferable from the changes:
- What original problem led to this PR?
- Are there related issues / prior discussions?
- What alternatives have been tried? Does this supersede previous attempts?
- Why are certain seemingly unreasonable choices made? What are the tradeoffs?
AI that generates summary based on the changes of an isolated PR is not really helpful in a meaningful way. Good PR descriptions need not only a holistic understanding of the entire codebase, but even the contribution history of the project. Thatโs of course harder to do, but I think itโs a possible direction to make it actually useful.
1/2: โ ๏ธ Alert for iOS users: We have credible intel regarding a high-risk zero-day exploit targeting iMessage on the Dark Web.
This can infiltrate your iPhone without clicking any link. High-value targets are likely. Each use raises detection risk. #CyberSecurity
In 2015, I spent weeks learning Docker.
I found it interesting, but more importantly, I believed learning Docker would help me grow in my career.
And it did. Working with Docker also improved my knowledge of bash scripts, CI/CD, and unix.
Now almost a decade later, I rarely use Docker. But I don't regret learning it. In fact, it taught me two valuable lessons.
1. You can go far using abstractions. But you'll thank yourself for learning about the foundations that make up those tools.
This meme is so goodโthere are a lot of things abstracted for you with Vercel. And if you want to appreciate what Vercel does, dig a layer deeper in your understanding.
Like Harkirat from our community, who built their own version of Vercel's deployment pipeline, teaching people about queues (Redis) and file storage (S3). https://t.co/7NWOrjVqdg
The same goes for frameworks like Next.js. How you would build your own web framework? Hacking together a version for yourself might improve your understanding of routing or bundlers. https://t.co/iBCXcwKPFn
2. There isn't one path. One roadmap. One failure-proof way of becoming a great developer.
In fact, you'll fail a lot. Someone wise once said "a senior developer is just someone who has seen that error 100 times".
Follow your curiosity. Build things for yourself. Have a hunger for learning. And most importantly, don't feel ashamed for learning things your way.
CSS Tip! ๐ช
You can create these tab controls with CSS :has() + radio buttons โจ
.tabs:has(input:nth-of-type(3)) { --count: 3; }
.tabs:has(:checked:nth-of-type(3)) { --active: 2; }
.tabs::after { translate: calc(var(--active, 0) * 100%) 0;
width: calc(100% / var(--count));
}
Two CSS :has() tricks here combined with a rendering trick ๐ค
The tab control is a container using display: grid. You can use :has() to count the number of tabs in the container:
.tabs:has(input:nth-of-type(3)) { --count: 3; }
.tabs:has(input:nth-of-type(4)) { --count: 4; }
Using the cascade, the last valid :has() gives you the number of tabs ๐ซถ
Once you know the number of tabs, you know how to size the indicator:
.tabs::after {
content: "";
position: absolute;
height: 100%;
width: calc(100% / var(--count));
}
It's a pseudoelement that uses --count to determine its size ๐
The next :has() trick is determining which tab is active or :checked as it's an input [type=radio]
.tabs:has(:checked:nth-of-type(2)) { --active: 1; }
.tabs:has(:checked:nth-of-type(3)) { --active: 2; }
You can use a zero-indexed translation here. If the second input is :checked, set --active: 1, then translate the pseudoelement on the tabs to that position ๐
.tabs::after { translate: calc(var(--active, 0) * 100%) 0; }
The last rendering trick is using mix-blend-mode ๐
The tabs have a black background-color, the pseudoelement is white, and the label text is white. When you use mix-blend-mode: difference on the pseudoelement it will give this effect that the text transitions from white to black sliding across ๐
.tabs::after {
color: hsl(0 0% 100%);
mix-blend-mode: difference;
}
You can totally mix up the colors here though and go with a different effect. The mechanics of how you can use CSS :has() is the main point here ๐
As always, any questions, suggestions, etc. let me know
@CodePen link below! ๐ (There's even a @tailwindcss play for this one too ๐)
CSS Tip! ๐
You can create a responsive infinite marquee animation with container queries and no duplicate items ๐ค
li{ animation: slide; }
@โkeyframes slide {
to { translate: 0% calc(var(--i) * -100%);}}
The trick is animating the items, not the list ๐
More tricks ๐
To get this one working, you need to animate the items and not the list (Watch the video first?). Each item needs to know its row index (--i) in the list and the parent needs to know how many rows are in the list:
ul { --count: 12; }
li:nth-of-type(1),
li:nth-of-type(2) { --i: 0; }
li:nth-of-type(3),
li:nth-of-type(4) { --i: 1; }
Once you have that, translate each item based on its row index in the list
li {
translate: 0% calc((var(--count) - var(--i)) * 100%);
}
Now for the animation. The key here is that each row has an animation-delay calculated from its index (--i). That number is offset to make it negative so the animation start is offset โจ
ul { --duration: 10s; }
li {
--delay:
calc((var(--duration) / var(--count)) * (var(--i) - 8));
animation:
slide var(--duration) var(--delay) infinite linear;
}
Make sure to wrap that animation in:
@โmedia (prefers-reduced-motion: no-preference) { ... }
Lastly, the fun parts! ๐ค
To create the "vignette" mask. Use a layered mask on the container ๐ท
.scene {
--buff: 3rem;
height: 100%;
width: 100%;
mask:
linear-gradient(transparent, white var(--buff) calc(100% - var(--buff)), transparent),
linear-gradient(90deg, transparent, white var(--buff) calc(100% - var(--buff)), transparent);
mask-composite: intersect;
}
To create the 3D skewed effect, use a chained transform (Try toggling it in the demo โก๏ธ):
.grid {
transform:
rotateX(20deg)
rotateZ(-20deg)
skewX(20deg);
}
As for the responsive part, use container queries! ๐ฅ
article { container-type: inline-size; }
When the article (card) is narrower than 400px update the grid and animation settings ๐ค Double the rows means double the duration!
@โcontainer (width < 400px) {
.grid {
--count: 12;
grid-template-columns: 1fr;
}
li:nth-of-type(1) { --i: 0; }
li:nth-of-type(2) { --i: 1; }
li:nth-of-type(3) { --i: 2; }
li:nth-of-type(4) { --i: 3; }
li {
--duration: 20s;
}
}
CSS has the magic to be able to update those animations at runtime based on your custom property values ๐
An added bonus in this demo is that it doesn't require any JavaScript at all, for any of it ๐คฏ We can use CSS :has() for those toggles that update the styles, even the theme toggle! ๐ซถ
Any questions, let me know! Make sure to check out the video. Will do a walkthrough one to follow-up ๐ค
@CodePen link below! ๐