<?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: Valeri Karpov</title>
    <description>The latest articles on DEV Community by Valeri Karpov (@code_barbarian).</description>
    <link>https://dev.to/code_barbarian</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%2F346523%2F17536457-fe39-4ba1-b672-f6e1f40c1606.jpg</url>
      <title>DEV Community: Valeri Karpov</title>
      <link>https://dev.to/code_barbarian</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/code_barbarian"/>
    <language>en</language>
    <item>
      <title>How to Render Tables in Mongoose Studio Dashboards</title>
      <dc:creator>Valeri Karpov</dc:creator>
      <pubDate>Thu, 12 Mar 2026 02:13:04 +0000</pubDate>
      <link>https://dev.to/code_barbarian/how-to-render-tables-in-mongoose-studio-dashboards-38kj</link>
      <guid>https://dev.to/code_barbarian/how-to-render-tables-in-mongoose-studio-dashboards-38kj</guid>
      <description>&lt;p&gt;Dashboards are great for charts, but not every result belongs in a graph. Sometimes the clearest way to present data is a table: top customers, recent failed jobs, inventory snapshots, leaderboard rows, or any result where exact values matter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mongoosestudio.app/docs/dashboards.html" rel="noopener noreferrer"&gt;Mongoose Studio dashboards&lt;/a&gt; support table output directly. If your dashboard code returns a &lt;code&gt;$table&lt;/code&gt; object with &lt;code&gt;columns&lt;/code&gt; and &lt;code&gt;rows&lt;/code&gt;, Studio will render it as a proper table in the dashboard UI. That gives you a simple way to turn aggregation results or query output into something readable without building a frontend by hand.&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%2F5kg13xo0sqbrei4zm5ea.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%2F5kg13xo0sqbrei4zm5ea.png" alt=" " width="800" height="647"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shape of a Table Result
&lt;/h2&gt;

&lt;p&gt;To render a table, return an object with a &lt;code&gt;$table&lt;/code&gt; property. Inside &lt;code&gt;$table&lt;/code&gt;, define the column names and the row data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;
  &lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;
  &lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
  &lt;span class="nf"&gt;lean&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;$table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Created At&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;columns&lt;/code&gt; is an array of header labels, and &lt;code&gt;rows&lt;/code&gt; is an array of row arrays. Each row should line up with the column order. That’s it. When Mongoose Studio sees &lt;code&gt;$table&lt;/code&gt;, it renders the result as a table automatically.&lt;/p&gt;

&lt;p&gt;For example, the raw code that generated the Arnold Schwarzenegger movies table above was the following, running on the &lt;a href="https://www.mongodb.com/docs/atlas/sample-data/sample-mflix/" rel="noopener noreferrer"&gt;MongoDB Atlas imdb data set&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Movie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; 
    &lt;span class="na"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Arnold Schwarzenegger&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$gte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1980&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;$lt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1990&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;movie&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Year&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rating&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage in Chat Tab
&lt;/h2&gt;

&lt;p&gt;Scripts generated by Mongoose Studio chat can also use &lt;code&gt;$table&lt;/code&gt;. As a matter of fact, the Arnold Schwarzenegger dashboard was generated by the chat tab.&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%2F3knxly5xr7bwubs24bjc.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%2F3knxly5xr7bwubs24bjc.png" alt=" " width="800" height="738"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>Tech books vs online documentation: what's the difference?</title>
      <dc:creator>Valeri Karpov</dc:creator>
      <pubDate>Tue, 21 Jul 2020 14:02:18 +0000</pubDate>
      <link>https://dev.to/tidelift/tech-books-vs-online-documentation-what-s-the-difference-4p9j</link>
      <guid>https://dev.to/tidelift/tech-books-vs-online-documentation-what-s-the-difference-4p9j</guid>
      <description>&lt;p&gt;&lt;i&gt;Editor’s note: From time to time, we will publish guest posts from the independent maintainers who partner with us as part of the Tidelift Subscription. In this post,  Mongoose maintainer Val Karpov shares the differences between the value of tech books and online documentation.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;When my dad first started writing computer programs in the 70's and 80's, he kept a copy of &lt;a href="https://www.goodreads.com/book/show/515601.The_C_Programming_Language" rel="noopener"&gt;The C Programming Language&lt;/a&gt; on his desk. Back then, a good reference book was the best way to get unstuck if you forgot how to use &lt;span&gt;printf()&lt;/span&gt;.&lt;/p&gt;

&lt;p&gt;That was before the Internet. In 2020, online documentation is better than ever. If you forgot how to use &lt;span&gt;printf()&lt;/span&gt; in C or &lt;span&gt;console.log()&lt;/span&gt; in JavaScript, most developers Google for the answer or use autocomplete in your IDE. Tech books aren't the go-to reference anymore, but that doesn't mean that tech books are useless. Today, tech books serve a new, equally important purpose.&lt;/p&gt;

