<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 0x5zen</title>
    <description>The latest articles on DEV Community by 0x5zen (@0x5zen).</description>
    <link>https://dev.to/0x5zen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3731734%2F62cbf6b9-0799-477d-8b4a-d3543d58fe3c.jpg</url>
      <title>DEV Community: 0x5zen</title>
      <link>https://dev.to/0x5zen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/0x5zen"/>
    <language>en</language>
    <item>
      <title>Building a Web-Based Infinite Canvas with Next.js, Neon, and Prisma</title>
      <dc:creator>0x5zen</dc:creator>
      <pubDate>Fri, 30 Jan 2026 09:01:23 +0000</pubDate>
      <link>https://dev.to/0x5zen/building-a-web-based-infinite-canvas-with-nextjs-neon-and-prisma-3oe2</link>
      <guid>https://dev.to/0x5zen/building-a-web-based-infinite-canvas-with-nextjs-neon-and-prisma-3oe2</guid>
      <description>&lt;p&gt;As a developer who loves design, I've always wanted a workspace that feels limitless. Desktop apps like PureRef are great, but I wanted that same freedom directly in the browser—accessible anywhere, with zero installation.&lt;/p&gt;

&lt;p&gt;So, I built &lt;strong&gt;PureZen&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎨 What is PureZen?
&lt;/h2&gt;

&lt;p&gt;PureZen is a distraction-free, infinite canvas designed for creatives. It allows you to drag, drop, and organize references or create moodboards in a boundless workspace.&lt;/p&gt;

&lt;p&gt;It is currently in &lt;strong&gt;Public Beta (v1.2)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9v3pe8caf5zf7lf74p5l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9v3pe8caf5zf7lf74p5l.png" alt=" " width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6cl96t4tpso24a2i9rwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6cl96t4tpso24a2i9rwg.png" alt=" " width="800" height="393"&gt;&lt;/a&gt;&lt;br&gt;
👉 &lt;strong&gt;Live Demo:&lt;/strong&gt; &lt;a href="https://purezen.vercel.app/" rel="noopener noreferrer"&gt;https://purezen.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠️ Under the Hood: The Tech Stack
&lt;/h2&gt;

&lt;p&gt;Building a performant canvas application on the web requires a robust stack. Here is what I used to bring PureZen to life:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Framework:&lt;/strong&gt; &lt;strong&gt;Next.js 14&lt;/strong&gt; (App Router) for the core infrastructure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database:&lt;/strong&gt; &lt;strong&gt;Neon&lt;/strong&gt; (Serverless Postgres). I needed a database that could scale automatically and work seamlessly with serverless functions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ORM:&lt;/strong&gt; &lt;strong&gt;Prisma&lt;/strong&gt;. It makes interacting with the Neon database type-safe and incredibly intuitive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage:&lt;/strong&gt; &lt;strong&gt;UploadThing&lt;/strong&gt;. Since this app is all about images, I needed a reliable way to handle file uploads. UploadThing made the implementation straightforward.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactions:&lt;/strong&gt; &lt;strong&gt;Framer Motion&lt;/strong&gt; to handle the complex drag, resize, and pan physics at 60fps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auth:&lt;/strong&gt; &lt;strong&gt;NextAuth.js&lt;/strong&gt; for secure Google authentication.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🧠 The Challenge: Visual Logic
&lt;/h2&gt;

&lt;p&gt;The hardest part wasn't the backend; it was the &lt;strong&gt;Canvas Logic&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I wanted a "smart" canvas. This means when you rotate an image, the resize handles need to rotate with it, and the snapping guides need to calculate the visual edges of the rotated object, not just the DOM element box.&lt;/p&gt;

&lt;p&gt;This involved projecting screen coordinates to world coordinates and applying some interesting trigonometry to ensure the UX felt natural.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✨ Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Infinite Pan &amp;amp; Zoom:&lt;/strong&gt; No boundaries, just space.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart Snapping:&lt;/strong&gt; Auto-alignment guides for keeping your board organized.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Sync:&lt;/strong&gt; Your workspace saves automatically to your account (powered by Prisma &amp;amp; Neon).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PWA Support:&lt;/strong&gt; Installable on desktop and mobile.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🚀 What's Next?
&lt;/h2&gt;

&lt;p&gt;I am currently refining the mobile experience and optimizing the rendering performance for boards with hundreds of images.&lt;/p&gt;

