<?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: Saad Salman</title>
    <description>The latest articles on DEV Community by Saad Salman (@saadsalman1).</description>
    <link>https://dev.to/saadsalman1</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4062130%2F623a49d6-fac3-4db6-9560-4664b9e1b4f7.png</url>
      <title>DEV Community: Saad Salman</title>
      <link>https://dev.to/saadsalman1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/saadsalman1"/>
    <language>en</language>
    <item>
      <title>I built a free API for Pakistani mutual fund NAVs (because MUFAP's own one doesn't work)</title>
      <dc:creator>Saad Salman</dc:creator>
      <pubDate>Sun, 30 Aug 2026 11:02:52 +0000</pubDate>
      <link>https://dev.to/saadsalman1/i-built-a-free-api-for-pakistani-mutual-fund-navs-because-mufaps-own-one-doesnt-work-20k3</link>
      <guid>https://dev.to/saadsalman1/i-built-a-free-api-for-pakistani-mutual-fund-navs-because-mufaps-own-one-doesnt-work-20k3</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://saadsalman.org/blog/free-api-pakistani-mutual-fund-navs" rel="noopener noreferrer"&gt;saadsalman.org&lt;/a&gt; in July 2026. Updated August 2026 with NAV history, fund metadata and a free public dataset.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why MUFAP's own API doesn't work
&lt;/h2&gt;

&lt;p&gt;I needed daily NAV data for Pakistani mutual funds for Gramafin, a personal finance app I'm building. MUFAP, the Mutual Funds Association of Pakistan, does have a JSON API. It just doesn't work for anyone who isn't a browser. I replicated Chrome's exact headers and parameters and still got 500 errors on every server-side request. My best guess is the frontend JavaScript establishes some session or anti-forgery state that isn't practical to replicate outside a real browser.&lt;/p&gt;

&lt;p&gt;Their public Fund Directory page is a different story. It's a plain server-rendered HTML table with over 500 funds, current NAVs and prices sitting right in the markup. No auth, no pagination, no JavaScript required. So instead of fighting the broken API, I scrape the page that works.&lt;/p&gt;

&lt;h2&gt;
  
  
  To be fair, there is a paid option
&lt;/h2&gt;

&lt;p&gt;CapitalStake sells a serious Pakistani mutual funds data product with AUMs, sector allocations, holdings history and uptime guarantees, delivered over REST, WebSocket, CSV and Excel. It's a commercial product with a "request a consultation" button, and if you're an organization that needs deep historical data and strict SLAs, that's probably where you should go.&lt;/p&gt;

&lt;p&gt;But most developers just need today's NAVs as JSON without a sales call or a subscription. That's the gap this fills.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turning it into its own thing
&lt;/h2&gt;

&lt;p&gt;The scraper started as a piece of Gramafin's backend and grew into a standalone MIT-licensed project: &lt;a href="https://github.com/saadsalmankhan/pakistan-mutual-funds-api" rel="noopener noreferrer"&gt;pakistan-mutual-funds-api&lt;/a&gt;. If you're building anything fintech-adjacent in Pakistan, you've probably hit this exact wall, so I pulled it out into something you can clone and run in two minutes. No database to set up, no cloud account to configure, no framework to learn.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it actually does
&lt;/h2&gt;

&lt;p&gt;Three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scrapes&lt;/strong&gt; MUFAP's Fund Directory with cheerio, pulling each fund's name, AMC, NAV, offer price and category&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stores&lt;/strong&gt; the result as plain JSON on disk, no Postgres or Redis required&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serves&lt;/strong&gt; it from a small Express API at &lt;code&gt;GET /api/funds&lt;/code&gt;, CORS wide open so you can call it straight from frontend code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By default it re-scrapes once a day and skips weekends, since MUFAP only publishes new NAVs on business days. Both are configurable through environment variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/saadsalmankhan/pakistan-mutual-funds-api.git
&lt;span class="nb"&gt;cd &lt;/span&gt;pakistan-mutual-funds-api
npm &lt;span class="nb"&gt;install
cp&lt;/span&gt; .env.example .env
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API is up at &lt;code&gt;localhost:4000/api/funds&lt;/code&gt;, and the README covers every configuration option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update (August 2026): it's a dataset now, not just an API
&lt;/h2&gt;

&lt;p&gt;Since publishing this, the project grew the pieces people kept asking for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NAV history.&lt;/strong&gt; Every scrape now appends each fund's NAV to a per-fund NDJSON file, so any instance builds its own time series from the day it starts running. New endpoint: &lt;code&gt;GET /api/funds/:id/history?from=&amp;amp;to=&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lookups and filters.&lt;/strong&gt; &lt;code&gt;GET /api/funds/:id&lt;/code&gt; for a single fund, plus &lt;code&gt;?category=&lt;/code&gt;, &lt;code&gt;?amc=&lt;/code&gt;, &lt;code&gt;?q=&lt;/code&gt; and &lt;code&gt;?shariah=true&lt;/code&gt; on the list endpoint, and &lt;code&gt;/api/categories&lt;/code&gt; and &lt;code&gt;/api/amcs&lt;/code&gt; for building dropdowns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shariah flags, benchmarks and expense ratios.&lt;/strong&gt; Every fund now carries a &lt;code&gt;shariah&lt;/code&gt; boolean (295 of 549 funds are Shariah-compliant, derived from MUFAP's own category names) and a benchmark mapping: KSE-100 for conventional equity categories, KMI-30 for Shariah equity, null where no single index honestly applies. A separate &lt;code&gt;npm run enrich&lt;/code&gt; pulls each fund's total expense ratio, management fee and inception date from MUFAP's expense ratios table and merges them into the snapshot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A public dataset that updates itself.&lt;/strong&gt; If you don't want to run anything at all: &lt;a href="https://github.com/saadsalmankhan/pakistan-mutual-funds-data" rel="noopener noreferrer"&gt;pakistan-mutual-funds-data&lt;/a&gt; is a repo where a GitHub Action scrapes MUFAP every business day and commits the snapshot, the growing NAV history and the fund metadata. You can &lt;code&gt;curl&lt;/code&gt; the raw files and be done, and the commit log doubles as an audit trail of every data change.&lt;/p&gt;