&lt;h2&gt;&lt;strong&gt;The limitations of online documentation&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;Now that online documentation is the preferred choice for reference material, docs attempt to explain everything about a given project. For example, the &lt;a href="https://curl.haxx.se/docs/manpage.html" rel="noopener"&gt;docs for the popular HTTP command line client curl&lt;/a&gt; list out 383 command line arguments. This huge list is great if you forgot how to use a particular option and need a refresher, but is exceedingly painful if you don't know what you're looking for.&lt;/p&gt;

&lt;p&gt;As the maintainer of &lt;a href="https://mongoosejs.com/" rel="noopener"&gt;Mongoose&lt;/a&gt;, I've often had to make trade-offs on what ends up in the documentation versus what doesn't. Because I see the documentation as a reference, I err on the side of including more information rather than less. That means there's a significant amount of detail on options and functionality that, in my experience, isn't important for building apps. But the information is there because people have needed it in the past.&lt;/p&gt;

&lt;p&gt;Because documentation needs to be complete, it can't omit details that the author thinks aren't relevant. Furthermore, people rarely read documentation from start to finish. Most of the time, developers end up using the documentation as a reference when they run into issues. So docs need to provide all the relevant details, with the assumption that people with all sorts of experience levels can jump into the documentation at any point.&lt;/p&gt;

&lt;h2&gt;&lt;strong&gt;Books provide perspective&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;Curl's 383 command line arguments are necessary because curl is more than just an HTTP client. But, if you're just looking to use curl to send some basic HTTP requests from the command line, the 383 options hurt more than they help. Because I find myself always forgetting the curl arguments I most commonly use, I took the time to write a blog post about &lt;a href="http://thecodebarbarian.com/what-javascript-developers-should-know-about-curl.html" rel="noopener"&gt;using curl for API requests&lt;/a&gt;. This blog post is far from a complete guide to curl, but I think it provides something that's equally valuable: an easily digestible &lt;i&gt;perspective&lt;/i&gt; on curl.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--olRhNlK---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://f.hubspotusercontent30.net/hubfs/4008838/68747470733a2f2f692e696d6775722e636f6d2f6a667850476a312e6a7067.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--olRhNlK---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://f.hubspotusercontent30.net/hubfs/4008838/68747470733a2f2f692e696d6775722e636f6d2f6a667850476a312e6a7067.jpg" alt="68747470733a2f2f692e696d6775722e636f6d2f6a667850476a312e6a7067" width="1280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My new eBook, &lt;a href="https://masteringjs.io/ebooks/mastering-mongoose" rel="noopener"&gt;&lt;i&gt;Mastering Mongoose&lt;/i&gt;&lt;/a&gt;, provides a similar perspective on Mongoose. It describes how, in my experience, developers should think about building apps with Mongoose. Rather than listing out all the functionality Mongoose offers, it explains the fundamental principles of Mongoose and how to apply them when building an app. &lt;i&gt;Mastering Mongoose&lt;/i&gt; also comes with 4 sample apps that demonstrate how to apply the book's principles.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Mastering Mongoose&lt;/i&gt; is meant to be a guide that provides perspective on how to build Mongoose apps, rather than a complete reference explaining all of Mongoose's functionality. What the eBook omits is as important as what it includes. I had to make several controversial exclusions: no &lt;a href="https://mongoosejs.com/docs/api/aggregate.html" rel="noopener"&gt;aggregation framework&lt;/a&gt;, no &lt;a href="https://mongoosejs.com/docs/transactions.html" rel="noopener"&gt;transactions&lt;/a&gt;, no &lt;a href="https://mongoosejs.com/docs/guide.html#read" rel="noopener"&gt;read preferences&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I excluded these topics because, in my experience, they're not essential for building apps effectively with Mongoose. Many developers disagree, and that's fine—that's why these topics will continue to be covered extensively in the documentation. &lt;i&gt;Mastering Mongoose&lt;/i&gt; is about providing perspective rather than serving as a reference, and that requires being more opinionated on certain points than the documentation.&lt;/p&gt;

&lt;h2&gt;&lt;strong&gt;Moving on&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;Tech books today serve a different role than they did 50 years ago. They provide a guided, opinionated perspective on how to use a library or framework, rather than serving as a reference for when you forget a method signature. Documentation needs to explain almost every bit of functionality the module offers, and needs to be accessible for people that hop into the middle of your content from Google looking for a quick fix. A book can be more opinionated on what it includes versus what it omits, and can provide a more guided perspective than documentation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@emilep?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Emile Perron&lt;/a&gt; on &lt;a href="https://unsplash.com/@emilep?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mongoose</category>
      <category>node</category>
      <category>opensource</category>
      <category>documentation</category>
    </item>
  </channel>
</rss>