&lt;p&gt;I’d love for you to try it out and let me know what you think. Feedback on the interaction feel is highly appreciated!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it here:&lt;/strong&gt; &lt;a href="https://purezen.vercel.app/" rel="noopener noreferrer"&gt;https://purezen.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>showdev</category>
      <category>react</category>
      <category>prisma</category>
    </item>
    <item>
      <title>ZenPNL — IDX Stock P&amp;L + TradingView Chart + News (Next.js)</title>
      <dc:creator>0x5zen</dc:creator>
      <pubDate>Sun, 25 Jan 2026 19:25:21 +0000</pubDate>
      <link>https://dev.to/0x5zen/zenpnl-idx-stock-pl-tradingview-chart-news-nextjs-570h</link>
      <guid>https://dev.to/0x5zen/zenpnl-idx-stock-pl-tradingview-chart-news-nextjs-570h</guid>
      <description>&lt;p&gt;I just shipped a small project called &lt;strong&gt;ZenPNL&lt;/strong&gt; a simple, single page IDX stock dashboard that focuses on three things: chart, P&amp;amp;L, and news (fast, responsive, dark-first).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live&lt;/strong&gt;:&lt;a href="https://zenpnl.vercel.app" rel="noopener noreferrer"&gt;https://zenpnl.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;:&lt;a href="https://github.com/meryzennn/profitandloss/" rel="noopener noreferrer"&gt;https://github.com/meryzennn/profitandloss/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&amp;gt; Not financial advice. Market data can be delayed depending on sources.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Why I built it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I wanted an open and go experience like stock apps:&lt;br&gt;
1) Open the site -&amp;gt; IHSG shows by default&lt;br&gt;
2) Search an IDX ticker -&amp;gt; chart switches instantly&lt;br&gt;
3) Calculate P&amp;amp;L using lots (1 lot = 100 shares)&lt;br&gt;
4) Scroll -&amp;gt; read relevant news without leaving the dashboard&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Core features&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;TradingView chart (IDX + IHSG)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses the TradingView widget (tv.js) for a real charting feel&lt;/li&gt;
&lt;li&gt;Default symbol: IHSG / IDX Composite&lt;/li&gt;
&lt;li&gt;When switching symbols, the chart resets so the previous viewport doesn't stick&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Lot-based P&amp;amp;L calculator&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inputs: buy/sell price, lots, buy fee %, sell fee %, sell tax %&lt;/li&gt;
&lt;li&gt;Outputs: net P&amp;amp;L (IDR), ROI %, break-even sell price&lt;/li&gt;
&lt;li&gt;Small UX helpers: quick set buy/sell = last price&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;News feed that points to real publishers&lt;br&gt;
Google News RSS is convenient, but RSS links can lead to redirects and sometimes weird/non-article pages.&lt;br&gt;
So I implemented a resolver that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;prioritizes the publisher domain from RSS source&lt;/li&gt;
&lt;li&gt;aggressively filters junk (ads/scripts/assets/spec pages)&lt;/li&gt;
&lt;li&gt;validates final URLs as real HTML articles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Result: the news list shows actual publisher sources (e.g., local finance media) instead of news.google.com / random pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dark-first UI + micro-interactions&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dark mode by default (better for charts)&lt;/li&gt;
&lt;li&gt;Shimmer loading states for news&lt;/li&gt;
&lt;li&gt;Subtle hover/press animations to feel app-like&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Tech stack&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next.js App Router + TypeScript&lt;/li&gt;
&lt;li&gt;Tailwind CSS&lt;/li&gt;
&lt;li&gt;SWR for client-side fetching + caching&lt;/li&gt;
&lt;li&gt;Route Handlers for API normalization:

&lt;ul&gt;
&lt;li&gt;Yahoo search &amp;amp; chart meta for Last / Prev Close&lt;/li&gt;
&lt;li&gt;Google News RSS -&amp;gt; resolve to publisher URLs&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Design choice: Last vs Close&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To keep the price card easy to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Main price uses Yahoo Last (regularMarketPrice)&lt;/li&gt;
&lt;li&gt;Change badge uses Last vs Prev Close&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This tends to match what users expect from stock apps and feels closer to live than strictly following candle close.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Hard parts&lt;/strong&gt; (the annoying ones)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TradingView + hydration: the widget is client-only DOM injection, so the container ID must be stable to avoid mismatch issues.&lt;/li&gt;
&lt;li&gt;RSS resolution: extracting clean publisher URLs from aggregated feeds is trickier than it looks (redirect chains, embedded URLs, junk endpoints).&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;What I'd like to improve next&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Watchlist (localStorage)&lt;/li&gt;
&lt;li&gt;Better market ticker (gainers/losers) if I find a stable IDX feed&lt;/li&gt;
&lt;li&gt;Smarter news relevance (query tuning per ticker to avoid ambiguous keywords)&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you have feedback on the UI/UX or know good IDX-friendly data sources, I'd love suggestions.&lt;/p&gt;

&lt;p&gt;Links again: &lt;a href="https://zenpnl.vercel.app/" rel="noopener noreferrer"&gt;https://zenpnl.vercel.app/&lt;/a&gt; | &lt;a href="https://github.com/meryzennn/profitandloss/" rel="noopener noreferrer"&gt;https://github.com/meryzennn/profitandloss/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>typescript</category>
      <category>tailwindcss</category>
    </item>
  </channel>
</rss>