&lt;p&gt;Why this matters: a team building an AI mutual funds advisor &lt;a href="https://builder.aws.com/content/3At6r43MnBxCrVr6tBE1qL9DdA3/aideas-gullak-autonomous-agents-for-mutual-funds" rel="noopener noreferrer"&gt;wrote about their AWS hackathon project&lt;/a&gt; that no clean, structured, public dataset existed for Pakistani mutual funds, and they had to assemble 301,749 NAV rows by hand before they could build anything. That dataset now exists, it updates itself daily and it's free.&lt;/p&gt;

&lt;p&gt;If you build something with it, I'd genuinely like to hear about it. I'm at &lt;a href="https://saadsalman.org" rel="noopener noreferrer"&gt;saadsalman.org&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>fintech</category>
      <category>pakistan</category>
      <category>api</category>
    </item>
    <item>
      <title>How I Built This Website With Claude Code</title>
      <dc:creator>Saad Salman</dc:creator>
      <pubDate>Tue, 04 Aug 2026 09:14:04 +0000</pubDate>
      <link>https://dev.to/saadsalman1/how-i-built-this-website-with-claude-code-dd9</link>
      <guid>https://dev.to/saadsalman1/how-i-built-this-website-with-claude-code-dd9</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu199iyshe7wben3juuaj.jpg" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu199iyshe7wben3juuaj.jpg" alt="Homepage of saadsalman.org, built with Claude Code" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This entire website — the pages you're clicking through, the illustrations, the CMS this post was published from, even the favicon in your browser tab — was built through a conversation with Claude Code, Anthropic's AI coding agent. I didn't write the code. I described what I wanted, reviewed what came back, and steered. Here's how it went.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with a vibe, not a spec
&lt;/h2&gt;

&lt;p&gt;My first message was one line: "keep a clean white look, take inspiration from Apple and how Claude designs." No wireframes, no tickets. Claude scaffolded a Next.js and Tailwind project, pulled my details from my resume PDF, and had a working site — hero, experience, resume download, analytics hooks — running in a live browser preview within minutes.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8rd6v9kibi1ix12layno.jpg" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8rd6v9kibi1ix12layno.jpg" alt="The finished homepage: gradient wordmark, hand-drawn payment illustrations, and explore tiles" width="799" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Borrow taste, then make it yours
&lt;/h2&gt;

&lt;p&gt;I shared a portfolio site I liked and said "go creative." Claude drew an entire illustration language from scratch — hand-written SVGs of payment cards, tap-to-pay phones, currency coins, and funnels, each with flat color blocks offset behind ink outlines. That language now runs through everything: the hero, the section tiles, the case-study artwork, the S-coin favicon in the browser tab, and even my LinkedIn banner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Restructure without fear
&lt;/h2&gt;

&lt;p&gt;The first draft was one long page, and honestly, it was boring. So we split it: a minimal home, then About, Experience, Blog, and Case Studies as their own pages. Copy got trimmed, gradients came in, my photo got a cleaner background and an animated frame. Big refactors are cheap when your pair programmer holds the whole codebase in its head — and checks every change in a real browser, on desktop and mobile widths, before calling it done.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fncdb97sj9ip3nk0lfv4i.jpg" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fncdb97sj9ip3nk0lfv4i.jpg" alt="The About page: photo with an offset-color frame and floating sparkles from the site's illustration language" width="799" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Give the site a brain
&lt;/h2&gt;

&lt;p&gt;For publishing, Claude created a Sanity project on my account through its management API, defined schemas for blog posts and case studies, and embedded the editing studio directly into the site. Content goes live within a minute of hitting Publish — no redeploys, no code changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ship it like you mean it
&lt;/h2&gt;

&lt;p&gt;Every change was committed to GitHub and auto-deployed by Vercel. When I pointed my domain at the project, Claude attached it, told me exactly which DNS records to add, watched the records propagate, and set up the www redirect and SSL. Analytics counts visits, project clicks, and resume downloads; speed monitoring watches how fast the site feels for real visitors.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7gttun24s3r4kbcluvaz.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7gttun24s3r4kbcluvaz.png" alt="The ecosystem: Claude Code at the center, orchestrating Next.js, Sanity CMS, GitHub, Vercel, Namecheap DNS, and Google Analytics 4" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd tell you if you're trying this
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Talk in outcomes, not implementations. "How do we track clicks and downloads," plus a reference link, beats any detailed spec I could have written.&lt;/li&gt;
&lt;li&gt;Ask for proof. Every change was verified in a live browser preview — screenshots at desktop and mobile widths — before I ever looked at it.&lt;/li&gt;
&lt;li&gt;Iterate out loud. "The intro is too long and boring" and "we need to support rapid publishing of articles and case studies" are both perfectly good code reviews.&lt;/li&gt;
&lt;li&gt;Keep one design language. When the site, favicon, banner, and blog art share a visual system, everything reads as intentional.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total build: a few conversations spread across two days. Lines of code I wrote myself: zero. If you've been putting off building your personal site, the excuse pool just got a lot shallower.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>nextjs</category>
      <category>buildinpublic</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
