<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title>Geshan&#39;s Blog</title>
	<subtitle>A blog about software engineering, devops and web development</subtitle>
	
	<link href="https://geshan.com.np/atom.xml" rel="self"/>
	<link href="https://geshan.com.np/"/>
	<updated>2026-03-27T10:52:47Z</updated>
	<id>https://geshan.com.np/</id>
	<author>
		<name>Geshan Manandhar</name>
		<email>geshan@gmail.com</email>
	</author>
	
	<entry>
		<title>How to build a simple Google login and profile page on Google AI Studio with Firebase as a datastore [step-by-step]</title>
		<link href="https://geshan.com.np/blog/2026/03/google-ai-studio-database/"/>
		<updated>2026-03-27T10:52:47Z</updated>
		<id>https://geshan.com.np/blog/2026/03/google-ai-studio-database/</id>
		<content type="html">&lt;p&gt;Google AI Studio has recently added an array of &lt;a href=&quot;https://blog.google/innovation-and-ai/technology/developers-tools/full-stack-vibe-coding-google-ai-studio/&quot;&gt;new features&lt;/a&gt;, calling it a new full-stack vibe-coding experience and vibe-coding-to-production. The new feature include ability to generate music, use Google Search data, use Google Maps data, add a database and auth, and add Gemini intelligence, to name a few. In this post, you will learn about adding a database and auth, which uses Google Firebase in the background to do so. Let’s get started!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-database/01google-ai-studio-database.jpg&quot; title=&quot;Google AI Studio basic login app with Firebase Firestore database&quot; alt=&quot;Google AI Studio basic login app with Firebase Firestore database&quot; fetchpriority=&quot;high&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/google-ai-studio-database/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/03/google-ai-studio-database/#prerequisites&quot;&gt;Prerequisites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/03/google-ai-studio-database/#build-a-simple-login-and-profile-page&quot;&gt;Build a simple login and profile page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/03/google-ai-studio-database/#google-ai-studio---build&quot;&gt;Google AI Studio - Build&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/03/google-ai-studio-database/#the-prompt-to-generate-the-app&quot;&gt;The prompt to generate the app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/03/google-ai-studio-database/#using-firebase-for-login-and-data-storage&quot;&gt;Using Firebase for login and data storage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/03/google-ai-studio-database/#data-in-firestore&quot;&gt;Data in Firestore&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/03/google-ai-studio-database/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;prerequisites&quot; tabindex=&quot;-1&quot;&gt;Prerequisites &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/google-ai-studio-database/#prerequisites&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before you get started with vibe coding a simple Google login and profile page on Google AI Studio using Firebase as a datastore and login provider, it is better to check off the following requirements:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You will need an active Google account; having a Gmail will suffice&lt;/li&gt;
&lt;li&gt;You may need a Google Cloud Project or a Firebase project, in my experiment, it was not required, but it is good to have&lt;/li&gt;
&lt;li&gt;You will use the &lt;code&gt;Gemini 3.1 Pro Preview&lt;/code&gt;, which can eat up your free limits.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Given that is mentioned, you can start building a login and user profile page on Google AI Studio by prompting (and vibe coding) in place of writing code to integrate with Firebase next.&lt;/p&gt;
&lt;h2 id=&quot;build-a-simple-login-and-profile-page&quot; tabindex=&quot;-1&quot;&gt;Build a simple login and profile page &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/google-ai-studio-database/#build-a-simple-login-and-profile-page&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The aim of this tutorial is to build a simple but useful login page with Google login (&lt;a href=&quot;https://www.demandsage.com/gmail-statistics/&quot;&gt;1.8 billion people use Gmail&lt;/a&gt; each month). The app will also have a form to input address, phone number, LinkedIn profile, and GitHub profile that will be displayed on a plain profile page.&lt;/p&gt;
&lt;p&gt;You could have used &lt;a href=&quot;https://blog.google/innovation-and-ai/models-and-research/google-labs/stitch-ai-ui-design/&quot;&gt;Google Stitch to vibe design&lt;/a&gt; it, we can keep it as a topic for another blog post.&lt;/p&gt;
&lt;h2 id=&quot;google-ai-studio---build&quot; tabindex=&quot;-1&quot;&gt;Google AI Studio - Build &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/google-ai-studio-database/#google-ai-studio---build&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First go to Google AI Studio at &lt;a href=&quot;https://ai.dev/&quot;&gt;AI.dev&lt;/a&gt; or &lt;a href=&quot;http://aistudio.google.com/&quot;&gt;aistudio.google.com&lt;/a&gt; which will look like:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-database/02google-ai-studio-home.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio main page -- click Build&quot; alt=&quot;Google AI Studio main page -- click Build&quot; /&gt;
&lt;p&gt;Then, click on &lt;code&gt;Build&lt;/code&gt; on the left navigation, which will load the following page:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-database/03gias-build.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio Build page&quot; alt=&quot;Google AI Studio Build page&quot; /&gt;
&lt;p&gt;On this page, click the settings gear ⚙️on the top right:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-database/04gias-bulld-settings.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio Build page, model and framework settings&quot; alt=&quot;Google AI Studio Build page, model and framework settings&quot; /&gt;
&lt;p&gt;Then select the Pro model, at the time of writing, that is &lt;code&gt;Gemini 3.1 Pro Preview&lt;/code&gt; and make sure &lt;code&gt;Next.js&lt;/code&gt; is selected as the framework. You are using the pro model because it is more powerful, and in my experience, it follows instructions better and produces output with fewer or no errors. Then you can close the settings and proceed with the prompt.&lt;/p&gt;
&lt;h2 id=&quot;the-prompt-to-generate-the-app&quot; tabindex=&quot;-1&quot;&gt;The prompt to generate the app &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/google-ai-studio-database/#the-prompt-to-generate-the-app&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After that, you will paste the following prompt in the textbox below the text &lt;code&gt;Build your ideas with Gemini&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Create a simple login page, then show the user&#39;s profile page with the user&#39;s name, email, and a photo from the 
user&#39;s Google profile. On that page, the email should be visible only when the eye icon is clicked. 
The user can add and update their address and phone number. The user can also add their LinkedIn and GitHub profiles; 
all of that data, along with the user profile data pulled from the Google profile, is saved in the database. 

After saving the information, it is presented in a profile page. Please keep the form and the profile page separate. 
Please add the necessary validation for the address, phone number, and profile URLs. The application should be built 
in the green theme, and the buttons should be dark green.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and also select &lt;code&gt;Add database and auth&lt;/code&gt;, after that it will look as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-database/05prompt-in-gias-build.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio Build page prompt for Google login and simple profile page app&quot; alt=&quot;Google AI Studio Build page prompt for Google login and simple profile page app&quot; /&gt;
&lt;p&gt;You can use a different color theme, but for this tutorial, you will use the “green” color. Then you will click the &lt;code&gt;Build&lt;/code&gt; button to start generating the app.&lt;/p&gt;
&lt;p&gt;Google AI Studio will start generating the app as per the given prompt using the Gemini 3.1 pro model, as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-database/06gias-generating-app.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio geneating the profile page app&quot; alt=&quot;Google AI Studio geneating the profile page app&quot; /&gt;
&lt;p&gt;Then it will ask for permission to use Firebase and to accept its terms, as discussed next.&lt;/p&gt;
&lt;h2 id=&quot;using-firebase-for-login-and-data-storage&quot; tabindex=&quot;-1&quot;&gt;Using Firebase for login and data storage &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/google-ai-studio-database/#using-firebase-for-login-and-data-storage&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After generating the basic app, once the model decides to use Firebase following the given instructions in the prompt, Google AI Studio will ask for permission to use Firebase as well as select the region for the project:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-database/07gias-firebase-perms.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio geneating the profile page app enable Firebase&quot; alt=&quot;Google AI Studio geneating the profile page app enable Firebase&quot; /&gt;
&lt;p&gt;Here, you can select the region as &lt;code&gt;Oregon (us-west1)&lt;/code&gt; or any other region that makes sense for you, and click the &lt;code&gt;Enable&lt;/code&gt; button to continue the app generation process. You can also click the &lt;code&gt;Code&lt;/code&gt; button to see the generated code if that interests you.&lt;/p&gt;
&lt;p&gt;After I clicked “Enable”,  which automatically agreed to the terms and conditions for Firebase, it worked for almost 4 minutes (223 seconds) and generated the app with a Google login. In the background, it also created the necessary Firebase project and Firestore database:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-database/08app-generated.jpg&quot; loading=&quot;lazy&quot; title=&quot;Profile page app generated by Google AI Studio connected to Firebase Firestore&quot; alt=&quot;Profile page app generated by Google AI Studio connected to Firebase Firestore&quot; /&gt;
&lt;p&gt;Then you can test the app by clicking the &lt;code&gt;Login to Google&lt;/code&gt; button, notice that it adhered to the prompt and created the app with a &lt;code&gt;green&lt;/code&gt; theme. It will ask you to continue with your Google account as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-database/09google-login.jpg&quot; loading=&quot;lazy&quot; title=&quot;Profile page app generated by Google AI Studio Test Google Login&quot; alt=&quot;Profile page app generated by Google AI Studio Test Google Login&quot; /&gt;
&lt;p&gt;After you click continue and log in, it will show you the name and the profile picture on a form:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-database/10logged-in-app-form.jpg&quot; loading=&quot;lazy&quot; title=&quot;Profile page app generated by Google AI Studio login working&quot; alt=&quot;Profile page app generated by Google AI Studio login working&quot; /&gt;
&lt;p&gt;Notice that it also adheres to the prompt and hides the email address, making it visible only after clicking the eye button. You can click the edit profile button to add the details:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-database/11form-filled.jpg&quot; loading=&quot;lazy&quot; title=&quot;Profile page app generated by Google AI Studio profile form filled&quot; alt=&quot;Profile page app generated by Google AI Studio profile form filled&quot; /&gt;
&lt;p&gt;Then you can save the details by clicking the &lt;code&gt;Save Changes&lt;/code&gt; button. Keep in mind that your app may look different from the above screenshot as LLMs are non-deterministic. It should then load the profile page as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-database/12profile-page.jpg&quot; loading=&quot;lazy&quot; title=&quot;Profile page app generated by Google AI Studio profile working and data saved in Firestore&quot; alt=&quot;Profile page app generated by Google AI Studio profile working and data saved in Firestore&quot; /&gt;
&lt;p&gt;You can try the app in full-screen mode and try changing the details. You can also log out and log in again.&lt;/p&gt;
&lt;h2 id=&quot;data-in-firestore&quot; tabindex=&quot;-1&quot;&gt;Data in Firestore &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/google-ai-studio-database/#data-in-firestore&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When all of this is happening, it is no longer a frontend-only prototype app. The data is being saved in Firebase Firestore. To verify that, go to your &lt;a href=&quot;https://console.firebase.google.com/&quot;&gt;Firebase console&lt;/a&gt; – either a new project would have been created, or a Firestore database would have been added to your exiting firebase project.&lt;/p&gt;
&lt;p&gt;The database name would usually start with &lt;code&gt;ai-studio&lt;/code&gt; and end with the UUID of the AI Studio project, like &lt;code&gt;ai-studio-0042ecab-af9a-4dfb-b5b2-5e39156b6258&lt;/code&gt;. When you peek into the Firestore database, you will see the record saved from your &lt;code&gt;Green Profile&lt;/code&gt; app:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-database/13data-in-firestore.jpg&quot; loading=&quot;lazy&quot; title=&quot;Profile page app generated by Google AI Studio verfied that data is saved correctly in Firebase Firestore&quot; alt=&quot;Profile page app generated by Google AI Studio verfied that data is saved correctly in Firebase Firestore&quot; /&gt;
&lt;p&gt;There you have it: a full-stack Next.js app generated with Google AI Studio – one-shot with a single prompt that supports Google login and saves data to Firebase Firestore. You can add more features in the chat section of Google AI Studio, like pulling in data from Google Search or Google Maps.&lt;/p&gt;
&lt;p&gt;You can also deploy the app to Google Cloud Run using the publish feature (top-right button) and make it available to anyone in the world via an open URL. The possibilities are endless.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/google-ai-studio-database/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this guide, you started with a prompt to build a basic login-and-profile-page app using Google AI Studio. You generated the app and tested it. Finally, you could verify that the data was saved properly on Firestore in Firebase. Every app needs a login and profile page. You can use the chat section in Google AI Studio to explore other newly added features, such as retrieving data from Google Search and Google Maps, or even add intelligence with Gemini or image-generation capabilities to this app. Keep building!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Choosing the best git branching strategy for continuous delivery in your team</title>
		<link href="https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/"/>
		<updated>2026-03-22T10:51:32Z</updated>
		<id>https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/</id>
		<content type="html">&lt;p&gt;With AI doing some or most of the code writing (ahm! generation, if I may), being strong in the basics becomes even more crucial. If you have the word &amp;quot;engineer&amp;quot; in your job title, then knowing tools like Git and Docker has become inevitable. In this post, you will learn about the three main Git branching strategies and which one your team should choose for continuous delivery. This post will also cover real-life experiences and recommend a Git branching strategy that has proven more effective for the teams I&#39;ve been a part of. Let’s get started!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/git-branching-strategy-for-continuous-delivery/01git-branching-strategy-for-continuous-delivery.jpg&quot; title=&quot;Choose the right Git branching strategy for your team to enable continuous delivery&quot; alt=&quot;Choose the right Git branching strategy for your team to enable continuous delivery&quot; fetchpriority=&quot;high&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of Contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#continuous-integration-and-delivery&quot;&gt;Continuous integration and delivery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#gitflow&quot;&gt;Gitflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#github-flow&quot;&gt;GitHub Flow&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#deploying-before-merging&quot;&gt;Deploying before merging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#deploying-after-merging&quot;&gt;Deploying after merging&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#trunk-based-development&quot;&gt;Trunk-based development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#github-flow-strikes-the-right-balance&quot;&gt;GitHub flow strikes the right balance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;continuous-integration-and-delivery&quot; tabindex=&quot;-1&quot;&gt;Continuous integration and delivery &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#continuous-integration-and-delivery&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As stated in Atlassian’s &lt;a href=&quot;https://www.atlassian.com/continuous-delivery/continuous-integration&quot;&gt;blog post&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Continuous integration (CI) is the practice of automating the integration of code changes from multiple contributors into a single software project. It&#39;s a primary DevOps best practice, allowing developers to frequently merge code changes into a central repository where builds and tests then run.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So the focus is on integrating code changes into a single project or for better understanding a Git Branch.&lt;/p&gt;
&lt;p&gt;Similarly Continuous delivery as per &lt;a href=&quot;https://continuousdelivery.com/&quot;&gt;Jez Humble&lt;/a&gt; is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Continuous Delivery is the ability to get changes of all types—including new features, configuration changes, bug fixes and experiments—into production, or into the hands of users, safely and quickly in a sustainable way.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In other words, Continuous delivery is the practice of ensuring that your software is always in a releasable state. It means that whenever a feature is finished, tested, and approved, it can be deployed to production with the push of a button.&lt;/p&gt;
&lt;p&gt;But how do you organize your Git branches to support this seamless flow? If your branching model is too complex, continuous delivery becomes hard because the code gets stuck in a web of merges. If your branching model is too loose, you risk deploying broken code to your users. In the next section, you will learn about one of the older Git branching strategies, Gitflow.&lt;/p&gt;
&lt;h2 id=&quot;gitflow&quot; tabindex=&quot;-1&quot;&gt;Gitflow &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#gitflow&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When discussing version control workflows, it is impossible not to start with Gitflow. Introduced around 2010 by Vincent Dreisen in his &lt;a href=&quot;https://nvie.com/posts/a-successful-git-branching-model/&quot;&gt;blog post&lt;/a&gt; of the same name, it was one of the first formalized, moderately adopted branching models that gave teams a structured way to handle releases. For many years, this was considered a good standard for software development teams. It provided a strict, rule-based approach to managing features, releases, and hotfixes.&lt;/p&gt;
&lt;p&gt;In the Gitflow model, the &lt;code&gt;master&lt;/code&gt; branch is reserved exclusively for code currently running in production. You never commit directly to &lt;code&gt;master&lt;/code&gt;. Alongside it lives the &lt;code&gt;develop&lt;/code&gt; branch, which serves as the integration branch for all new features. When you want to build a new feature, you branch off from &lt;code&gt;develop&lt;/code&gt; to create a &lt;code&gt;feature/your-feature-name&lt;/code&gt; branch. Once your work is done, you merge it back into &lt;code&gt;develop&lt;/code&gt;.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/git-branching-strategy-for-continuous-delivery/02gitflow.jpg&quot; title=&quot;The complexity of Gitflow as a Git branching model&quot; alt=&quot;The complexity of Gitflow as a Git branching model&quot; /&gt;
&lt;p&gt;The Image is taken from this &lt;a href=&quot;https://medium.com/@zaghdoudi.mohamed/the-secret-to-better-version-control-gitflow-explained-6cbb094780a4&quot;&gt;blog post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This sounds fine in theory, but the complexity multiplies when it is time to release. Multiple changes from two or more software engineers would have been merged to develop. Big changes = big risk, and all of it goes to production in one go when the &lt;code&gt;develop&lt;/code&gt; branch is deployed. After deployment, the develop branch’s changes have to be merged into master.&lt;/p&gt;
&lt;p&gt;If a critical bug is found in production, you have to create a &lt;code&gt;hotfix&lt;/code&gt; branch off of &lt;code&gt;master&lt;/code&gt;, fix the bug, and then merge that hotfix into both &lt;code&gt;master&lt;/code&gt; and &lt;code&gt;develop&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Continuous delivery relies on small, frequent, and automated releases. Gitflow, by its very design, encourages batching features together into large, infrequent releases. The overhead of managing multiple long-lived branches, resolving complex merge conflicts between &lt;code&gt;develop&lt;/code&gt; and &lt;code&gt;master&lt;/code&gt;, and maintaining release branches creates massive friction.&lt;/p&gt;
&lt;p&gt;While Gitflow might still make sense for software with scheduled, versioned releases (like desktop applications or mobile apps that require app store approval), it is generally considered not up to the mark for modern web applications and APIs that aim for multiple deployments per day.&lt;/p&gt;
&lt;h2 id=&quot;github-flow&quot; tabindex=&quot;-1&quot;&gt;GitHub Flow &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#github-flow&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As the frustrations with Gitflow grew, a new, much simpler model emerged and quickly took the software engineering world by storm. This model gained massive popularity on GitHub with the introduction of the Pull Request (PR) mechanism. It is aptly named &lt;a href=&quot;https://docs.github.com/en/get-started/using-github/github-flow&quot;&gt;GitHub Flow&lt;/a&gt; or &lt;a href=&quot;https://geshan.com.np/blog/2014/12/do-you-git-your-code-follow-this-simplified-gitflow-model/&quot;&gt;simplified Gitflow&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;GitHub Flow is beautifully simple. Unlike Gitflow, it operates on the principle that there is only one long-lived branch: &lt;code&gt;master&lt;/code&gt; (often referred to as &lt;code&gt;main&lt;/code&gt; in modern repositories). The golden rule of GitHub Flow is that the &lt;code&gt;master&lt;/code&gt; branch must always be deployable.&lt;/p&gt;
&lt;p&gt;When you want to work on a new feature or fix a bug, you create a descriptively named branch directly off of &lt;code&gt;master&lt;/code&gt;. You write your code, commit your changes, and push the branch to the remote repository. Then, you open a Pull Request. The Pull Request is the heart of GitHub Flow. It is where code reviews happen, where automated tests are run by your Continuous Integration (CI) server, and where discussions about the architecture and logic take place. Once the code is reviewed and approved, it is merged into &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/git-branching-strategy-for-continuous-delivery/03github-flow.jpg&quot; title=&quot;GitHub flow is simpler than GitFlow&quot; alt=&quot;GitHub flow is simpler than GitFlow&quot; /&gt;
&lt;p&gt;The image is taken from this &lt;a href=&quot;https://www.alexhyett.com/git-flow-github-flow/&quot;&gt;blog post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Because of its simplicity, GitHub Flow is widely considered an excellent git branching strategy for continuous delivery. However, there are two distinct ways teams handle deployment in this flow, and you must choose the one that aligns with your team&#39;s risk appetite.&lt;/p&gt;
&lt;h3 id=&quot;deploying-before-merging&quot; tabindex=&quot;-1&quot;&gt;Deploying before merging &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#deploying-before-merging&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In this variation of GitHub Flow, the deployment happens before the code is merged into the &lt;code&gt;master&lt;/code&gt; branch. When you open a Pull Request, your CI/CD pipeline automatically provisions a temporary environment or deploys the feature branch to a staging server or a preview URL (also known as a deployment preview).&lt;/p&gt;
&lt;p&gt;You and your team test the feature branch thoroughly in this environment. Once the CI tests pass, the product manager approves the feature, and the QA checks pass (if any), you deploy that exact feature branch directly to the production environment. Only after the code runs successfully in production and has been verified as stable, do you merge the Pull Request into the &lt;code&gt;master&lt;/code&gt; branch. This could be done within minutes of the production deployment or may take some time, depending on the type of change or the feature deployed.&lt;/p&gt;
&lt;p&gt;This approach guarantees that the &lt;code&gt;master&lt;/code&gt; branch is always 100% stable. If a deployment fails, &lt;code&gt;master&lt;/code&gt; is untouched, and you can simply deploy  &lt;code&gt;master&lt;/code&gt; to roll back. Then, fix the issue on your feature branch and try again. This is a highly resilient way to handle continuous delivery, though it requires sophisticated deployment tooling to deploy from arbitrary branches or tags.&lt;/p&gt;
&lt;h3 id=&quot;deploying-after-merging&quot; tabindex=&quot;-1&quot;&gt;Deploying after merging &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#deploying-after-merging&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The second, and perhaps more common, variation is deploying &lt;em&gt;after&lt;/em&gt; merging to &lt;code&gt;master&lt;/code&gt;. In this scenario, once your Pull Request is approved and the automated tests pass, you merge the feature branch into &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Merging into &lt;code&gt;master&lt;/code&gt; triggers your continuous delivery pipeline. The pipeline takes the latest commit on &lt;code&gt;master&lt;/code&gt;, builds the application, and deploys it to production. You might choose to automatically create a Git tag for every deployment to keep track of versions.&lt;/p&gt;
&lt;p&gt;While this is easier to set up in most CI/CD tools, it comes with a significant caveat: &lt;code&gt;master&lt;/code&gt; will not always be stable. If a bug slips through the code review and automated tests, the pipeline will deploy broken code to production. Because the broken code has already been merged into &lt;code&gt;master&lt;/code&gt;, the &lt;code&gt;master&lt;/code&gt; branch is now broken.&lt;/p&gt;
&lt;p&gt;To recover, you must either quickly run the &lt;code&gt;git revert&lt;/code&gt; command to undo the merge commit and push the reversion through the pipeline, or roll back the deployment using your infrastructure tools (such as Kubernetes or other traffic-control mechanisms) while you fix the &lt;code&gt;master&lt;/code&gt; branch. This requires your team to be highly responsive and have excellent application-level logging and monitoring in place to detect issues immediately.&lt;/p&gt;
&lt;p&gt;Rollback would typically involve opening a pull request and merging it to remove the problematic change from master, so other software engineers can merge their work and deploy to production as normal.&lt;/p&gt;
&lt;p&gt;Regardless of which deployment variation you choose, GitHub Flow&#39;s reliance on a single long-lived branch drastically reduces merge conflicts and cognitive load, making it a useful git branching strategy for continuous delivery.&lt;/p&gt;
&lt;h2 id=&quot;trunk-based-development&quot; tabindex=&quot;-1&quot;&gt;Trunk-based development &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#trunk-based-development&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If GitHub Flow simplifies things by having only one long-lived branch, then Trunk-based development takes the concepts of simplicity and speed to their absolute extremes. In recent years, Trunk-based development has been &lt;a href=&quot;https://dora.dev/capabilities/trunk-based-development/&quot;&gt;promoted&lt;/a&gt; by DevOps experts and the DORA (DevOps Research and Assessment) reports as the ultimate practice for high-performing engineering teams.&lt;/p&gt;
&lt;p&gt;However, there is often a subtle confusion surrounding Trunk-based development. The confusion usually stems from whether it means having literally only one branch (&lt;code&gt;master&lt;/code&gt; or &amp;quot;trunk&amp;quot;) where everyone commits directly, or doing extremely small, short-lived feature branches that are merged multiple times a day.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/git-branching-strategy-for-continuous-delivery/04trunk-based-dev.jpg&quot; title=&quot;Trunk based development enables speed but has engineering team maturity as a requirement&quot; alt=&quot;Trunk based development enables speed but has engineering team maturity as a requirement&quot; /&gt;
&lt;p&gt;The image is taken from &lt;a href=&quot;https://trunkbaseddevelopment.com/&quot;&gt;Trunk Based Development&lt;/a&gt; website.&lt;/p&gt;
&lt;p&gt;In practice, modern Trunk-based development usually means the latter. Software engineers create very short-lived branches off the trunk, write a small batch of code, and merge it back into the trunk as quickly as possible—often several times a day. The goal is to completely eliminate the &amp;quot;merge hell&amp;quot; that occurs when long-running feature branches diverge too far from the main codebase. By integrating code continuously, you ensure that everyone is always working on the most up-to-date version of the software. This is where sync code review with &lt;a href=&quot;https://geshan.com.np/blog/2020/06/pair-programming-benefits-for-your-team/&quot;&gt;pair programming&lt;/a&gt; comes into play. In this age of AI written/generated code pair programming might be a dying art form.&lt;/p&gt;
&lt;p&gt;When evaluating a git branching strategy for continuous delivery, Trunk-based development is often seen as the holy grail. Because code is integrated so frequently, the continuous delivery pipeline is constantly firing, deploying small, incremental changes to production. This drastically reduces the blast radius of any given deployment. If a deployment breaks something, it is incredibly easy to pinpoint the cause because the changeset is so small.&lt;/p&gt;
&lt;p&gt;You cannot simply adopt Trunk-based development by telling your team to merge faster. Because you are constantly merging code into the trunk—even code for features that are only half-finished—using feature flags becomes absolutely essential for Trunk-based development.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://geshan.com.np/blog/2018/10/deployment-is-not-release/&quot;&gt;Feature flags&lt;/a&gt; (or feature toggles) allow you to wrap your new, half-done code in a conditional statement. The code is deployed to production, but the feature flag is turned off, so end users cannot see or interact with the new feature.&lt;/p&gt;
&lt;p&gt;For example, if you are building a new checkout flow, you will merge the database migrations on Monday, the backend API routes on Tuesday, and the frontend UI components on Wednesday. All of this code goes to production immediately via your continuous delivery pipeline. However, because the feature flag is disabled, customers continue to use the old checkout flow. Once the entire feature is complete and tested in production by internal staff, you simply flip the switch on your feature flag dashboard, and the new checkout flow is instantly available to your users.&lt;/p&gt;
&lt;p&gt;Trunk-based development requires a highly mature engineering culture. You must have an extensive suite of automated tests (unit, integration, and end-to-end) that run within a reasonable time. If your test suite takes an hour to run, you cannot merge multiple times a day. You also need excellent monitoring, fast build times (utilizing tools like &lt;a href=&quot;https://geshan.com.np/blog/2019/11/how-to-use-docker-multi-stage-build/&quot;&gt;Docker multi-stage builds&lt;/a&gt;), and a team that deeply understands how to break large tasks into tiny, independent, release-ready parts.&lt;/p&gt;
&lt;p&gt;If your team lacks this level of maturity, attempting Trunk-based development will likely result in broken builds, frustrated engineers, and a chaotic production environment.&lt;/p&gt;
&lt;h2 id=&quot;github-flow-strikes-the-right-balance&quot; tabindex=&quot;-1&quot;&gt;GitHub flow strikes the right balance &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#github-flow-strikes-the-right-balance&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You have now explored the three main contenders for your team&#39;s workflow. Gitflow is heavy and bureaucratic, hindering rapid deployment. Trunk-based development is incredibly fast and efficient, but it requires a level of engineering maturity, testing infrastructure, and feature flag management that many teams simply do not possess yet.&lt;/p&gt;
&lt;p&gt;When choosing a Git branching strategy for continuous delivery, you need a process that provides structure without bottlenecks and speed without chaos. This is exactly why GitHub flow strikes the right balance.&lt;/p&gt;
&lt;p&gt;You can think of GitHub Flow as existing in the &amp;quot;Goldilocks zone&amp;quot; of version control strategies. It is not too hot or too cold; it is just right.&lt;/p&gt;
&lt;p&gt;GitHub Flow provides enough structure to ensure code quality. By utilizing Pull Requests, you enforce a mandatory code review process. This ensures that at least one other software engineer looks at the code, checks for architectural issues, and verifies that the automated tests have passed before anything is merged. This serves as a crucial safety net, preventing bad code from reaching your users.&lt;/p&gt;
&lt;p&gt;At the same time, GitHub Flow is lightweight enough to support true continuous delivery. Because there is only one long-lived branch, developers do not have to navigate a maze of &lt;code&gt;develop&lt;/code&gt;, &lt;code&gt;release&lt;/code&gt;, and &lt;code&gt;hotfix&lt;/code&gt; branches. When a feature is ready, it is reviewed, merged, and deployed. The cycle time from writing code to delivering business value is kept short.&lt;/p&gt;
&lt;p&gt;For most teams—especially those building web applications, SaaS products, or microservices—GitHub Flow is the best fit.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It allows junior engineers to work safely within feature branches without the fear of breaking the trunk. It allows senior engineers to enforce quality standards through PR reviews. And it allows the operations and DevOps personnel to build straightforward, predictable CI/CD pipelines that trigger deployments based on actions taken on the &lt;code&gt;master&lt;/code&gt; branch.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Furthermore, GitHub Flow does not strictly prohibit the use of feature flags. In fact, as your team matures, you can easily incorporate feature flags into your GitHub Flow process. You can start by building smaller feature branches and merging them more quickly, gradually moving your team&#39;s culture closer to Trunk-based development without completely overhauling your branching strategy overnight.&lt;/p&gt;
&lt;p&gt;By choosing GitHub Flow, you are adopting a pragmatic, battle-tested methodology that aligns perfectly with the goals of agile software development and continuous delivery. It removes the unnecessary overhead of legacy models while providing the safety mechanisms needed to protect your production environment.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/03/git-branching-strategy-for-continuous-delivery/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Software engineering is a complex discipline, and delivering reliable software to your customers quickly is one of the hardest challenges a team faces. The tools and processes you choose should empower your developers, not hinder them.&lt;/p&gt;
&lt;p&gt;In this guide, you have explored the landscape of version control workflows. You learned that while Gitflow was a pioneer, its multiple long-lived branches make it too cumbersome for modern, rapid release cycles. You discovered that Trunk-based development offers incredible speed and integration, but demands a highly mature testing culture and strict reliance on feature flags.&lt;/p&gt;
&lt;p&gt;Ultimately, finding the right git branching strategy for continuous delivery comes down to evaluating your team&#39;s current capabilities and your business needs. For the vast majority of software engineering teams, GitHub Flow provides the perfect equilibrium. It leverages the power of Pull Requests for code quality while maintaining a single, deployable &lt;code&gt;master&lt;/code&gt; branch to enable fast, frictionless releases.&lt;/p&gt;
&lt;p&gt;Remember, your branching strategy is a means to an end. The ultimate goal is to deliver value to your users consistently and safely. Choose the strategy that keeps your team productive, your codebase clean, and your deployments boring and predictable. Happy coding and deploying!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to use an open model with your application using Docker Model Runner and Docker Compose [Part 2]</title>
		<link href="https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/"/>
		<updated>2026-01-25T10:53:32Z</updated>
		<id>https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/</id>
		<content type="html">&lt;p&gt;You can run open models with other apps, such as &lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/&quot;&gt;Ollama&lt;/a&gt;. Docker Model Runner shines when you want to connect your application’s Docker container with an open model. It feels more native to Docker to define both the application and the model in a single Docker Compose file. You will learn to do so in this tutorial with a demo app built with Node.js that talks to Smollm2, defined in a Docker Compose file. Let’s get going!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/docker-model-runner-docker-compose/01docker-model-runner-docker-compose.jpg&quot; title=&quot;Docker Model Runner: with Docker compose to run a Node.js app with Smollm2&quot; alt=&quot;Docker Model Runner: with Docker compose to run a Node.js app with Smollm2&quot; fetchpriority=&quot;high&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#prerequisites&quot;&gt;Prerequisites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#settings-for-the-api-on-docker-desktop&quot;&gt;Settings for the API on Docker Desktop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#the-demo-node-application&quot;&gt;The demo Node application&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#code-for-the-node-app&quot;&gt;Code for the Node app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#dockerfile-for-node-app&quot;&gt;Dockerfile for Node app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#docker-compose-file-with-node-app-and-smollm2-model&quot;&gt;Docker compose file with Node app and Smollm2 model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#running-the-app-with-docker-compose&quot;&gt;Running the app with Docker Compose&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;prerequisites&quot; tabindex=&quot;-1&quot;&gt;Prerequisites &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#prerequisites&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this part, similar to part 1 about &lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner/&quot;&gt;Docker Model Runner&lt;/a&gt;, you will need Docker Desktop installed with Docker Model Runner available. You will also need a decent hardware configuration to run the models, especially the ones with billions of parameters. On top of that, the following things will also be needed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Docker compose installed on your machine. Compose is bundled with Docker Desktop if it is not installed, please &lt;a href=&quot;https://docs.docker.com/compose/install/&quot;&gt;install&lt;/a&gt; it.&lt;/li&gt;
&lt;li&gt;A general idea of how Docker Compose works and how services communicate in Docker Compose would be good to know. You can get a refresher with this &lt;a href=&quot;https://geshan.com.np/blog/2024/04/docker-compose-tutorial/&quot;&gt;Docker Compose tutorial&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Given that, you can jump to the next section to configure the AI settings for Desktop.&lt;/p&gt;
&lt;h2 id=&quot;settings-for-the-api-on-docker-desktop&quot; tabindex=&quot;-1&quot;&gt;Settings for the API on Docker Desktop &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#settings-for-the-api-on-docker-desktop&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Any open model you pull and run can expose the APIs for chat completion and other functionalities. For this API to be accessible from your local machine or other containers (inside or outside a docker compose set up), you will need to &lt;code&gt;Enable host-side TCP support&lt;/code&gt; when Docker Model Runner (DMR) is enabled.&lt;/p&gt;
&lt;p&gt;To do this, you can follow the steps below:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open Docker Desktop&lt;/li&gt;
&lt;li&gt;Click on the gear icon (⚙️) on the top right to show the settings of Docker Desktop&lt;/li&gt;
&lt;li&gt;Then, click &lt;code&gt;AI&lt;/code&gt; on the left sidebar&lt;/li&gt;
&lt;li&gt;After that, make sure &lt;code&gt;Enable Docker Model Runner&lt;/code&gt; is checked&lt;/li&gt;
&lt;li&gt;Also confirm that the &lt;code&gt;Enable host-side TCP support&lt;/code&gt; checkbox is also checked&lt;/li&gt;
&lt;li&gt;Then click &lt;code&gt;Apply&lt;/code&gt; as seen below:&lt;/li&gt;
&lt;/ol&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/docker-model-runner-docker-compose/02docker-desktop-ai-models-settings.jpg&quot; loading=&quot;lazy&quot; title=&quot;Docker Desktop AI modles settings for Docker Model Runner&quot; alt=&quot;Docker Desktop AI modles settings for Docker Model Runner&quot; /&gt;
&lt;p&gt;By default, it will use port number &lt;code&gt;12343&lt;/code&gt;, adjust &lt;code&gt;CORS&lt;/code&gt; settings if you need to. In the next section, you will learn about the demo Node.js application you will use to chat with the Smollm2 model.&lt;/p&gt;
&lt;h2 id=&quot;the-demo-node-application&quot; tabindex=&quot;-1&quot;&gt;The demo Node application &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#the-demo-node-application&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For this tutorial, rather than writing a completely new application, you will reuse the &lt;a href=&quot;https://github.com/docker/hello-genai/tree/main/node-genai&quot;&gt;Node.js version&lt;/a&gt; of the &lt;a href=&quot;https://github.com/docker/hello-genai/&quot;&gt;hello-genai&lt;/a&gt; open-source code from Docker.&lt;/p&gt;
&lt;p&gt;You can use any open model like &lt;a href=&quot;https://hub.docker.com/r/ai/gemma3&quot;&gt;Gemma 3&lt;/a&gt; or &lt;a href=&quot;https://hub.docker.com/r/ai/ministral3&quot;&gt;Mistral 3&lt;/a&gt; or even &lt;a href=&quot;https://hub.docker.com/r/ai/functiongemma&quot;&gt;Gemma function&lt;/a&gt; if you want to build AI Agents. For this guide, you will use Smollm2&#39;s default variant with 360 M parameters as it general purpose and small enough to run on most machines. Next, you will see a snippet of the Node.js Express ap,p which calls the Smollm2 model.&lt;/p&gt;
&lt;h3 id=&quot;code-for-the-node-app&quot; tabindex=&quot;-1&quot;&gt;Code for the Node app &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#code-for-the-node-app&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The demo application connects a Node.js Express app to Smollm2, defined as a &lt;code&gt;model&lt;/code&gt; in the Docker Compose file. The app is reused from Docker&#39;s open-source &lt;a href=&quot;https://github.com/docker/hello-genai&quot;&gt;hello-genai&lt;/a&gt; repository. I have taken the &lt;a href=&quot;https://github.com/docker/hello-genai/tree/main/node-genai&quot;&gt;node-genai&lt;/a&gt; app and modified it a bit. It is a simple chat interface used to send prompts to the model and display the response on a webpage. There is a screenshot if this in action in the later section.&lt;/p&gt;
&lt;p&gt;Main part of the code for the Express.js app in the &lt;code&gt;node-genai&lt;/code&gt; app is as follows:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/api/chat&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; message &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Special command for model info&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;!modelinfo&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getModelName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;callLLMAPI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; response &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Error calling LLM API:&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Failed to get response from LLM&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Call the LLM API&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;callLLMAPI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;userMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; chatRequest &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getModelName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token literal-property property&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;system&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token literal-property property&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;You are a helpful assistant.&quot;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token literal-property property&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token literal-property property&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; userMessage&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; axios&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token function&quot;&gt;getLLMEndpoint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;            chatRequest&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token literal-property property&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&#39;Content-Type&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;application/json&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token literal-property property&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;30000&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 30 seconds&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;choices &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;choices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;choices&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;No response choices returned from API&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;API returned status code &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above code defines an Express.js API endpoint that sends user messages to a Large Language Model (LLM), which will be Smollm2 in the example, and returns the model’s reply.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;POST /api/chat&lt;/code&gt; route reads a message from the request body. If the message is the special command &lt;code&gt;!modelinfo&lt;/code&gt;, it immediately returns the current model name via &lt;code&gt;getModelName()&lt;/code&gt;. Otherwise, it calls &lt;code&gt;callLLMAPI(message)&lt;/code&gt; to get a response from the LLM. If anything fails, it logs the error and returns an HTTP 500 with a friendly error message.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;callLLMAPI&lt;/code&gt; function builds a request payload in a chat-style format: a system message that sets behavior (“You are a helpful assistant.”) and the user’s message. It sends this payload to the LLM endpoint (from &lt;code&gt;getLLMEndpoint()&lt;/code&gt;) using Axios with a JSON header and a 30-second timeout.&lt;/p&gt;
&lt;p&gt;If the API returns a valid response with choices, it extracts and trims the assistant’s reply. If no choices are returned or the API returns an error status, it throws a descriptive error so the caller can handle it properly. You can check the whole &lt;a href=&quot;https://github.com/geshan/hello-genai/blob/smollm2-node-24/node-genai/app.js&quot;&gt;app.js&lt;/a&gt; and the &lt;a href=&quot;https://github.com/geshan/hello-genai/blob/smollm2-node-24/node-genai/views/index.html&quot;&gt;view&lt;/a&gt; file too. In the next section, you will see the Dockerfile for this chat app.&lt;/p&gt;
&lt;h3 id=&quot;dockerfile-for-node-app&quot; tabindex=&quot;-1&quot;&gt;Dockerfile for Node app &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#dockerfile-for-node-app&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;Dockefile&lt;/code&gt; below is used to run the Node.js chat app built with Express.js.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;FROM node:24-alpine

WORKDIR /app

# Copy package files
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy application code
COPY . .

# Create directories if they don&#39;t exist
RUN mkdir -p views

# Expose port 8080
EXPOSE 8080

# Run the application
CMD [&amp;quot;node&amp;quot;, &amp;quot;app.js&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above Dockerfile builds a lightweight container for a Node.js application. It would have been better to use a &lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/blog/2019/11/how-to-use-docker-multi-stage-build/&quot;&gt;multistage Docker build&lt;/a&gt;, still, it is fine for a demo app.&lt;/p&gt;
&lt;p&gt;It starts from the &lt;code&gt;node:24-alpine&lt;/code&gt; base image, which provides Node.js 24 on a small Alpine Linux distribution. &lt;code&gt;WORKDIR /app&lt;/code&gt; sets &lt;code&gt;/app&lt;/code&gt; as the working directory inside the container.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;COPY package*.json ./&lt;/code&gt; copies package.json and package-lock.json (if present) first, allowing Docker to cache dependency installation. &lt;code&gt;RUN npm install&lt;/code&gt; installs all Node.js npm dependencies.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;COPY . .&lt;/code&gt; then copies the rest of the application source code into the container. &lt;code&gt;RUN mkdir -p views&lt;/code&gt; ensures a &lt;code&gt;views&lt;/code&gt; directory exists, preventing runtime errors if the app expects it.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;EXPOSE 8080&lt;/code&gt; documents that the app listens on port 8080. Finally, &lt;code&gt;CMD [&amp;quot;node&amp;quot;, &amp;quot;app.js&amp;quot;]&lt;/code&gt; defines the default command to start the application when the container runs.&lt;/p&gt;
&lt;p&gt;It is a good enough Dockefile for a small chat app like this. The next section details the Docker Compose file that links this app and container to the Smollm2 model.&lt;/p&gt;
&lt;h3 id=&quot;docker-compose-file-with-node-app-and-smollm2-model&quot; tabindex=&quot;-1&quot;&gt;Docker compose file with Node app and Smollm2 model &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#docker-compose-file-with-node-app-and-smollm2-model&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can link up the Node.js Chat app with the Smollm2 model easily using a Docker Compose file that looks like:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;services:&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  node-genai:&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    build:&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      context: &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      dockerfile: Dockerfile&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    ports:&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      - &lt;span class=&quot;token string&quot;&gt;&quot;8082:8080&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    environment:&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      - &lt;span class=&quot;token assign-left variable&quot;&gt;PORT&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    models:&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      - smollm2&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    healthcheck:&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      test: &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;CMD&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;curl&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;-f&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;http://localhost:8080/health&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      interval: 30s&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      timeout: 10s&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      retries: &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      start_period: 10s&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;models:&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  smollm2:&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    model: ai/smollm2&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    context_size: &lt;span class=&quot;token number&quot;&gt;8048&lt;/span&gt;&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above Docker Compose file defines a single service, &lt;code&gt;node-genai&lt;/code&gt;, and its related AI model configuration.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;node-genai&lt;/code&gt; service is built from the local directory using the specified &lt;code&gt;Dockerfile&lt;/code&gt; as seen in the above section. It maps port &lt;code&gt;8082&lt;/code&gt; on the host to port &lt;code&gt;8080&lt;/code&gt; inside the container, allowing external access to the Node.js app. The &lt;code&gt;PORT=8080&lt;/code&gt; environment variable configures the app’s listening port. The models section links this service to a model named &lt;code&gt;smollm2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A health check is a mechanism for verifying that the service is running correctly. It uses curl to call &lt;a href=&quot;http://localhost:8080/health&quot;&gt;http://localhost:8080/health&lt;/a&gt; every 30 seconds, with a 10-second timeout, three retries, and a 10-second startup grace period.&lt;/p&gt;
&lt;p&gt;The models section declares the Smollm2 model, referencing the image ai/smollm2 from DockerHub and setting a context size of 8048 tokens, which controls how much text the model considers at once.&lt;/p&gt;
&lt;p&gt;In the next section, you will run the chat app and the model together with Docker Compose.&lt;/p&gt;
&lt;h3 id=&quot;running-the-app-with-docker-compose&quot; tabindex=&quot;-1&quot;&gt;Running the app with Docker Compose &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#running-the-app-with-docker-compose&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To run the Node.js Chat app built with Express.js and Smollm2 attached to it, you can run the following command, which will first build the app and then run the app and the model in the  background:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; compose build &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; compose up &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will give an output like the following:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/docker-model-runner-docker-compose/03docker-model-runner-build-up.jpg&quot; loading=&quot;lazy&quot; title=&quot;Docker Model runner and Docker compose to build and run a Node.js App with Smollm2 open model&quot; alt=&quot;Docker Model runner and Docker compose to build and run a Node.js App with Smollm2 open model&quot; /&gt;
&lt;p&gt;You don’t need to build the container every time; you can do &lt;code&gt;docker compose up -d&lt;/code&gt; the next time. After that, to confirm that the containers are runnin,g you can execute:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; compose logs &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which will show something like:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/docker-model-runner-docker-compose/04docker-model-runner-compose-logs.jpg&quot; loading=&quot;lazy&quot; title=&quot;Docker Model runner and Docker compose logs of Node.js App with Smollm2 open model&quot; alt=&quot;Docker Model runner and Docker compose logs of Node.js App with Smollm2 open model&quot; /&gt;
&lt;p&gt;As the app is running on localhost port &lt;code&gt;8082&lt;/code&gt;, you can open your browser of choice and hit &lt;code&gt;http://localhost:8082&lt;/code&gt;, which will render something similar to:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/docker-model-runner-docker-compose/05dmr-nodejs-smollm2-app-running.jpg&quot; loading=&quot;lazy&quot; title=&quot;Docker Model runner and Docker compose Node.js App with Smollm2 open model running on the browser&quot; alt=&quot;Docker Model runner and Docker compose Node.js App with Smollm2 open model running on the browser&quot; /&gt;
&lt;p&gt;Docker includes an internal URL for the Model’s APIs at &lt;code&gt;http://model-runner.docker.internal/&lt;/code&gt;, which can be called by other containers. If you want to call it from localhost, it is running on port &lt;code&gt;12434&lt;/code&gt;. Then you can chat with Smolllm2 via the simple Node.js chat interface.&lt;/p&gt;
&lt;p&gt;To check the running containers, you can run &lt;code&gt;docker compose ps&lt;/code&gt;. To stop the containers, run &lt;code&gt;docker compose stop&lt;/code&gt;. To check the running models, you can run &lt;code&gt;docker model ps&lt;/code&gt;. To unload Smollm2, you can run &lt;code&gt;docker model unload smollm2&lt;/code&gt;; if you run &lt;code&gt;docker model ps&lt;/code&gt;, it will not be running Smollm2 anymore.&lt;/p&gt;
&lt;p&gt;In my experience, when running AI models locally, they can start to eat up CPU resources. So it is best to unload the model when you are done using it.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this post, you built on part 1, the introduction to Docker Model Runner, by connecting a simple Node.js (Express.js) chat app to the Smollm2 model using Docker Compose. You saw the code for the chat app, then a simple Dockerfile to run a Node.js app, and finally the Docker Compose file that connects the app to the open model (SmolM2 in this case). Then you ran it and saw it in action. Keep Learning!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Docker Model Runner: A beginner’s guide to running open models on your own machine [Part 1]</title>
		<link href="https://geshan.com.np/blog/2026/01/docker-model-runner/"/>
		<updated>2026-01-23T11:47:32Z</updated>
		<id>https://geshan.com.np/blog/2026/01/docker-model-runner/</id>
		<content type="html">&lt;p&gt;Docker has been the de facto containerization ecosystem for more than a decade now. It recently added a model runner that runs many open models locally via a &lt;code&gt;docker model&lt;/code&gt; command. In this post, you will learn how to use the Docker model runner to run smoll2 locally and interact with it. Let’s get started!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/docker-model-runner/01docker-model-runner.jpg&quot; title=&quot;Docker Model Runner: A beginner’s guide to running open models on your own machine&quot; alt=&quot;Docker Model Runner: A beginner’s guide to running open models on your own machine&quot; fetchpriority=&quot;high&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner/#prerequisites&quot;&gt;Prerequisites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner/#running-smollm2-with-docker-model-runner&quot;&gt;Running Smollm2 with Docker Model Runner&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner/#pull-a-model-with-docker-model-runner&quot;&gt;Pull a model with Docker model runner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner/#run-a-model&quot;&gt;Run a model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner/#remove-a-model&quot;&gt;Remove a model&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;prerequisites&quot; tabindex=&quot;-1&quot;&gt;Prerequisites &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner/#prerequisites&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Below are some prerequisites you will need installed on the machine you want to run Docker Model Runner (DMR)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Docker Model Runner (DMR) is available from Docker Desktop version 4.40 or later, so you will need Docker Desktop version 4.40 or later installed&lt;/li&gt;
&lt;li&gt;Your hardware will also need to support the functionality, which has GPU backends. I am running the commands shown in this tutorial on a Mac with an Apple Silicon chip&lt;/li&gt;
&lt;li&gt;If you are running Docker Engine on a Linux distro without Docker Desktop, you will need to install the &lt;code&gt;docker-model-plugin&lt;/code&gt; separately with a command like &lt;code&gt;sudo apt-get install docker-model-plugin&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The easiest way to check if Docker Model Runner (DMR) is available on your machine with Docker Desktop or Docker engine installed is by running:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; model version&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you see a version for your Docker Model Runner with the Docker Engine Kind, DMR is available on your machine. In my case, I am running Docker Model Runner version 1.0.6 on Docker Desktop 4.57.0.&lt;/p&gt;
&lt;p&gt;Given the prerequisites have been mentioned, in the next section, you will run Smollm2 with Docker Model Runner(DMR).&lt;/p&gt;
&lt;h2 id=&quot;running-smollm2-with-docker-moder-runner&quot; tabindex=&quot;-1&quot;&gt;Running Smollm2 with Docker Moder Runner &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner/#running-smollm2-with-docker-moder-runner&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Given that you have tested that you have Docker and Docker Model Runner installed on your system of choice. You will be running the &lt;a href=&quot;https://huggingface.co/collections/HuggingFaceTB/smollm2&quot;&gt;Smollm2&lt;/a&gt; model’s default/latest variant, which is the 360 million parameter one. It is 256.38 MB in size. You might ask why Smollm2. In my opinion, it is small enough to download quickly and does a good job of answering basic questions.&lt;/p&gt;
&lt;p&gt;If you are not very confident with Docker commands, you can read the &lt;a href=&quot;https://geshan.com.np/blog/2024/04/docker-for-beginners/&quot;&gt;Docker for beginners&lt;/a&gt; tutorial for a refresher on Docker. You can also read the post on &lt;a href=&quot;https://geshan.com.np/blog/2022/05/docker-commands/&quot;&gt;Docker commands&lt;/a&gt; like docker pull, docker images, docker run, and others.&lt;/p&gt;
&lt;h3 id=&quot;pull-a-model-with-docker-model-runner&quot; tabindex=&quot;-1&quot;&gt;Pull a model with Docker model runner &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner/#pull-a-model-with-docker-model-runner&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can run the following command to pull &lt;a href=&quot;https://hub.docker.com/r/ai/smollm2&quot;&gt;Smoll2&lt;/a&gt; from DockerHub:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; model pull ai/smollm2:latest&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The output will look as follows after Smollm2 open model (by Huggingface) is downloaded to your machine:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/docker-model-runner/02docker-model-runner-pull.jpg&quot; loading=&quot;lazy&quot; title=&quot;Docker Model Runner pulling Smollm2 from DockerHub&quot; alt=&quot;Docker Model Runner pulling Smollm2 from DockerHub&quot; /&gt;
&lt;p&gt;You can also pull the model from Hugging Face.&lt;/p&gt;
&lt;p&gt;You can use the Docker Desktop interface to pull the same model after searching in the DockerHub tab, as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/docker-model-runner/03docker-desktop-search-model.jpg&quot; loading=&quot;lazy&quot; title=&quot;Search for Smollm2 on DockerHub from Docker Desktop Models section&quot; alt=&quot;Search for Smollm2 on DockerHub from Docker Desktop Models section&quot; /&gt;
&lt;p&gt;But a single command is much easier than following 4 steps on the GUI. Next, to see if the model is pulled (downloaded) correctly, you can run the following command to list all models:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; model list&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will show the following output.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/docker-model-runner/04docker-model-runner-list-models.jpg&quot; loading=&quot;lazy&quot; title=&quot;Docker model runner CLI listing pulled models&quot; alt=&quot;Docker model runner CLI listing pulled models&quot; /&gt;
&lt;p&gt;After that, you can run the Smollm2 35-million-parameter model as discussed next.&lt;/p&gt;
&lt;h3 id=&quot;run-a-model&quot; tabindex=&quot;-1&quot;&gt;Run a model &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner/#run-a-model&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To run the pulled Smollm2 model, you will need to run the following command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; model run ai/smollm2 &lt;span class=&quot;token string&quot;&gt;&quot;Why is the sky blue? Answer in a single sentence.&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will result in something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;The sky is blue because it scatters sunlight in all directions and our eyes are more sensitive to shorter wavelengths of light, like blue and violet.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To run the model in an interactive question-answer mode, you can execute the following command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; model run ai/smollm2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After that, you can chat with the model as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/docker-model-runner/05dmr-chat-with-smollm.jpg&quot; loading=&quot;lazy&quot; title=&quot;Docker model runner running Smollm2 and user having a with with it&quot; alt=&quot;Docker model runner running Smollm2 and user having a with with it&quot; /&gt;
&lt;p&gt;To exit the chat, you can type &lt;code&gt;/bye&lt;/code&gt; on the command prompt, and it will take you back to your shell/CLI. If you type &lt;code&gt;/?&lt;/code&gt;, it will give you more help options as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/docker-model-runner/06dmr-smollm2-exit.jpg&quot; loading=&quot;lazy&quot; title=&quot;Exit the chat and other help options for a model running with Docker Model Runner&quot; alt=&quot;Exit the chat and other help options for a model running with Docker Model Runner&quot; /&gt;
&lt;p&gt;You can look at all the prompts given to the model on Docker Desktop by clicking the model in the &lt;code&gt;Models&lt;/code&gt; screen, which is &lt;code&gt;Smoll2&lt;/code&gt; in this case:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/docker-model-runner/07docker-desktop-models-list.jpg&quot; loading=&quot;lazy&quot; title=&quot;Listing pulled models in Docker Desktop Models section&quot; alt=&quot;Listing pulled models in Docker Desktop Models section&quot; /&gt;
&lt;p&gt;Then click the &lt;code&gt;Requests&lt;/code&gt; tab:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/docker-model-runner/08docker-desktop-listing-prompts.jpg&quot; loading=&quot;lazy&quot; title=&quot;Listing ran prompts on Desktop Models section Requests tab&quot; alt=&quot;Listing ran prompts on Desktop Models section Requests tab&quot; /&gt;
&lt;p&gt;The logs don’t stay for long, though. You can see that the model is responding very fast -- under 6 ms.&lt;/p&gt;
&lt;p&gt;You can also chat with the model from the &lt;code&gt;Chat&lt;/code&gt; tab, as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/docker-model-runner/09docker-desktop-chat-with-model.jpg&quot; loading=&quot;lazy&quot; title=&quot;Chatting with Smollm2 open model on Docker Desktop&quot; alt=&quot;Chatting with Smollm2 open model on Docker Desktop&quot; /&gt;
&lt;p&gt;You can also inspect the mode’s architecture, parameters, and other information in the &lt;code&gt;Inspect&lt;/code&gt; tab:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/docker-model-runner/10docker-desktop-model-inspect.jpg&quot; loading=&quot;lazy&quot; title=&quot;Looking at the model information in Docker Desktop&quot; alt=&quot;Looking at the model information in Docker Desktop&quot; /&gt;
&lt;p&gt;The above information is similar to running the &lt;code&gt;docker model inspect smollm2&lt;/code&gt; command. You can find the list of commands supported by &lt;code&gt;docker model&lt;/code&gt; in the official Docker &lt;a href=&quot;https://docs.docker.com/reference/cli/docker/model/&quot;&gt;documentation&lt;/a&gt;. For instance, you can see the running models with &lt;code&gt;docker model ps&lt;/code&gt; and try out other commands similar to the main Docker CLI.&lt;/p&gt;
&lt;p&gt;Smollm2 is an example; at the time of writing, there are &lt;a href=&quot;https://hub.docker.com/u/ai&quot;&gt;57 models&lt;/a&gt; available on Docker Hub. You can pull in Llama, Gemma, Qwen, Kimi, or any other open model of your choice and run it on your machine.&lt;/p&gt;
&lt;p&gt;The best part is that it is local, fast, and you don’t even need internet to run a model once it is downloaded and running on your local machine.&lt;/p&gt;
&lt;h3 id=&quot;remove-a-model&quot; tabindex=&quot;-1&quot;&gt;Remove a model &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner/#remove-a-model&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you want to remove the Smollm2 model, you can run &lt;code&gt;docker model rm smollm2&lt;/code&gt;, which will delete the model given an output like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Untagged: index.docker.io/ai/smollm2:latest 
Deleted: sha256:354bf30d0aa3af413d2aa5ae4f23c66d78980072d1e07a5b0d776e9606a2f0b9
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There you go, you pulled a model with Docker Model runner and were able to run it. You had a quick chat with Smollm2. In the next part, you will learn how to connect a model with your own app using &lt;a href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner-docker-compose/&quot;&gt;Docker Model Runner and Docker Compose&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2026/01/docker-model-runner/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this quick and useful tutorial, you learned how to pull an open model like Smollm2 from DockerHub and run it on your local machine. This is just scratching the surface, with Docker Model runner you can run many open models on your machine from Gemma to Llama, and from Qwen to Deepseek deepening on your hardware. Keep learning!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Recap 2025: Blogging, public speaking, tech community work, and other things</title>
		<link href="https://geshan.com.np/blog/2025/12/recap-2025/"/>
		<updated>2025-12-25T10:47:52Z</updated>
		<id>https://geshan.com.np/blog/2025/12/recap-2025/</id>
		<content type="html">&lt;p&gt;This will be the seventh year I have written a recap or “wrap” of the year that has passed. I started writing these in &lt;a href=&quot;https://geshan.com.np/blog/2019/12/2019-year-in-review/&quot;&gt;2019&lt;/a&gt;, and I have continued writing them since then. In this one, I will reflect on some of the crucial professional accomplishments I achieved in 2025. Fasten your seatbelts!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/recap-2025/01recap-2025.jpg&quot; title=&quot;Professional recap of my year 2025 symbolized by a car side view mirror&quot; alt=&quot;Professional recap of my year 2025 symbolized by a car side view mirror&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#highlights&quot;&gt;Highlights&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#public-speaking-in-2025&quot;&gt;Public speaking in 2025&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#blog-posts-in-2025&quot;&gt;Blog posts in 2025&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#most-viewed-blog-posts-of-2025&quot;&gt;Most viewed blog posts of 2025&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#being-a-guest-on-a-podcast&quot;&gt;Being a guest on a podcast&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#community-activities&quot;&gt;Community activities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#listening-to-podcasts&quot;&gt;Listening to Podcasts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#misc&quot;&gt;Misc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;highlights&quot; tabindex=&quot;-1&quot;&gt;Highlights &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#highlights&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Below are the highlights of 2025 in a nutshell:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I did 10 in-person &lt;a href=&quot;https://github.com/geshan/public-speaking&quot;&gt;public talks/workshops&lt;/a&gt; this year. I did a couple more at work. In addition to Sydney, I gave talks at &lt;a href=&quot;https://gdg.community.dev/events/details/google-gdg-canberra-presents-build-with-ai-workshop/cohost-gdg-on-campus-the-australian-national-university-canberra-australia/&quot;&gt;Canberra&lt;/a&gt;, &lt;a href=&quot;https://gdg.community.dev/events/details/google-gdg-perth-presents-devfest-perth-2025-ai-careers-amp-community/&quot;&gt;Perth&lt;/a&gt;, and &lt;a href=&quot;https://www.linkedin.com/feed/update/urn:li:activity:7362071245305102336/&quot;&gt;Shanghai, China&lt;/a&gt; too.&lt;/li&gt;
&lt;li&gt;I wrote 16+1 (this post) blog posts this year, much less than &lt;a href=&quot;https://geshan.com.np/stats.json&quot;&gt;previous years&lt;/a&gt;, which I had stated in &lt;a href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/blog/2024/12/recap-2024/&quot;&gt;last year’s recap&lt;/a&gt;, too. And I still beat my goal.&lt;/li&gt;
&lt;li&gt;I was a guest on one podcast this year, &lt;a href=&quot;https://www.youtube.com/watch?v=Ebhe84ClLGg&quot;&gt;Everyday Karma&lt;/a&gt;, where Saroj asked me many meaningful questions. The Podcast is in Nepali.&lt;/li&gt;
&lt;li&gt;I helped organize nine meetups and one conference for GDG Sydney, and I have transferred the GDG Sydney organizing part to the next generation.&lt;/li&gt;
&lt;li&gt;I have listened to 9 days, 19 hours of podcasts this year, from the Pragmatic Engineer to Practical AI and from Tech Lead Journal to Kubernetes Podcast.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Below are some of the details of the review of this year.&lt;/p&gt;
&lt;h2 id=&quot;public-speaking-in-2025&quot; tabindex=&quot;-1&quot;&gt;Public speaking in 2025 &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#public-speaking-in-2025&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In 2025, I did 10 public talks (or workshops), most of them in Sydney. In November, I gave two talks at two conferences and participated in one panel discussion. In August, I gave a talk to mostly Google Developer Experts (GDEs) at Shanghai, China, for the GDE Summit APAC.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/recap-2025/02talks-2025.jpg&quot; loading=&quot;lazy&quot; title=&quot;Some of my talks from 2025 from Shanghai, China, Perth, Canberra and Sydney&quot; alt=&quot;Some of my talks from 2025 from Shanghai, China, Perth, Canberra and Sydney&quot; /&gt;
&lt;p&gt;This year, I did the most talks in a year, which was 10. The last record was in 2019, with eight talks, all in Sydney. You can view all of my talks since 2016 listed on this &lt;a href=&quot;https://github.com/geshan/public-speaking&quot;&gt;GitHub repository&lt;/a&gt;. I wrote talks/workshops on six new topics this year and gave &lt;a href=&quot;https://www.linkedin.com/feed/update/urn:li:activity:7342721813543645184/&quot;&gt;five talks by June&lt;/a&gt;. Some of the topics were &lt;a href=&quot;https://docs.google.com/presentation/d/1xpOBI1FoQR0HmQbG-GHodShBQ06z6jV74IVjEpWPINo/edit?usp=sharing&quot;&gt;Feature flags&lt;/a&gt;, &lt;a href=&quot;https://docs.google.com/presentation/d/1ETu4612YqE89wcMz622Sbp9nVr6kyoDhxtccZGSTvYo/edit?usp=sharing&quot;&gt;Image to geolocation using Gemini&lt;/a&gt;, and &lt;a href=&quot;https://docs.google.com/presentation/d/1MmHU7_EoO9BOd5_KuE60ZIgG8fpjAjPe3AfgFbwihWg/edit?usp=drive_link&quot;&gt;Building a resume reviewer app with Gemini&lt;/a&gt;. One workshop has already been planned for &lt;a href=&quot;https://gdg.community.dev/events/details/google-gdg-darwin-presents-build-with-ai-2026/&quot;&gt;April 2026 in Darwin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;blog-posts-in-2025&quot; tabindex=&quot;-1&quot;&gt;Blog posts in 2025 &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#blog-posts-in-2025&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This year, I wrote 16 blog posts (the target was 14), and with this recap, it will be 17. One thing I did differently this year was to refresh a blog post about &lt;a href=&quot;https://geshan.com.np/blog/2021/01/free-nodejs-hosting/&quot;&gt;free Node.js hosting&lt;/a&gt; from 2021, with help from &lt;a href=&quot;https://www.linkedin.com/in/aaasisss/&quot;&gt;Ashis&lt;/a&gt;, &lt;a href=&quot;https://www.linkedin.com/in/yash-shrestha/&quot;&gt;Yash&lt;/a&gt;, and &lt;a href=&quot;https://www.linkedin.com/in/bibekdallakoti/&quot;&gt;Bibek&lt;/a&gt;. Thanks for updating the post. And after the refresh, it has climbed back up in the Google Search Results.&lt;/p&gt;
&lt;p&gt;Unsurprisingly, 13 out of the 16 posts have been about &lt;a href=&quot;https://geshan.com.np/blog/categories/ai/&quot;&gt;AI&lt;/a&gt;, and that is what sells in the current times. Speaking of which, the most popular blog posts from 2025 are as follows.&lt;/p&gt;
&lt;h3 id=&quot;most-viewed-blog-posts-of-2025&quot; tabindex=&quot;-1&quot;&gt;Most viewed blog posts of 2025 &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#most-viewed-blog-posts-of-2025&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The five most popular blog posts written in 2025 are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/&quot;&gt;Ollama commands: How to use Ollama in the command line [Part 2]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/&quot;&gt;How to use Ollama and Open WebUI with Docker Compose [Part 4]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/&quot;&gt;Using Ollama APIs to generate responses and much more [Part 3]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/&quot;&gt;How to use NotebookLM: A practical guide with examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/01/ollama-google-cloud-run/&quot;&gt;How to run (any) open LLM with Ollama on Google Cloud Run [Step-by-step]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The top three are from the Ollama Series I wrote in Feb 2025. There were almost 500K users on my blog in 2025, browsing through nearly a million pages. I will keep the same goal of 14+1 (recap) posts for 2026.&lt;/p&gt;
&lt;p&gt;My blog landed on one of the top 290K websites in the world for November 2025, as per Similaweb:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/recap-2025/03blog-rank-similarweb.jpg&quot; loading=&quot;lazy&quot; title=&quot;Blog rank at the top 290K websites in the worlds on Similarweb&quot; alt=&quot;Blog rank at the top 290K websites in the worlds on Similarweb&quot; /&gt;
&lt;p&gt;And between the top 220K to 240K websites in the world as per the &lt;a href=&quot;https://tranco-list.eu/api/ranks/domain/geshan.com.np&quot;&gt;Tranco Rankings&lt;/a&gt;. Next, you can read about a podcast on which I appeared as a guest.&lt;/p&gt;
&lt;h2 id=&quot;being-a-guest-on-a-podcast&quot; tabindex=&quot;-1&quot;&gt;Being a guest on a podcast &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#being-a-guest-on-a-podcast&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This year, I was a guest on only one podcast: the Everyday Karma podcast, hosted by Saroj Dahal. Below is the audio of the podcast, and it is in the Nepali language:&lt;/p&gt;
&lt;div style=&quot;position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%; margin-bottom: 1rem;&quot;&gt;
  &lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/Ebhe84ClLGg&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; style=&quot;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;The podcast was released towards the end of January 2025.&lt;/p&gt;
&lt;h2 id=&quot;community-activities&quot; tabindex=&quot;-1&quot;&gt;Community activities &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#community-activities&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As the organizer of GDG Sydney, I helped organize 15+ evening meetups and the full-day, three-track conference: &lt;a href=&quot;https://gdg-sydney-devfest-2025.sessionize.com/&quot;&gt;DevFest Sydney 2025&lt;/a&gt; in mid-October this year. I attended the Google For Developers Summit, having both Google Developer Group(s) (GDG) organizers and Google Developer Expert(s) (GDEs) from Australia and New Zealand in mid-March. It was amazing, the best part was meeting all the participants in person (in Sydney). I also attended the &lt;a href=&quot;https://cloudonair.withgoogle.com/events/summit-sydney-2025&quot;&gt;Google Cloud Summit 2025&lt;/a&gt; at the end of July. A quick summary of the events is below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/recap-2025/04community-activities-2025.jpg&quot; loading=&quot;lazy&quot; title=&quot;Some photos from the events I helped organize in 2025, the biggest one being DevFest Sydney 2025 in October&quot; alt=&quot;Some photos from the events I helped organize in 2025, the biggest one being DevFest Sydney 2025 in October&quot; /&gt;
&lt;p&gt;I could not attend the AWS Summit, but I did attend some other meetups in Sydney. As usual, I helped around eight people with their first (or second) talk to kickstart their public speaking journey.&lt;/p&gt;
&lt;h2 id=&quot;listening-to-podcasts&quot; tabindex=&quot;-1&quot;&gt;Listening to podcasts &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#listening-to-podcasts&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In 2025, I listened to 9 days and 21 hours of audio content. That is a total of 237 hours in a year, averaging at around 39 minutes a day. Below are the podcasts I listened to this year:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/recap-2025/05podcast-listening.jpg&quot; loading=&quot;lazy&quot; title=&quot;Listening to almost 39 mins of podcasts on average for the whole year is not a small feat&quot; alt=&quot;Listening to almost 39 mins of podcasts on average for the whole year is not a small feat&quot; /&gt;
&lt;p&gt;Mostly, the podcasts were technical, but I also listened to some non-technical ones like Investopoly. You can also see the &lt;a href=&quot;https://podcasts-2025.geshan.workers.dev/&quot;&gt;full breakdown of each podcast&lt;/a&gt; I have heard in 2025.&lt;/p&gt;
&lt;h2 id=&quot;misc&quot; tabindex=&quot;-1&quot;&gt;Misc &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#misc&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Some of the other things that came to fruition this year:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I reached more than &lt;a href=&quot;https://www.linkedin.com/feed/update/urn:li:activity:7290889028432711681/&quot;&gt;10K followers on LinkedIn&lt;/a&gt; in March this year.&lt;/li&gt;
&lt;li&gt;Made &lt;a href=&quot;https://github.com/geshan?tab=overview&amp;amp;from=2025-12-01&amp;amp;to=2025-12-25&quot;&gt;975+ public contributions on GitHub&lt;/a&gt; (33% less than last year) and also completed Hacktoberfest&lt;/li&gt;
&lt;li&gt;The side project this year was to help some people get into the habit of listening to podcasts. We gamified it in the &lt;a href=&quot;https://xplorers-website.vercel.app/&quot;&gt;Xplorers&lt;/a&gt; group, and we got it done in style.&lt;/li&gt;
&lt;li&gt;Similar to previous years, I did many 1:1 chats with people about career, finding a tech job in Australia, and similar topics. I hope it has helped many individuals.&lt;/li&gt;
&lt;li&gt;I have written three blog posts this year around how AI can help you with &lt;a href=&quot;https://geshan.com.np/blog/categories/job-search/&quot;&gt;job search&lt;/a&gt;. It would be good for you to read them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Looking back, I achieved some of the goals I set in 2025, and I have set some goals for 2026. Hopefully, I will achieve them too.&lt;/p&gt;
&lt;p&gt;A couple of new things will be coming in January or February of 2026. Stay tuned to my &lt;a href=&quot;https://www.linkedin.com/in/geshan/&quot;&gt;LinkedIn&lt;/a&gt;, the only social media I use.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/recap-2025/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Looking back, 2025 was a good year. I attended many tech events and was fortunate to be a guest on a podcast. I also wrote the 15+ blog posts (a lot less than previous years with 25 blog posts), which still exceeded my target.&lt;/p&gt;
&lt;p&gt;I look forward to 2026, but I will scale back on things I have been doing, like blogging and community activities, to focus on something else. Merry Christmas and Happy New Year 2026.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to use Gemini Live audio as an interviewer for a software engineer’s job (with video)</title>
		<link href="https://geshan.com.np/blog/2025/12/gemini-live-audio/"/>
		<updated>2025-12-16T10:48:25Z</updated>
		<id>https://geshan.com.np/blog/2025/12/gemini-live-audio/</id>
		<content type="html">&lt;p&gt;Wouldn’t it be great if you had an on-demand experienced software engineer interviewer who could take a technical interview whenever and wherever you wanted? Yes, it is possible with &lt;a href=&quot;https://gemini.google/overview/gemini-live/&quot;&gt;Gemini Live&lt;/a&gt; and the &lt;a href=&quot;https://blog.google/products/gemini/gemini-audio-model-updates/&quot;&gt;native audio&lt;/a&gt; feature on Google AI Studio, along with a well-crafted prompt. The best part is that it&#39;s free. Let’s get started!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-live-audio/01gemini-live-audio.jpg&quot; title=&quot;Use Gemini Live Audio feature to do mock software enginer interview&quot; alt=&quot;Use Gemini Live Audio feature to do mock software enginer interview&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/gemini-live-audio/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/12/gemini-live-audio/#gemini-multimodal-capabilities&quot;&gt;Gemini Multimodal capabilities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/12/gemini-live-audio/#gemini-live-native-audio-on-google-ai-studio&quot;&gt;Gemini Live Native Audio on Google AI Studio&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/12/gemini-live-audio/#steps-to-use-gemini-live-audio-as-an-interviewer&quot;&gt;Steps to use Gemini Live audio as an interviewer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/12/gemini-live-audio/#switching-modes&quot;&gt;Switching modes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/12/gemini-live-audio/#demo-video&quot;&gt;Demo video&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/12/gemini-live-audio/#other-inteview-ideas&quot;&gt;Other interview ideas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/12/gemini-live-audio/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;gemini-multimodal-capabilities&quot; tabindex=&quot;-1&quot;&gt;Gemini Multimodal capabilities &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/gemini-live-audio/#gemini-multimodal-capabilities&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Google Gemini LLM has multimodal capabilities. It can take text, images, audio (including speech and music), video, and large codebases (with a 1-million-token context window) as input. With that input, it can output text, image, audio, and code. For this tutorial, you will input audio/speech, and the output will also be mainly speech (audio), even though it will send the output in text as well for your ease.&lt;/p&gt;
&lt;p&gt;To use Gemini with the live native audio feature as an interviewer for a software engineering job (backend engineer), you will use the Google AI Studio &lt;a href=&quot;https://aistudio.google.com/live&quot;&gt;live feature&lt;/a&gt; as discussed next.&lt;/p&gt;
&lt;h2 id=&quot;gemini-live-native-audio-on-google-ai-studio&quot; tabindex=&quot;-1&quot;&gt;Gemini Live Native Audio on Google AI Studio &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/gemini-live-audio/#gemini-live-native-audio-on-google-ai-studio&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To use the Gemini Live Native Audio feature to behave like an experienced software engineer who will take an interview for a backend engineer role, you will need to go to the &lt;a href=&quot;https://aistudio.google.com/live&quot;&gt;live feature&lt;/a&gt; in Google AI Studio. It is one of the easiest and most accessible ways to use this feature. At the time of writing, the model available for the Live feature is &lt;code&gt;Gemini 2.5 Flash Native Audio Preview 12-2025&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;steps-to-use-gemini-live-audio-as-an-interviewer&quot; tabindex=&quot;-1&quot;&gt;Steps to use Gemini Live audio as an interviewer &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/gemini-live-audio/#steps-to-use-gemini-live-audio-as-an-interviewer&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;First, go to &lt;a href=&quot;https://aistudio.google.com/&quot;&gt;Google AI Studio&lt;/a&gt; and click the &lt;code&gt;Playground&lt;/code&gt; link available in the left sidebar as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-live-audio/02gias-playground.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio Playground link&quot; alt=&quot;Google AI Studio Playground link&quot; /&gt;
&lt;p&gt;After that, click the &lt;code&gt;Live&lt;/code&gt; button available under the &lt;code&gt;Google AI Studio&lt;/code&gt; logo then click the &lt;code&gt;Gemini 2.5 Flash Native Audio Preview 12-2025&lt;/code&gt; option available:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-live-audio/03gias-live.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio Live Audio feature selection&quot; alt=&quot;Google AI Studio Live Audio feature selection&quot; /&gt;
&lt;p&gt;Then, on the right sidebar, change the voice from &lt;code&gt;Zephyr&lt;/code&gt; to &lt;code&gt;Puck&lt;/code&gt;, it is a better voice (in my opinion) as you will chat with that voice for minutes:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-live-audio/04gias-live-voice.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio change voice to Puck&quot; alt=&quot;Google AI Studio change voice to Puck&quot; /&gt;
&lt;p&gt;Subsequently, scroll down to turn on &lt;code&gt;Thinking mode&lt;/code&gt;, then &lt;code&gt;Affective dialog&lt;/code&gt;, and lastly &lt;code&gt;Grounding with Google Search&lt;/code&gt; as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-live-audio/05gias-live-settings.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio Live feature settings panel&quot; alt=&quot;Google AI Studio Live feature settings panel&quot; /&gt;
&lt;p&gt;When you hover over each, it will tell you what the setting does, for instance, &lt;code&gt;Affective dialog&lt;/code&gt; on will: &lt;code&gt;Let Gemini adapt its response style to the input expression and tone&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;After that, copy the prompt below and paste it into the &lt;code&gt;Start typing a prompt&lt;/code&gt; text box:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;You are a seasoned backend software engineer with over 20 years of experience and 
you have taken more than 100 backend-focused technical interviews.
For this task, you will act as an experienced interviewer, too.

You operate in two modes, the interviewer mode and the reviewer mode.
When the interviewee asks you to &amp;quot;switch to reviewer mode&amp;quot;, you will change to a 
softer voice tone and provide feedback on the last answered question. 
When the interviewee asks you to &amp;quot;switch to interviewer mode&amp;quot;,  you go back 
to the interviewer mode with a stronger voice tone, continue asking questions, 
and record the answers for later analysis.

Before the interview starts, you will ask for a job posting. You will ask 
general questions and other specific questions based on the job description. 

You can start with the question &amp;quot;Introduce yourself,&amp;quot; then move to the 
technical section.

You will ask relevant backend-related questions covering, but not confined to:

* REST endpoints: how REST works, things like the difference between 
PUT and PATCH, HTTP Response codes, idempotency, Rate Limits, authentication, 
and authorization
* Databases: like relational database vs non-relational ones, you have a long 
SQL select query that takes 1-2 minutes to run, how can you optimize it, 
ACID, eventually consistent, DB normalization
* Code: like testing, SOLID principles, TDD, Design patterns, Security OWASP
* System architecture: microservices, caching, message queues, 
horizontal scaling, software resilience
* Operations: Application performance monitoring (APM), logs, 
observability, SLA/SLO, infrastructure as code (IAC) - Terraform

You will wait and record all the interviewee&#39;s answers, then provide 
feedback when asked to do so.

At the end, you will let the interviewee ask you some questions about 
the company and the role, then answer them. You will let the interviewee 
know when the interview is complete and ask whether they would like feedback.

Your role is to provide actionable, easy-to-follow, and high-quality 
advice to improve the answers from a technical point of view, as well as
how the interviewee delivered the answers in relation to 
confidence and clarity. 

Adhere to the following principles and structure when providing feedback 
and advice:

General Instructions:
User Context Sensitivity: Tailor recommendations to the person&#39;s 
specific needs, considering the target audience, mainly software 
engineering managers and senior or lead engineers, goals, and finding 
a good balance of technical correctness, clarity, and 
confidence in answer delivery.

Clarity: Ensure all advice is straightforward, free of unnecessary 
jargon, and includes step-by-step guidance where relevant.

Actionability: Provide actionable advice with a clear path to 
implementation, including prioritization and how to maximize 
outcomes to ace the interview.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The prompt is self-explanatory, and when pasted on the text area, it will look as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-live-audio/06gias-prompt.jpg&quot; loading=&quot;lazy&quot; title=&quot;Adding the prompt to make Gemini live act as an experience software interviewer who has done more than 100 technical interviews&quot; alt=&quot;Adding the prompt to make Gemini live act as an experience software interviewer who has done more than 100 technical interviews&quot; /&gt;
&lt;p&gt;After that, click &lt;code&gt;Run&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then it will ask for a job description. It is best to give a backend engineer role you can try with this opening at Atlassian: &lt;code&gt;https://www.atlassian.com/company/careers/details/23645&lt;/code&gt; – here is an internet web archive &lt;a href=&quot;https://web.archive.org/web/20251215100104/https://www.atlassian.com/company/careers/details/23645&quot;&gt;link&lt;/a&gt; for future reference, and again click &lt;code&gt;Run&lt;/code&gt;:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-live-audio/07gias-jd.jpg&quot; loading=&quot;lazy&quot; title=&quot;Gemini Live prompt for software interview mode, providing the link to the job description&quot; alt=&quot;Gemini Live prompt for software interview mode, providing the link to the job description&quot; /&gt;
&lt;p&gt;After that, it will ask for your introduction. You can give your “backend engineer” introduction by  clicking the &lt;code&gt;Record&lt;/code&gt; mic button and speaking:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-live-audio/08gias-answer.jpg&quot; loading=&quot;lazy&quot; title=&quot;Giving your backend engineer introduction using the Gemini Live interviewer prompt&quot; alt=&quot;Giving your backend engineer introduction using the Gemini Live interviewer prompt&quot; /&gt;
&lt;p&gt;Then it will move on to other technical questions, and you can follow along and provide the answers.&lt;/p&gt;
&lt;h3 id=&quot;switching-modes&quot; tabindex=&quot;-1&quot;&gt;Switching modes &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/gemini-live-audio/#switching-modes&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;At any point in the interview, you can say &lt;code&gt;switch to reviewer mode&lt;/code&gt; then ask for feedback about your answers.&lt;/p&gt;
&lt;p&gt;Then again, tell it to &lt;code&gt;switch to interviewer mode&lt;/code&gt;,  and it will continue the questions. You can also ask for feedback at the end, but for that, you will need to increase the &lt;code&gt;session context size&lt;/code&gt; setting in the right sidebar. You can see this in action in the video below.&lt;/p&gt;
&lt;h3 id=&quot;demo-video&quot; tabindex=&quot;-1&quot;&gt;Demo video &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/gemini-live-audio/#demo-video&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Below is a 7 minute demo video of the whole process for your reference:&lt;/p&gt;
&lt;div style=&quot;position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%; margin-bottom: 1rem;&quot;&gt;
  &lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/valxA5kk0oM&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; style=&quot;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;h2 id=&quot;other-inteview-ideas&quot; tabindex=&quot;-1&quot;&gt;Other inteview ideas &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/gemini-live-audio/#other-inteview-ideas&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can also use Gemini Live with the screen share feature to do a system design interview. You will need to tweak the prompt to be a system design interviewer and do a system design interview&lt;br /&gt;
for a URL shortner. Be ready to draw some boxes and arrows :).&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/12/gemini-live-audio/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this post you saw the powerful combination of Gemini Live, native audio, and a detailed prompt offers a groundbreaking way to practice technical interviews. By simulating a real-world interview environment with an AI that provides immediate, actionable feedback, you can significantly enhance your preparation.&lt;/p&gt;
&lt;p&gt;This approach not only sharpens your technical knowledge but also builds confidence and clarity in your delivery and the real interview scenario. Give this free tool a try and take your software engineering interview skills to the next level. Keep learning and experimenting!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to create a hair style changer app using Gemini 3 on Google AI Studio</title>
		<link href="https://geshan.com.np/blog/2025/11/gemini-3-ai/"/>
		<updated>2025-11-27T10:48:25Z</updated>
		<id>https://geshan.com.np/blog/2025/11/gemini-3-ai/</id>
		<content type="html">&lt;p&gt;You can make practical and fun apps using Gemini 3 on Google AI Studio for free. In this post, you will create a fun app fast. The app lets you change a person&#39;s hairstyle on any human picture you upload. It will work for both male and female photos. Let’s get started!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-3-ai/01gemini-3-ai.jpg&quot; title=&quot;Hair Style changer app with Gemini 3 on Google AI Studio&quot; alt=&quot;Hair Style changer app with Gemini 3 on Google AI Studio&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#prerequisites&quot;&gt;Prerequisites&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#steps-to-generate-a-hair-style-changer-app&quot;&gt;Steps to generate a hair style changer app&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#navigate-to-google-ai-studio&quot;&gt;Navigate to Google AI Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#go-to-build&quot;&gt;Go to Build&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#paste-the-prompt-on-ai-studio&quot;&gt;Paste the prompt on AI Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#wait-for-the-generation-to-finish&quot;&gt;Wait for the generation to finish&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#use-the-hair-style-changer-app-in-preview-mode&quot;&gt;Use the hair style changer app in preview mode&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#try-a-female-hairstyle-upgrade&quot;&gt;Try a female hairstyle upgrade&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#add-another-feature&quot;&gt;Add another feature&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;prerequisites&quot; tabindex=&quot;-1&quot;&gt;Prerequisites &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#prerequisites&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before you generate the hair style changer app on Google AI Studio using the latest Gemini model, Gemini 3, you will need the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A Google Account to access Google AI Studio&lt;/li&gt;
&lt;li&gt;Understanding of how prompting for LLMs like Gemini works would be helpful. Reading this &lt;a href=&quot;https://cloud.google.com/discover/what-is-prompt-engineering?hl=en&quot;&gt;guide on prompt engineering&lt;/a&gt; would help you get some critical pointers&lt;/li&gt;
&lt;li&gt;Knowing how frontend apps are built with React.js would be beneficial, but not needed&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Given that, we can get our hands dirty with some code generated by Gemini 3 on Google AI Studio&#39;s &lt;code&gt;Build&lt;/code&gt; feature next.&lt;/p&gt;
&lt;h2 id=&quot;steps-to-generate-a-hair-style-changer-app&quot; tabindex=&quot;-1&quot;&gt;Steps to generate a hair style changer app &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#steps-to-generate-a-hair-style-changer-app&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To build a virtual try new hair style app using Gemin 3 on Google AI Studio, you will first need to go to the Google AI Studio app:&lt;/p&gt;
&lt;h3 id=&quot;navigate-to-google-ai-studio&quot; tabindex=&quot;-1&quot;&gt;Navigate to Google AI Studio &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#navigate-to-google-ai-studio&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can go to the Google AI Studio app by visiting &lt;a href=&quot;https://aistudio.google.com/&quot;&gt;https://aistudio.google.com/&lt;/a&gt; on your favourite browser. I am using Chrome and signed into my Google account. You should see something like the below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/02google-ai-studio-home.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio home page&quot; alt=&quot;Google AI Studio home page&quot; /&gt;
&lt;h3 id=&quot;go-to-build&quot; tabindex=&quot;-1&quot;&gt;Go to Build &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#go-to-build&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Then click on &lt;code&gt;Build&lt;/code&gt; to build/generate your AI virtual hair style try on app. And you will land on the build page – &lt;code&gt;Start&lt;/code&gt; section as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-3-ai/02google-ai-studio.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio Build link&quot; alt=&quot;Google AI Studio Build link&quot; /&gt;
&lt;p&gt;To build your app, you will paste the prompt as shown in the next section.&lt;/p&gt;
&lt;h3 id=&quot;paste-the-prompt-on-ai-studio&quot; tabindex=&quot;-1&quot;&gt;Paste the prompt on AI Studio &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#paste-the-prompt-on-ai-studio&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After that, you can paste the following prompt in the &lt;code&gt;Describe your idea&lt;/code&gt; text box:&lt;/p&gt;
&lt;p&gt;Prompt:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Create an app that lets users either upload their own photo or take a 
picture with the camera, then select a hairstyle. After that, a new 
image of the user will be generated with the chosen hairstyle. 
This app should work for both male and female users.

Please ensure there are at least 40 hairstyles, categorized into 
male, female, and creative styles. Figure out the photo is of a 
male or female and select the right category automatically.
Also, please provide the output that includes both the uploaded 
photo and the generated photo with the chosen hairstyle. The user 
should be able to upload an image up to 5 MB. You can show some 
hair grooming and styling tips while the chosen hairstyle 
photo is being generated.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which will look like the below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-3-ai/03hair-style-changer-prompt-on-gais.jpg&quot; loading=&quot;lazy&quot; title=&quot;Hair style changer app prompt on Google AI Studio Build -&gt; Start&quot; alt=&quot;Hair style changer app prompt on Google AI Studio Build -&gt; Start&quot; /&gt;
&lt;p&gt;After that, click the &lt;code&gt;Build&lt;/code&gt; button and it will start building the app.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;At the time of writing (Nov 2025) it selects the &lt;code&gt;Gemini 3 Pro preview&lt;/code&gt; model by default which is the latest &lt;a href=&quot;https://blog.google/products/gemini/gemini-3/&quot;&gt;version&lt;/a&gt; of the Gemini model.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;wait-for-the-generation-to-finish&quot; tabindex=&quot;-1&quot;&gt;Wait for the generation to finish &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#wait-for-the-generation-to-finish&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The generation of the Hair Style change app will take some time to complete. You can have a look at the &lt;code&gt;Code&lt;/code&gt; section to see the code Gemini is generating (or vibing):&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-3-ai/04gais-generting-code.jpg&quot; loading=&quot;lazy&quot; title=&quot;Hair style changer code being generated on Google AI Studio by Gemini 3 LLM&quot; alt=&quot;Hair style changer code being generated on Google AI Studio by Gemini 3 LLM&quot; /&gt;
&lt;p&gt;In my case, it took 123 seconds to generate the whole app and then I clicked the &lt;code&gt;Preview&lt;/code&gt; button to see how the app works.&lt;/p&gt;
&lt;h3 id=&quot;use-the-hair-style-changer-app-in-preview-mode&quot; tabindex=&quot;-1&quot;&gt;Use the hair style changer app in preview mode &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#use-the-hair-style-changer-app-in-preview-mode&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I had to click &lt;code&gt;Allow&lt;/code&gt; for the app to use the camera but I uploaded AI generated photos to test the app which looked like:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-3-ai/05hair-style-changer-app-preview.jpg&quot; loading=&quot;lazy&quot; title=&quot;Hair style changer app preview on Google AI Studio&quot; alt=&quot;Hair style changer app preview on Google AI Studio&quot; /&gt;
&lt;p&gt;I made the app go &lt;code&gt;FullScreen&lt;/code&gt; – the option is besides the &lt;code&gt;Code&lt;/code&gt; button`.  After uploading the photo of a &lt;a href=&quot;https://postimg.cc/WdNLYD43&quot;&gt;male&lt;/a&gt; (AI Generated photo with &lt;a href=&quot;https://labs.google/fx/tools/image-fx&quot;&gt;Google ImageFX&lt;/a&gt; for free), this is what the app showed me:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-3-ai/06list-of-male-hair-styles.jpg&quot; loading=&quot;lazy&quot; title=&quot;Hair style changer app on Google AI Studio preview with list of male hair style after uploading a photo&quot; alt=&quot;Hair style changer app on Google AI Studio preview with list of male hair style after uploading a photo&quot; /&gt;
&lt;p&gt;Notice, that it auto selected &lt;code&gt;Male&lt;/code&gt; as instructed in the prompt. You can select any style, I selected &lt;code&gt;Man Bun&lt;/code&gt; and then it showed me the loading screen for some seconds:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-3-ai/07hair-care-tips.jpg&quot; loading=&quot;lazy&quot; title=&quot;Hair care tips showing on the loading screen as per the prompt to Gemini 3&quot; alt=&quot;Hair care tips showing on the loading screen as per the prompt to Gemini 3&quot; /&gt;
&lt;p&gt;Adhering to the prompt it showed the hair care tips.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Gemini 3 is much better at doing what it is instructed to do than older version. It has a very good adherence to the provided prompt, as seen above.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Once the image generation was done this is what I saw on the screen:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-3-ai/08spiked-to-man-bun.jpg&quot; loading=&quot;lazy&quot; title=&quot;Hair style changer app on Google AI Studio preview with original and man bun hairstyle&quot; alt=&quot;Hair style changer app on Google AI Studio preview with original and man bun hairstyle&quot; /&gt;
&lt;p&gt;You can see the original image with a spiked hair style and the generated photo with the selected &lt;code&gt;Man bun&lt;/code&gt; hair style. Wasn’t it fun to build and this test app :) . Next, you will try a female photo and see how the app works.&lt;/p&gt;
&lt;h4 id=&quot;try-a-female-hairstyle-upgrade&quot; tabindex=&quot;-1&quot;&gt;Try a female hairstyle upgrade &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#try-a-female-hairstyle-upgrade&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;To try out a female subject, I have generaetd a photo using Google Image FX, To try a new photo, I click the &lt;code&gt;logo&lt;/code&gt; of the app on the top left corner to &lt;code&gt;reset&lt;/code&gt; the app. Then I uploaded &lt;a href=&quot;https://postimg.cc/YLjK2ZJS&quot;&gt;this&lt;/a&gt; image and it took me to the &lt;code&gt;Choose a Style&lt;/code&gt; screen:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-3-ai/09list-of-female-hair-styles.jpg&quot; loading=&quot;lazy&quot; title=&quot;List of female hair styles on Google AI Studio preview as a female photo is uploaded&quot; alt=&quot;List of female hair styles on Google AI Studio preview as a female photo is uploaded&quot; /&gt;
&lt;p&gt;Again, adhering to the prompt it auto selected &lt;code&gt;Female&lt;/code&gt; styles and you can select a style like &lt;code&gt;Pixie Cut&lt;/code&gt;, then it will show the &lt;code&gt;Loading..&lt;/code&gt; screen with the hair care tips again and when it is done it will show something like the below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-3-ai/10hair-style-changer-working.jpg&quot; loading=&quot;lazy&quot; title=&quot;Hair style changer app generated with Gemini 3 on Google AI Studio working on a female photo&quot; alt=&quot;Hair style changer app generated with Gemini 3 on Google AI Studio working on a female photo&quot; /&gt;
&lt;p&gt;You can also try some creative hairstyles with funky colors. I tried &lt;code&gt;Rainbow Hair&lt;/code&gt; and it was funny.&lt;/p&gt;
&lt;p&gt;There you have it your own hair style changer app generated by AI and powered by AI too. You can deploy it on Google Cloud Run and share it with your friends too. You can read on how to do that in my &lt;a href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#deploy-the-app-on-google-cloud-run&quot;&gt;previous blog post&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;add-another-feature&quot; tabindex=&quot;-1&quot;&gt;Add another feature &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#add-another-feature&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can also add other feature like a side by side slider. Google AI Studio also recomemnds some other feature you can add to your app:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemini-3-ai/11gias-suggestions.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio suggesting other features for the hair style changer app&quot; alt=&quot;Google AI Studio suggesting other features for the hair style changer app&quot; /&gt;
&lt;p&gt;You can click the &lt;code&gt;Suggestions&lt;/code&gt; and Gemini 3.0 will build it for you on Google AI Studio. Try it!&lt;/p&gt;
&lt;p&gt;Thanks to Google: Google Cloud credits are provided for this project. It is part of the #AISprintH2 sprint.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/gemini-3-ai/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Using Gemini 3 on Google AI Studio&#39;s &lt;code&gt;Build&lt;/code&gt; feature, you rapidly created a functional hair style changer app with a simple prompt in less than 3 minutes. The model successfully handled style categorization, uploads, and accurate image generation for both genders.&lt;/p&gt;
&lt;p&gt;This showcases how multimodal LLMs like Gemini 3 accelerate app development, making complex image tasks straightforward. From prompt to tested application, a sophisticated AI tool was quickly realized.&lt;/p&gt;
&lt;p&gt;Your deployment-ready app can now be enhanced with features like a side-by-side slider or new styles. Google AI Studio and Gemini 3 usher in the era of prompt-driven development, offering boundless creative potential. Keep Learning and reaching new goals with Google’s AI products!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to use NotebookLM: A practical guide with examples</title>
		<link href="https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/"/>
		<updated>2025-11-23T10:38:25Z</updated>
		<id>https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/</id>
		<content type="html">&lt;p&gt;Google’s NotebookLM is a hidden gem in the world of information processing. It is not just another chatbot; it is a personalized AI research assistant grounded in your own documents. If you have ever felt overwhelmed by the sheer amount of documentation, PDFs, or websites you need to read to get a job done, this tool is for you at no cost. In this post, you will learn how to use NotebookLM, explore every important NotebookLM feature, and walk through a real-life example of using it to land a Senior Software Engineer job. Let’s get started!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/01how-to-use-notebooklm.jpg&quot; title=&quot;How to use NotebookLM with practical job search example&quot; alt=&quot;How to use NotebookLM with practical job search example&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of Contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#need-for-notebooklm&quot;&gt;Need for NotebookLM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#what-is-notebooklm&quot;&gt;What is NotebookLM?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#prerequisites&quot;&gt;Prerequisites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#notebooklm-features&quot;&gt;NotebookLM features&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#audio-overview---podcasts&quot;&gt;Audio Overview - podcasts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#video-overview&quot;&gt;Video Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#mind-map&quot;&gt;Mind Map&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#reports&quot;&gt;Reports&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#flashcards&quot;&gt;Flashcards&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#quiz&quot;&gt;Quiz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#infographic&quot;&gt;Infographic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#slide-deck&quot;&gt;Slide Deck&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#how-to-use-notebooklm---real-life-example-of-job-search&quot;&gt;How to use NotebookLM - Real-life example of job search&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#add-sources-to-notebooklm&quot;&gt;Add sources to NotebookLM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#ask-questions-about-the-company&quot;&gt;Ask questions about the company&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#explore-more-of-the-notebooklm-features&quot;&gt;Explore more of the NotebookLM features&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;need-for-notebooklm&quot; tabindex=&quot;-1&quot;&gt;Need for NotebookLM &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#need-for-notebooklm&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We live in an era of information overload. As technologists or even just avid learners, we are constantly bombarded with documentation, white papers, long YouTube tutorials, and complex job descriptions. The problem isn&#39;t finding information; it&#39;s synthesizing it into something useful.&lt;/p&gt;
&lt;p&gt;You might be used to pasting text into ChatGPT or Claude to get a summary. That works for small things. But what if you have a 50-page PDF, a link to a website, and a YouTube video, and you need answers based &lt;code&gt;only&lt;/code&gt; on those sources without the AI hallucinating facts?&lt;/p&gt;
&lt;p&gt;This is where NotebookLM shines. It uses a concept called &lt;a href=&quot;https://cloud.google.com/use-cases/retrieval-augmented-generation&quot;&gt;Retrieval-Augmented Generation&lt;/a&gt; (RAG) to &amp;quot;ground&amp;quot; the AI in your specific sources. It’s like hiring a super-smart intern, handing them a stack of books, and saying, &amp;quot;Only answer questions based on these books.&amp;quot;&lt;/p&gt;
&lt;p&gt;In this guide, you will go deep into how to use NotebookLM to boost your productivity. We will look at its features and then apply them to an efficient scenario: preparing for a high-stakes job interview.&lt;/p&gt;
&lt;h2 id=&quot;what-is-notebooklm%3F&quot; tabindex=&quot;-1&quot;&gt;What is NotebookLM? &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#what-is-notebooklm%3F&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://notebooklm.google/&quot;&gt;NotebookLM&lt;/a&gt; is an AI-first notebook offered by Google. Unlike standard LLMs (Large Language Models) that rely on their vast, pre-trained knowledge of the internet (which can be outdated or inaccurate), NotebookLM relies on &amp;quot;Sources&amp;quot; that you upload or links you provide.&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/02notebooklm.jpg&quot; title=&quot;NotebookLM Understand Anything - AI Powered Research Partner&quot; alt=&quot;NotebookLM Understand Anything - AI Powered Research Partner&quot; /&gt;
&lt;p&gt;When you create a &amp;quot;Notebook&amp;quot;, you upload documents (PDFs, text files, Google Docs, Slides), paste website URLs, or link YouTube videos. The AI then becomes an expert on those specific sources – not on the parts of the internet with a cut-off date. NotebookLM is built with the latest Gemini models.&lt;/p&gt;
&lt;p&gt;The main benefit here is trust. When NotebookLM gives you an answer, it includes citations. You can click a citation to jump directly to the paragraph in your uploaded PDF where the information is located. For software engineers reading technical specs or API documentation, this accuracy is non-negotiable.&lt;/p&gt;
&lt;h2 id=&quot;prerequisites&quot; tabindex=&quot;-1&quot;&gt;Prerequisites &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#prerequisites&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before we dive into the features and examples, below are some prerequisites you should have:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;A Google Account:&lt;/strong&gt; NotebookLM is a Google product, so you will need a standard Gmail account or a Workspace account to access it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Access to NotebookLM:&lt;/strong&gt; You can access it at &lt;a href=&quot;https://notebooklm.google.com/&quot;&gt;notebooklm.google.com&lt;/a&gt;. It is currently has a free version (at the time of writing).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Source Material:&lt;/strong&gt; To get the most out of this guide, have a PDF, a website URL, or a YouTube video link ready to experiment with.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Basic understanding of GenAI:&lt;/strong&gt; Knowing how to write a basic prompt (asking the AI to do something) will be helpful.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Given that is mentioned, you can proceed to explore the features.&lt;/p&gt;
&lt;h2 id=&quot;notebooklm-features&quot; tabindex=&quot;-1&quot;&gt;NotebookLM features &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#notebooklm-features&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;NotebookLM is packed with features to help you quickly understand complex information. It is not just about text summaries; it is about multimodal understanding.&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/03notebooklm-interface.jpg&quot; title=&quot;NotebookLM user interface as of Nov 2025&quot; alt=&quot;NotebookLM user interface as of Nov 2025&quot; /&gt;
&lt;p&gt;Let’s analyze every important NotebookLM feature you should be using. All the features mentioned below take a couple of minutes or more to be generated. It shows a loading icon on NotebookLM when the artifact is being generated.&lt;/p&gt;
&lt;h3 id=&quot;audio-overview---podcasts&quot; tabindex=&quot;-1&quot;&gt;Audio Overview - podcasts &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#audio-overview---podcasts&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is arguably the most viral and impressive NotebookLM feature. The Audio Overview allows you to turn your static documents, text files, and slides into an engaging, two-way audio conversation. These are also called NotebookLM podcasts.&lt;/p&gt;
&lt;p&gt;Imagine you have uploaded a dry, 30-page technical document on Kubernetes architecture. Reading it might put you to sleep. However, with one click, NotebookLM generates a &amp;quot;Deep Dive&amp;quot; audio discussion.&lt;/p&gt;
&lt;p&gt;Two AI hosts (a male and a female voice) will discuss your content. They don&#39;t just read it out loud like a text-to-speech engine. They banter. They use analogies. They express surprise at interesting facts. They summarize the key points in a format that sounds like a “high-quality” tech podcast. Take the “high-quality” with a grain (spoon) of salt :).&lt;/p&gt;
&lt;p&gt;Someone apparently listened to 200 of these (in November 2024 - a year back) and wrote a &lt;a href=&quot;https://medium.com/@bamby_media/i-listened-to-200-notebook-lm-podcasts-so-you-dont-have-to-d5b206911592&quot;&gt;blog post&lt;/a&gt; about it with a YouTube video. She concluded they lack the genuine connection and authenticity required to compete with human conversations. I would leave the analysis up to you. Here is an &lt;a href=&quot;https://www.youtube.com/watch?v=USLDoOj097A&quot;&gt;audio overview&lt;/a&gt; for a blog post about &lt;a href=&quot;https://geshan.com.np/blog/2023/12/good-software-engineering/&quot;&gt;Good software engineering is about finding a solution at the correct layer with boring technology&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To use this, simply load your sources, go to the &amp;quot;Studio&amp;quot; section, and click &amp;quot;Audio Overview&amp;quot;. it takes a few minutes, but the result is pretty realistic as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/04audio-overview-in-action.jpg&quot; title=&quot;NotebookLM audio overview being played after generation&quot; alt=&quot;NotebookLM audio overview being played after generation&quot; /&gt;
&lt;p&gt;Next, you will learn about video overview.&lt;/p&gt;
&lt;h3 id=&quot;video-overview&quot; tabindex=&quot;-1&quot;&gt;Video Overview &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#video-overview&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Notebook LM has recently added the &lt;a href=&quot;https://www.youtube.com/watch?v=KA_pExdDSUo&quot;&gt;video overview&lt;/a&gt; feature. Similar to an audio overview, it will create a video from the documents or links you provided in the source. Since last month, it has been using &lt;a href=&quot;https://blog.google/technology/google-labs/video-overviews-nano-banana/&quot;&gt;Nano banana&lt;/a&gt; to choose styles and create a brief video overview.&lt;/p&gt;
&lt;p&gt;To create a default &lt;code&gt;Video Overview&lt;/code&gt; after you add your source(s), you can click the &lt;code&gt;Video Overview&lt;/code&gt; option in the &lt;code&gt;Studio&lt;/code&gt; panel on the right side of the screen. Below is a 7-minute video I created based on my blog post &lt;a href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/&quot;&gt;Unblocking Software Engineers: Overcoming Non-technical and Technical Roadblocks&lt;/a&gt;:&lt;/p&gt;
&lt;div style=&quot;position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%; margin-bottom: 1rem;&quot;&gt;
  &lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/H8iitzNOIeA&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; style=&quot;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;The video is usually around 8 minutes, and the brief is around 2.5 minutes. It is an excellent feature if you want to digest information faster and you learn things better in a visual format. Suppose you click the “pen” beside the &lt;code&gt;Video Overview&lt;/code&gt;. In that case, you can generate an “Explainer” or a “Brief,” choose the &lt;code&gt;Language&lt;/code&gt; (50+ available, including Nepali), and select the visual style for the video. Give it a go.&lt;/p&gt;
&lt;h3 id=&quot;mind-map&quot; tabindex=&quot;-1&quot;&gt;Mind Map &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#mind-map&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Visualizing data is crucial, while NotebookLM doesn&#39;t have a &amp;quot;Draw Mind Map&amp;quot; feature. You can use it to generate a mind map. To create a mind map from the uploaded sources, you can click the “Mind Map” on the Studio panel on the right side of the screen. It will generate a mindmap like the one below:&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/05mind-map.jpg&quot; title=&quot;NotebookLM mind map generated from sources&quot; alt=&quot;NotebookLM mind map generated from sources&quot; /&gt;
&lt;p&gt;This converts your static text or PDFs into visual architecture diagram code, a massive time-saver. It really helps you understand complex concepts in a hierarchical mind map, as shown above.&lt;/p&gt;
&lt;h3 id=&quot;reports&quot; tabindex=&quot;-1&quot;&gt;Reports &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#reports&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Reports are distilled information, taking a particular angle or type of writing generated by NotebookLM from the given set of sources. It can be in various formats like a &lt;code&gt;Brefing Doc&lt;/code&gt; (with key insights and quotes from the source, &lt;code&gt;Study Guide&lt;/code&gt; (short-answer quiz and glossary of key terms), &lt;code&gt;Blog Post&lt;/code&gt; (insightful takeaways distilled into a highly readable format). Depending on the source, NotebookLM now has suggested formats for reports like &lt;code&gt;Historical timeline&lt;/code&gt;, &lt;code&gt;Concept Explainer&lt;/code&gt;, and others.&lt;/p&gt;
&lt;p&gt;You can generate a “report” by clicking the &lt;code&gt;Reports&lt;/code&gt; option in the &lt;code&gt;Studio&lt;/code&gt; right side panel. It will show an overlay like the one below:&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/06notebooklm-reports.jpg&quot; title=&quot;NotebookLM reports overlay to generate the report format you need&quot; alt=&quot;NotebookLM reports overlay to generate the report format you need&quot; /&gt;
&lt;p&gt;From there, you can click the given format or click the &lt;code&gt;pen&lt;/code&gt; beside the format and edit the format to be generated. If you click the &lt;code&gt;pen&lt;/code&gt; / edit button, you can choose the language and type in what you want the report to be about.&lt;/p&gt;
&lt;h3 id=&quot;flashcards&quot; tabindex=&quot;-1&quot;&gt;Flashcards &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#flashcards&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Flashcards are like short questions and answers that are generated from the sources you upload to NotebookLM. You can generate them by clicking the &lt;code&gt;FlashCards&lt;/code&gt; option on the Studio panel on the right side of the screen. You can customize the &lt;code&gt;Number of cards&lt;/code&gt; and &lt;code&gt;Level of Difficulty&lt;/code&gt; of questions, and click the &lt;code&gt;pen&lt;/code&gt; icon to change the generation. Below is an example of the generated flash card:&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/07flashcards.jpg&quot; title=&quot;NotebookLM genreated flash cards with an answer link&quot; alt=&quot;NotebookLM genreated flash cards with an answer link&quot; /&gt;
&lt;p&gt;Flashcards can help you quickly learn the main points from the additional sources.&lt;/p&gt;
&lt;h3 id=&quot;quiz&quot; tabindex=&quot;-1&quot;&gt;Quiz &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#quiz&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Similar to Flashcards, &lt;code&gt;Quiz&lt;/code&gt; is another information representation format in NotebookLM. This feature will be handy as it will generate a quiz with 10 questions (usually) and answers from the given sources.  You can generate a &lt;code&gt;Quiz&lt;/code&gt; by clicking the &lt;code&gt;Quiz&lt;/code&gt; option in the &lt;code&gt;Studio&lt;/code&gt; panel on the right side of the NotebookLM user interface. Similar to the other features already mentioned, you can edit the type of the quiz by clicking the &lt;code&gt;pen&lt;/code&gt; button. Below is a quiz generated for my blog post &lt;a href=&quot;https://geshan.com.np/blog/2021/04/sofware-deployment-tools/&quot;&gt;How Software Deployment tools have changed in the past 20 years&lt;/a&gt; using the default settings.&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/08notebooklm-quiz.jpg&quot; title=&quot;NotebookLM genreated Quiz with the right answer selected&quot; alt=&quot;NotebookLM genreated Quiz with the right answer selected&quot; /&gt;
&lt;p&gt;You can play the &lt;a href=&quot;https://notebooklm.google.com/notebook/1784044d-3ec6-4f42-8510-f673c40fe86c?artifactId=3f251ac9-c75f-4efa-86a4-99eb5fac841a&quot;&gt;quiz&lt;/a&gt; too and refresh your knowledge on the software deployment tools of the past 20 years.&lt;/p&gt;
&lt;h3 id=&quot;infographic&quot; tabindex=&quot;-1&quot;&gt;Infographic &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#infographic&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;From the given sources of files, links, Google Docs, and YouTube videos, you can also generate an infographic on NoteBookLM. To create an infographic, you should click the &lt;code&gt;Infographic&lt;/code&gt; option in the &lt;code&gt;Studio&lt;/code&gt; section found on the right side of the page. Below is an infographic generated by Notebook LM for the 20 years of software deployment tools blog post:&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/09infographic.jpg&quot; title=&quot;Infographic generated by NotebookLM for the 20 years of software deployment tools blog post&quot; alt=&quot;Infographic generated by NotebookLM for the 20 years of software deployment tools blog post&quot; /&gt;
&lt;p&gt;It can distill the information well. This feature was recently added to the free version of NotebookLM.&lt;/p&gt;
&lt;h3 id=&quot;slide-deck&quot; tabindex=&quot;-1&quot;&gt;Slide Deck &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#slide-deck&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Similar to an infographic, you can also generate an “image” slide deck from the uploaded sources. You can also download the slide deck as a PDF and upload it to a slide rendering service like SlideShare or SpeakerDeck. In my experience, it usually generates 12-15 slides with images and explanations from the sources provided. You can develop the slides by clicking the &lt;code&gt;Slide Deck&lt;/code&gt; option in the &lt;code&gt;Studio&lt;/code&gt; panel on the right side of the NotebookLM user interface. The generated slides look as follows on the NotebookLM interface:&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/10notebooklm-slide-deck.jpg&quot; title=&quot;NotebookLM generated slide deck&quot; alt=&quot;NotebookLM generated slide deck&quot; /&gt;
&lt;p&gt;Below is an example of a generated slide deck for the 20 years of software deployment blog post:&lt;/p&gt;
&lt;script defer=&quot;&quot; class=&quot;speakerdeck-embed&quot; data-id=&quot;c8bda2d4300343d88b0a8c6ffe272da5&quot; data-ratio=&quot;1.791044776119403&quot; src=&quot;https://speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;In the next section, we will put all of this into practice with a concrete, real-life example.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-notebooklm---real-life-example-of-job-search&quot; tabindex=&quot;-1&quot;&gt;How to use NotebookLM - Real-life example of job search &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#how-to-use-notebooklm---real-life-example-of-job-search&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let’s say you are a backend software engineer looking for a new role. You have found a job opening at &lt;a href=&quot;https://relevanceai.com/&quot;&gt;Relevance AI&lt;/a&gt;, a real company doing incredible things with AI agents, for a Senior Software Engineer role.&lt;/p&gt;
&lt;p&gt;The job market is tough. To stand out, you cannot just send a generic resume. You need to understand the company deeply, understand the role, and prep for the specific interview questions they might ask.&lt;/p&gt;
&lt;p&gt;Here is how you use NotebookLM to crush this process.&lt;/p&gt;
&lt;h3 id=&quot;add-sources-to-notebooklm&quot; tabindex=&quot;-1&quot;&gt;Add sources to NotebookLM &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#add-sources-to-notebooklm&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To start a new Notebook, first go to NotebookLM and click the &lt;code&gt;Create new notebook&lt;/code&gt;:&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/11new-notebook-notebooklm.jpg&quot; title=&quot;Create new notebook in NotebookLM&quot; alt=&quot;Create new notebook in NotebookLM&quot; /&gt;
&lt;p&gt;After creating an empty notebook, you can add sources. You will add the following sources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the job vacancy&lt;/li&gt;
&lt;li&gt;some pages from the Relevance AI website&lt;/li&gt;
&lt;li&gt;Relevance AI reviews from Glassdoor&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To add the &lt;code&gt;job vacancy&lt;/code&gt; page, you can save the job as a PDF file by going to &lt;code&gt;https://jobs.ashbyhq.com/relevanceai/d5d5fc13-7415-454b-92d7-487cf187ba0a&lt;/code&gt; on Chrome and hitting &lt;code&gt;Ctrl+P&lt;/code&gt; to print it and save the file as &lt;a href=&quot;https://filebin.net/kol6zjojv398fw7t/Senior%20Software%20Engineer%20_%20Relevance%20AI.pdf&quot;&gt;PDF&lt;/a&gt;. You can also access an &lt;a href=&quot;https://archive.is/biPll&quot;&gt;archived&lt;/a&gt; version of the job vacancy. Sometimes NotebookLM doesn&#39;t extract the contents of a URL, especially if the page is loaded with JavaScript, so saving the page as a PDF file is better.&lt;/p&gt;
&lt;p&gt;After you have the file, click on the &lt;code&gt;choose file&lt;/code&gt; option below the &lt;code&gt;Upload sources&lt;/code&gt; section in the newly created NotebookLM notebook as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/12notebooklm-upload-file.jpg&quot; title=&quot;Upload a file as source on a new Notebook in NotebookLM&quot; alt=&quot;Upload a file as source on a new Notebook in NotebookLM&quot; /&gt;
&lt;p&gt;After the file is uploaded and processed, you will see a screen like the one below:&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/13notbooklm-source-parsed.jpg&quot; title=&quot;NotebookLM has parsed the source PDF&quot; alt=&quot;NotebookLM has parsed the source PDF&quot; /&gt;
&lt;p&gt;It has the vacancy as a PDF uploaded as a source, and in the &lt;code&gt;Chat&lt;/code&gt; section in the middle, it also includes a summary of the Senior Software Engineer vacancy. Before you use any of the things in the right panel – &lt;code&gt;Studio&lt;/code&gt;, upload more sources.&lt;/p&gt;
&lt;p&gt;Next, you can go to the company’s website, which is &lt;code&gt;relevanceai.com&lt;/code&gt; for this case, and run the following script to get all the links on that page:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;urls &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;a&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;links &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; urls&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; href &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; urls&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;href&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;href&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;startsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://relevanceai.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;href&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;#&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;links&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;href&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    links&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;href&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;links&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;links&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Open the console on Google Chrome and run the above JavaScript snippet as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/14extract-links.jpg&quot; title=&quot;Extract all links from a webpage with client-side JavaScript snippet&quot; alt=&quot;Extract all links from a webpage with client-side JavaScript snippet&quot; /&gt;
&lt;p&gt;It will log all the links on that page (61 in my case), since NotebookLM (free version) only has a maximum of 50 sources, so I had to select the first 40. You can choose the ones that make more sense to you. It would be good to keep the &lt;code&gt;careers&lt;/code&gt; page, though, &lt;a href=&quot;https://gist.github.com/geshan/2d565a5354a9a5ea87c1f03ef3de08c0#file-links-txt&quot;&gt;These&lt;/a&gt; were the 40 links I selected and pasted on &lt;code&gt;Paste URLs&lt;/code&gt; after clicking the &lt;code&gt;Add sources&lt;/code&gt; -&amp;gt; &lt;code&gt;Website&lt;/code&gt; under the &lt;code&gt;Link&lt;/code&gt; section:&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/15notebook-lm-add-urls.jpg&quot; title=&quot;Adding multiple URLs as sources in NotebookLM&quot; alt=&quot;Adding multiple URLs as sources in NotebookLM&quot; /&gt;
&lt;p&gt;Then you can click &lt;code&gt;Insert&lt;/code&gt; to add the 40 links to the Notebook. It will take a couple of seconds to pull in the contents of the 40 web pages, then it will look as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/16urls-parsed-by-notebooklm.jpg&quot; title=&quot;Added URLs paresed as sources by NotebookLM&quot; alt=&quot;Added URLs paresed as sources by NotebookLM&quot; /&gt;
&lt;p&gt;Now you can also add the Glassdoor review for Relevance AI, saved as a PDF. For that, go to the Glassdoor review page of &lt;a href=&quot;https://www.glassdoor.com.au/Reviews/Relevance-AI-Reviews-E8344893.htm&quot;&gt;Relevance AI&lt;/a&gt;, expand all the reviews by clicking the &lt;code&gt;Show more&lt;/code&gt; link after every review, then only print the page as a PDF, and then upload the page. If there are multiple pages, you can use a free &lt;a href=&quot;https://www.ilovepdf.com/merge_pdf&quot;&gt;PDF joiner&lt;/a&gt; to join multiple PDFs into one.&lt;/p&gt;
&lt;p&gt;To upload the PDF, click on &lt;code&gt;+ Add sources,&lt;/code&gt; then click &lt;code&gt;choose file&lt;/code&gt; and select the PDF file you created from the Glassdoor page for Relevance AI. By now, you would have 42 sources, and if you want, you can add your resume too to ask questions to make it better, but we will not do that for this tutorial.&lt;/p&gt;
&lt;h3 id=&quot;ask-questions-about-the-company&quot; tabindex=&quot;-1&quot;&gt;Ask questions about the company &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#ask-questions-about-the-company&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can start asking questions, and NotebookLM will give you answers based on the 42 sources added (including the two PDF files). You can ask a question like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What tech stack is used, and what is mentioned, in the senior software engineer job vacancy?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Which will be answered by NotebookLM as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/17notebooklm-answering-questions-with-citations.jpg&quot; title=&quot;NotebookLM answering questions with citations&quot; alt=&quot;NotebookLM answering questions with citations&quot; /&gt;
&lt;p&gt;If you click on citation numbers like &lt;code&gt;2&lt;/code&gt;, it will take you to the source in the list of sources added. You can also hover over it to see the source’s text.&lt;/p&gt;
&lt;p&gt;You can also ask other questions, like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is Relevance AI profitable?&lt;/li&gt;
&lt;li&gt;How big is the tech team at Relevance AI?&lt;/li&gt;
&lt;li&gt;What are the values of the company? Could you list all of them?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can get an idea of what you can ask the sources you added to the Notebook now. You can also add more sources, such as YouTube videos, to enrich your research, but be aware that the free version of NotebookLM has more limitations than the pro version. Read the &lt;a href=&quot;https://notebooklm.google/plans?hl=en-US&quot;&gt;plans page&lt;/a&gt; to get the exact details.&lt;/p&gt;
&lt;h3 id=&quot;explore-more-of-the-notebooklm-features&quot; tabindex=&quot;-1&quot;&gt;Explore more of the NotebookLM features &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#explore-more-of-the-notebooklm-features&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In addition to asking questions about the source, you should explore the NotebookLM features discussed above. Let’s start with Audio Overview. You can tell NotebookLM to generate a &lt;code&gt;Brief&lt;/code&gt; audio overview (podcast) and focus on the senior software engineer job vacancy:&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/18audio-overview-options.jpg&quot; title=&quot;NotebookLM Audio Overview Options&quot; alt=&quot;NotebookLM Audio Overview Options&quot; /&gt;
&lt;p&gt;After you click &lt;code&gt;Generate&lt;/code&gt;, it will take a couple of minutes, and you will get a 2-3 minute podcast focusing on the job vacancy. You can generate the audio overview in &lt;a href=&quot;https://blog.google/technology/google-labs/notebooklm-audio-overviews-50-languages/&quot;&gt;more than 50 languages&lt;/a&gt;. It will take a few minutes to be generated. When it is done, it will be listed below the eight options/features in the &lt;code&gt;Studio&lt;/code&gt; panel on the bottom right side of the NotebookLM interface:&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/19audio-overview-generated.jpg&quot; title=&quot;NotebookLM Audio Overview Generated&quot; alt=&quot;NotebookLM Audio Overview Generated&quot; /&gt;
&lt;p&gt;You can listen to it or even download it as a &lt;code&gt;.mp3&lt;/code&gt; file. You can use this online &lt;a href=&quot;https://www.onlineconverter.com/audio-to-video&quot;&gt;audio to video converter&lt;/a&gt;, put an image, and upload it to YouTube if you wish.&lt;/p&gt;
&lt;p&gt;Similarly, you can generate a &lt;code&gt;Quiz&lt;/code&gt;, play it, or even share it with your interviewer after the interview. A &lt;code&gt;Mind Map&lt;/code&gt; will help you understand the company&#39;s domain in a hierarchical format, which is much easier to comprehend. You can also create a &lt;code&gt;Video Overview&lt;/code&gt; to get a quick 5-8 minute video to understand what the company does and how it makes money, depending on the sources you have uploaded.&lt;/p&gt;
&lt;p&gt;Try all eight tiles and see what they generate. I have set my &lt;a href=&quot;https://notebooklm.google.com/notebook/e0100ed9-6a4d-47c4-9036-a574b5f9282b&quot;&gt;Relevance AI Notebook&lt;/a&gt; to be publicly accessible if you want to see what it looks like.&lt;/p&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/how-to-use-notebooklm/20notebooklm-all-features.jpg&quot; title=&quot;NotebookLM most feature used and notes generated&quot; alt=&quot;NotebookLM most feature used and notes generated&quot; /&gt;
&lt;p&gt;You can watch the video overview and listen to the audio overview too. You can also add your own notes and play around with NotebookLM. If you would like to use NotebookLM as a native mobile app you can download the &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.google.android.apps.labs.language.tailwind&quot;&gt;Android app&lt;/a&gt; or the &lt;a href=&quot;https://apps.apple.com/us/app/google-notebooklm/id6737527615&quot;&gt;iOS app&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/how-to-use-notebooklm/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;NotebookLM is more than just a summarizer; it is a tool for synthesis and deep understanding with a &lt;a href=&quot;https://support.google.com/notebooklm/answer/16213268?hl=en&quot;&gt;generous&lt;/a&gt; free plan. By grounding the AI in your specific documents—whether that is a job description, technical documentation, or meeting notes—you eliminate the noise of the general internet and focus purely on what matters to you.&lt;/p&gt;
&lt;p&gt;In this guide, you learned how to use NotebookLM features like Audio Overviews to learn while commuting, video overview, Mind Map, Reports, Flashcards, Quiz, Infographic, and Slide Deck. You also looked at a practical example of using NotebookLM as a research and thinking companion in a job search context.&lt;/p&gt;
&lt;p&gt;Don&#39;t just read about it. Go to &lt;a href=&quot;https://notebooklm.google.com/&quot;&gt;notebooklm.google.com&lt;/a&gt;, upload a PDF you have been meaning to read, and hit that &amp;quot;Audio overview&amp;quot; button or &lt;code&gt;Video Overview&lt;/code&gt;. You will be surprised at how much more you learn. Keep learning!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to build your own resume reviewer with Google AI Studio in minutes</title>
		<link href="https://geshan.com.np/blog/2025/11/google-ai-studio-build/"/>
		<updated>2025-11-14T10:48:25Z</updated>
		<id>https://geshan.com.np/blog/2025/11/google-ai-studio-build/</id>
		<content type="html">&lt;p&gt;Using Google AI Studio’s build feature, you can build any frontend application by giving a prompt. The Build feature in AI Studio generates applications that use the Gemini SDK without any server-side components. The apps run in a sandboxed frame. For this post, you will create a tech resume reviewer that will score your resume out of 100 against a given job description. Let’s get started!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/01google-ai-studio-build.jpg&quot; title=&quot;How to build your own resume reviewer with Google AI Studio in minutes and deploy it on Google Cloud Run&quot; alt=&quot;How to build your own resume reviewer with Google AI Studio in minutes and deploy it on Google Cloud Run&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of Contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#google-ai-studio&quot;&gt;Google AI Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#steps-to-build-a-resume-reviewer-with-google-ai-studio&quot;&gt;Steps to build a resume reviewer with Google AI Studio&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#go-to-google-ai-studio&quot;&gt;Go to Google AI Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#navigate-to-build&quot;&gt;Navigate to Build&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#input-the-intelligent-resume-reviewer-prompt&quot;&gt;Input the intelligent resume reviewer prompt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#use-the-built-app-in-preview-mode&quot;&gt;Use the built app in preview mode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#deploy-the-app-on-google-cloud-run&quot;&gt;Deploy the app on Google Cloud Run&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#video&quot;&gt;Video&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#resume-reviewer-gemini-gem&quot;&gt;Resume reviewer Gemini Gem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;google-ai-studio&quot; tabindex=&quot;-1&quot;&gt;Google AI Studio &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#google-ai-studio&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As Google defines it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Google AI Studio is the fastest way to start building with Gemini, our next generation family of multimodal generative AI models.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In short, it is an application that turns a prompt into an application prototype in minutes. It is a playground where you can test out your ideas, build apps, and even use the latest Gemini feature, like the live feature to share your screen or camera video, and ask questions about it. You can also build multimodal apps that can take an image or a video as input and generate images as output. There are lots of possibilities.&lt;/p&gt;
&lt;p&gt;For the scope of this blog post, you will focus on the “Build” feature of Google AI Studio and generate a text input to text output application that takes in your tech resume and a job description, analyzes both, and gives your resume a score out of 100 against the job description. It also provides specific guidance on writing your position description using the &lt;a href=&quot;https://www.tealhq.com/post/xyz-resume&quot;&gt;XYZ formula&lt;/a&gt; to achieve the best results. You will build your own tech resume reviewer next.&lt;/p&gt;
&lt;h2 id=&quot;steps-to-build-a-resume-reviewer-with-google-ai-studio&quot; tabindex=&quot;-1&quot;&gt;Steps to build a resume reviewer with Google AI Studio &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#steps-to-build-a-resume-reviewer-with-google-ai-studio&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To build a tech resume reviewer using the Google AI Studio’s Build feature. You will first need to go to the Google AI Studio app:&lt;/p&gt;
&lt;h3 id=&quot;go-to-google-ai-studio&quot; tabindex=&quot;-1&quot;&gt;Go to Google AI Studio &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#go-to-google-ai-studio&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can go to the Google AI Studio app by visiting &lt;a href=&quot;https://aistudio.google.com/&quot;&gt;https://aistudio.google.com/&lt;/a&gt; on your favourite browser. For this blog post, I am using Chrome with my Google account signed in. It will look like the following when you open Google AI Studio on your browser:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/02google-ai-studio-home.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio home page&quot; alt=&quot;Google AI Studio home page&quot; /&gt;
&lt;p&gt;Next, you will navigate to the build section of Google AI Studio.&lt;/p&gt;
&lt;h3 id=&quot;navigate-to-build&quot; tabindex=&quot;-1&quot;&gt;Navigate to Build &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#navigate-to-build&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To go to the Build feature of Google AI Studio, you can click the &lt;code&gt;Build&lt;/code&gt; menu item on the left navigation, as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/03google-ai-studio-build-link.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio build link&quot; alt=&quot;Google AI Studio build link&quot; /&gt;
&lt;p&gt;From there, you can give a prompt for the type of app you want Gemini to build, which is in the next section.&lt;/p&gt;
&lt;h3 id=&quot;input-the-intelligent-resume-reviewer-prompt&quot; tabindex=&quot;-1&quot;&gt;Input the intelligent resume reviewer prompt &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#input-the-intelligent-resume-reviewer-prompt&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As you want to build an intelligent tech resume reviewer, you will use the prompt given below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Build me an intelligent resume reviewer that analyses a resume against a job
description, providing actionable feedback and suggestions based on the 
proven XYZ formula to help you stand out. Both the resume and the job 
description are also uploaded as text.

Please take note of the following things when reviewing the resume:
1. The primary purpose of the resume is to get the initial call or 
email from the tech recruiter, who is a non-technical person 
2. Please make the resume appeal equally to the engineering manager 
and other technical leaders who will take the interviews in later rounds. 
3. Keep yourself in the position of the resume receiver and frame the 
bullet points in a way to accentuate how the candidate can add value 
to the organisation


Technically, please do the following: 
1. While uploading, show messages like &amp;quot;Parsing objective&amp;quot;, 
&amp;quot;Analysing job descriptions&amp;quot;, &amp;quot;Creating a personalised review&amp;quot;, 
and similar messages. Please show the same message exactly once
2. Show a percentage score of what the resume currently scores 
against 100, and things that can be improved in categories 
like objective, job description, side projects, formatting, and 
use of language, etc
3. Show all the suggestions for each category nicely presented 
in a foldable bullet point list per category, highlighting the 
things to change per sentence.

As a baseline, always use Australian English spellings for 
all the suggestions.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s quickly analyze the prompt:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The prompt is divided into three parts. The first part tells the model what kind of app it needs to build&lt;/li&gt;
&lt;li&gt;The second part adds some more information about how to review the resume from both a technical and a non-technical point of view&lt;/li&gt;
&lt;li&gt;The third part provides some technical guidelines, like scoring, providing suggestions, and using Australian English&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can edit the prompt if you like, or just paste the prompt on Google AI Studio Build feature as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/04prompt.jpg&quot; loading=&quot;lazy&quot; title=&quot;Prompt to generate the intelligent tech resume reviewer app on Google AI Studio build&quot; alt=&quot;Prompt to generate the intelligent tech resume reviewer app on Google AI Studio build&quot; /&gt;
&lt;p&gt;After that, click the &lt;code&gt;Build&lt;/code&gt; button on the form. Then you will need to wait for the app to be built. It will take 1-2 minutes it will show something as follows when it is creating the app:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/05google-ai-studio-building.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio building the resume reviewer app&quot; alt=&quot;Google AI Studio building the resume reviewer app&quot; /&gt;
&lt;p&gt;You can follow the progress on the left-hand side, the &lt;code&gt;Code assistant&lt;/code&gt; panel or even click the “Code” button on the right side to see the generated code as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/06google-ai-studio-generating-code.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio generating code for the resume reviewer app&quot; alt=&quot;Google AI Studio generating code for the resume reviewer app&quot; /&gt;
&lt;p&gt;Once it is done, it will load the &lt;code&gt;Preview&lt;/code&gt; tab and may look something like the below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/07google-ai-studio-preview.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio preview of the resume reviewer app&quot; alt=&quot;Google AI Studio preview of the resume reviewer app&quot; /&gt;
&lt;p&gt;Next, let&#39;s test the app in preview mode.&lt;/p&gt;
&lt;h3 id=&quot;use-the-built-app-in-preview-mode&quot; tabindex=&quot;-1&quot;&gt;Use the built app in preview mode &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#use-the-built-app-in-preview-mode&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To test the generated app, you will need a resume. For that, we will use a sample frontend engineer resume in &lt;a href=&quot;https://gist.githubusercontent.com/geshan/6218fdaac542c3314535dbe253c13341/raw/c1dff1ae304ef9433a1369406ce3659854fb1c10/test-fe-resume.txt&quot;&gt;text format&lt;/a&gt;. As the sample Frontend engineer role, we will use this mid-level &lt;a href=&quot;https://gist.githubusercontent.com/geshan/6218fdaac542c3314535dbe253c13341/raw/b3622236cb069753e4befc4093c21129baf62204/z-fe-vacancy-text.txt&quot;&gt;Frontend Engineer Role&lt;/a&gt; at Lorikeet AI in text format.&lt;/p&gt;
&lt;p&gt;When you paste both the resume and the job vacancy text in the app, it looks like the following:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/08google-ai-studio-preview-testing.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio preview testing of the resume reviewer app&quot; alt=&quot;Google AI Studio preview testing of the resume reviewer app&quot; /&gt;
&lt;p&gt;After that, you can click the &lt;code&gt;Review My Resume&lt;/code&gt; button, which will take some time to review the resume against the job description:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/09google-ai-studio-analysing.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio reviewing the resume&quot; alt=&quot;Google AI Studio reviewing the resume&quot; /&gt;
&lt;p&gt;After a few seconds, it will give its analysis, something like the following:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/10resume-reviewer-result.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio resume review result&quot; alt=&quot;Google AI Studio resume review result&quot; /&gt;
&lt;p&gt;Hurray! Your AI-powered tech resume reviewer is working. Now, if you want to share it with your friends, you can deploy it on Google Cloud Run. How to do it is discussed next.&lt;/p&gt;
&lt;h3 id=&quot;deploy-the-app-on-google-cloud-run&quot; tabindex=&quot;-1&quot;&gt;Deploy the app on Google Cloud Run &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#deploy-the-app-on-google-cloud-run&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To deploy your app, you will need a functioning Google Cloud Platform account. You can create a &lt;a href=&quot;https://console.cloud.google.com/projectcreate&quot;&gt;new project&lt;/a&gt; on a Google Cloud Platform account:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/11gcp-new-project.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google Cloud create project called resume-reviewer&quot; alt=&quot;Google Cloud create project called resume-reviewer&quot; /&gt;
&lt;p&gt;Put in the name as &lt;code&gt;resume-reviewer&lt;/code&gt; and then click the &lt;code&gt;Create&lt;/code&gt; button. It will take a few seconds, and the project will be created associated with your selected billing account:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/12gcp-project-created.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google Cloud project resume-reviewer created&quot; alt=&quot;Google Cloud project resume-reviewer created&quot; /&gt;
&lt;p&gt;Then head back to Google AI Studio, you can click the &lt;code&gt;Deploy App&lt;/code&gt; button on the top right, which looks like a rocket 🚀:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/14gias-deploy.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio deploy app button&quot; alt=&quot;Google AI Studio deploy app button&quot; /&gt;
&lt;p&gt;In the drop-down, select &lt;code&gt;Import Project&lt;/code&gt;:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/13google-ai-studio-import-project.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio Import GCP project&quot; alt=&quot;Google AI Studio Import GCP project&quot; /&gt;
&lt;p&gt;In the right sidebar, search for &lt;code&gt;resume reviewer&lt;/code&gt; and choose the project you have just created, and click &lt;code&gt;Import&lt;/code&gt;:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/16import-project-button.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio Import GCP project to deploy&quot; alt=&quot;Google AI Studio Import GCP project to deploy&quot; /&gt;
&lt;p&gt;After that, select the &lt;code&gt;resume-reviwer&lt;/code&gt; project in the drop-down of the overlay to deploy your app to Google Cloud Run in that &lt;code&gt;resume-reviewer&lt;/code&gt; project:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/17select-project.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio select GCP project to deploy&quot; alt=&quot;Google AI Studio select GCP project to deploy&quot; /&gt;
&lt;p&gt;After the project (and billing) is verified, you can click the &lt;code&gt;Deploy app&lt;/code&gt; button to deploy your intelligent tech resume reviewer app to Cloud Run:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/18deploy-app.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio deploy app button&quot; alt=&quot;Google AI Studio deploy app button&quot; /&gt;
&lt;p&gt;It will take some time (up to a couple of minutes) for Google AI Studio to deploy the app, and then it will give you a URL to view your app running on Google Cloud Run:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/19app-deploying.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio deploying resume reviewer app&quot; alt=&quot;Google AI Studio deploying resume reviewer app&quot; /&gt;
&lt;p&gt;Then you can click &lt;code&gt;View app&lt;/code&gt; to see the app running on Google Cloud Run. You can share the URL with anyone, and they will be able to view and test the tech resume reviewer you generated:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/20app-deployed.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio deployed resume reviewer app&quot; alt=&quot;Google AI Studio deployed resume reviewer app&quot; /&gt;
&lt;p&gt;You have successfully built and deployed your own intelligent tech resume reviewer using Google AI Studio in minutes without writing any server code! You can test it out on your favourite browser:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/21app-on-cloud-run.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio deployed resume reviewer app running on Google Cloud Run&quot; alt=&quot;Google AI Studio deployed resume reviewer app running on Google Cloud Run&quot; /&gt;
&lt;p&gt;You can close the overlay and edit the app with another prompt if you like. If you want to use the app as a chat, you can use the Resume reviewer Gemini Gem as discussed next.&lt;/p&gt;
&lt;h2 id=&quot;video&quot; tabindex=&quot;-1&quot;&gt;Video &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#video&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I have recorded a video of generating the whole app and testing it in preview (not the deployment part). You can watch the 6-minute video below:&lt;/p&gt;
&lt;div style=&quot;position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%; margin-bottom: 1rem;&quot;&gt;
  &lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/2-mOMPic_bI&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; style=&quot;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;h2 id=&quot;resume-reviewer-gemini-gem&quot; tabindex=&quot;-1&quot;&gt;Resume reviewer Gemini Gem &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#resume-reviewer-gemini-gem&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you don’t want to build an app and still use the resume reviewer, I have created a Gemini Gem for &lt;a href=&quot;https://gemini.google.com/gem/1z6S8yx2kkFPUTBHzmkPnxqDky9ssXA6y?usp=sharing&quot;&gt;Resume reviewer&lt;/a&gt;, just click the link and use it:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-build/22resume-reviewer-gemini-gem.jpg&quot; loading=&quot;lazy&quot; title=&quot;Resume reviewer app running as a Gemini Gem&quot; alt=&quot;Resume reviewer app running as a Gemini Gem&quot; /&gt;
&lt;p&gt;That is another way to use the prompt without creating a custom application.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/11/google-ai-studio-build/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This post demonstrated using Google AI Studio&#39;s Build feature to quickly prototype and deploy an intelligent tech resume reviewer without complex server code. You covered exploring AI Studio and its Build feature, crafting a detailed prompt for functionality (job description analysis, 100-point scoring, XYZ feedback), generating and testing the application, and finally deploying it to Google Cloud Run for a shareable URL.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You also noted the pre-built Gemini Gem as an alternative. This process showcases the rapid, custom tool development possible with Google AI Studio and the Gemini SDK.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Keep learning and keep exploring!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to use the remote GitHub MCP server with Copilot on VS Code: a step-by-step guide</title>
		<link href="https://geshan.com.np/blog/2025/08/github-mcp-vscode/"/>
		<updated>2025-08-30T10:59:24Z</updated>
		<id>https://geshan.com.np/blog/2025/08/github-mcp-vscode/</id>
		<content type="html">&lt;p&gt;Imagine being able to open a pull request or close an issue without leaving your IDE/Editor. This is made possible by the GitHub Model Context Protocol (MCP) server. In this post, you will learn how to use the remote GitHub MCP server with GitHub Copilot on VS Code. Let&#39;s get started!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/github-mcp-vscode/01github-mcp-vscode.jpg&quot; title=&quot;How to use the remote GitHub MCP server with Copilot on VS Code: a step-by-step guide&quot; alt=&quot;How to use the remote GitHub MCP server with Copilot on VS Code: a step-by-step guide&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#what-is-mcp&quot;&gt;What is MCP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#official-github-mcp-server&quot;&gt;Official GitHub MCP server&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#using-github-mcp-server-locally&quot;&gt;Using GitHub MCP server locally&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#remote-github-mcp-server&quot;&gt;Remote GitHub MCP server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#remote-github-mcp-server-on-vs-code-with-copilot&quot;&gt;Remote GitHub MCP server on VS Code with Copilot&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#step-by-step-guide-to-connect-vs-code-to-the-remote-github-mcp-server&quot;&gt;Step-by-step guide to connect VS Code to the remote GitHub MCP server&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#install-the-remote-mcp-server&quot;&gt;Install the remote MCP Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#list-the-pull-requests-for-a-repo&quot;&gt;List the pull requests for a repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#other-things-to-do-with-remote-github-mcp-server&quot;&gt;Other things to do with remote GitHub MCP Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#mcp-server-settings&quot;&gt;MCP server settings&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-is-mcp&quot; tabindex=&quot;-1&quot;&gt;What is MCP &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#what-is-mcp&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It is hard to believe that the Model Context Protocol (MCP) was announced less than a year ago in &lt;a href=&quot;https://www.anthropic.com/news/model-context-protocol&quot;&gt;November 2024&lt;/a&gt;, and it has achieved so much &lt;a href=&quot;https://trends.google.com/trends/explore?date=2024-11-01%202025-08-30&amp;amp;q=%2Fg%2F11x5hnm0vb,mcp,mcp%20server&amp;amp;hl=en&quot;&gt;popularity&lt;/a&gt;. But then what is MCP? MCP stands for Model Context Protocol. Think of it as a universal translator or a &amp;quot;&lt;a href=&quot;https://modelcontextprotocol.io/docs/getting-started/intro&quot;&gt;USB-C port for AI applications&lt;/a&gt;”. Just as a USB-C cable allows you to connect various devices to your computer seamlessly, MCP provides a standardized way for Large Language Models (LLMs), such as GitHub Copilot, to communicate with external data sources and tools.&lt;/p&gt;
&lt;p&gt;In essence, as per the &lt;a href=&quot;https://modelcontextprotocol.io/specification/2025-06-18&quot;&gt;specification&lt;/a&gt;, MCP standardizes how applications share contextual information with LLMs and how AI systems can expose and utilize external tools and capabilities. This means that instead of an AI model operating in a vacuum, it can tap into the rich, real-world context of your development environment. This protocol is open, meaning anyone can implement and use it, fostering a vibrant ecosystem of integrations.&lt;/p&gt;
&lt;p&gt;The goal of MCP is to make AI assistants more informed and capable, turning them into true teammates that can handle complex, multi-step projects with real-time access to external resources using an &lt;a href=&quot;https://modelcontextprotocol.io/docs/tutorials/use-remote-mcp-server&quot;&gt;MCP server&lt;/a&gt;, which can be local or remote. It&#39;s about making your AI tools understand your world better.&lt;/p&gt;
&lt;h2 id=&quot;official-github-mcp-server&quot; tabindex=&quot;-1&quot;&gt;Official GitHub MCP server &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#official-github-mcp-server&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that you understand the power of MCP, let&#39;s talk about the official &lt;a href=&quot;https://github.com/github/github-mcp-server&quot;&gt;GitHub MCP server&lt;/a&gt;. This server is a specific implementation of the Model Context Protocol, provided and maintained by GitHub &lt;a href=&quot;https://docs.github.com/en/enterprise-cloud@latest/copilot/concepts/about-mcp&quot;&gt;itself&lt;/a&gt;. Its primary purpose is to connect your AI tools directly to GitHub&#39;s platform, enabling them to interact with your repositories, issues, pull requests, and more through a structured and secure interface.&lt;/p&gt;
&lt;p&gt;The GitHub MCP server acts as a bridge, enabling AI assistants to manage repositories, automate issues and pull requests, gain CI/CD insights with GitHub Actions, and perform other tasks. It is &lt;a href=&quot;https://github.com/github/github-mcp-server&quot;&gt;open source&lt;/a&gt; and also used for the remote GitHub MCP server.&lt;/p&gt;
&lt;p&gt;There are two main ways you can utilize the GitHub MCP server: running it locally or connecting to a remote, hosted version. Let&#39;s explore both.&lt;/p&gt;
&lt;h3 id=&quot;using-github-mcp-server-locally&quot; tabindex=&quot;-1&quot;&gt;Using GitHub MCP server locally &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#using-github-mcp-server-locally&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For those who prefer a hands-on approach or need a highly controlled environment, you can run the GitHub MCP server directly on your local machine. This typically involves using Docker, which encapsulates the server and its dependencies, ensuring a consistent environment.&lt;/p&gt;
&lt;p&gt;You will need Docker and a personal access token from GitHub to run the image of the open-source, official GitHub MCP server. Although this is not difficult to do, some effort and maintenance are surely involved. You can follow the official &lt;a href=&quot;https://docs.github.com/en/enterprise-cloud@latest/copilot/how-tos/provide-context/use-mcp/use-the-github-mcp-server?tool=vscode#local-mcp-server-setup&quot;&gt;docs&lt;/a&gt; on how to run it locally. You can see one way of running the GitHub MCP server below:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; run &lt;span class=&quot;token parameter variable&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;GITHUB_PERSONAL_ACCESS_TOKEN&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;your-token&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;GITHUB_TOOLSETS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;repos,issues,pull_requests,actions,code_security,experiments&quot;&lt;/span&gt; ghcr.io/github/github-mcp-server&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While running the GitHub MCP server locally gives you control, it often comes with the overhead of infrastructure management. This is where the remote GitHub MCP server shines.&lt;/p&gt;
&lt;h3 id=&quot;remote-github-mcp-server&quot; tabindex=&quot;-1&quot;&gt;Remote GitHub MCP server &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#remote-github-mcp-server&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For most teams and individual developers, the remote GitHub MCP server offers a significantly more streamlined and hassle-free experience. This version is hosted and managed directly by GitHub, eliminating the need for you to worry about Docker containers, manual updates, or &lt;a href=&quot;https://github.blog/ai-and-ml/generative-ai/a-practical-guide-on-how-to-use-the-github-mcp-server/&quot;&gt;infrastructure maintenance&lt;/a&gt;. On top of that, as you are using the Oauth authentication and not a personal access token, it s a better alternative from a security point of view as well.&lt;/p&gt;
&lt;p&gt;There are multiple advantages to using the remote GitHub MCP server, which GitHub manages. There is no infrastructure overhead for you; getting started is much easier (just add a URL, authenticate, and you are good to go). As you are using a remote server, it will work on any device, including a remote machine/Cloud Shell running on a VM on a remote server.&lt;/p&gt;
&lt;p&gt;The remote GitHub MCP server is currently in &lt;a href=&quot;https://github.com/github/github-mcp-server?tab=readme-ov-file#install-in-other-mcp-hosts&quot;&gt;Public Preview&lt;/a&gt;. While access may be gated depending on the authentication type, it&#39;s the recommended path for most users due to its ease of use and reduced management burden. It allows you to focus on what you do best: writing code and building amazing things, not running an extra Docker container on your machine.&lt;/p&gt;
&lt;h2 id=&quot;remote-github-mcp-server-on-vs-code-with-copilot&quot; tabindex=&quot;-1&quot;&gt;Remote GitHub MCP server on VS Code with Copilot &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#remote-github-mcp-server-on-vs-code-with-copilot&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is where the magic truly happens. Integrating the remote GitHub MCP server with VS Code and GitHub Copilot elevates your AI-assisted development to a whole new level. Copilot, already a powerful coding assistant, becomes an even more intelligent and context-aware partner when it can access your GitHub data through MCP.&lt;/p&gt;
&lt;p&gt;When you use Copilot in VS Code with the GitHub MCP server configured, Copilot Chat&#39;s &amp;quot;Agent Mode&amp;quot; can perform complex tasks by invoking specialized tools exposed by the MCP server. This means you can interact with your GitHub repositories using natural language prompts, and Copilot will translate those into actions via the MCP server.&lt;/p&gt;
&lt;p&gt;For example, instead of manually navigating GitHub to create an issue, you could simply prompt Copilot: &amp;quot;Create a new issue on this repository for fixing a bug with the submit button style.&amp;quot;. The agent would then use the MCP server to interact with GitHub&#39;s APIs, creating the issue on your behalf. Similarly, you can ask it to create a pull request, list the last run GitHub action, and do many other things.&lt;/p&gt;
&lt;h3 id=&quot;step-by-step-guide-to-connect-vs-code-to-the-remote-github-mcp-server&quot; tabindex=&quot;-1&quot;&gt;Step-by-step guide to connect VS Code to the remote GitHub MCP server &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#step-by-step-guide-to-connect-vs-code-to-the-remote-github-mcp-server&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To connect the remote GitHub MCP server with your VS Code and Copilot, you will surely need VS Code (V1.92 or later) with the &lt;a href=&quot;https://code.visualstudio.com/docs/copilot/overview&quot;&gt;GitHub Copilot extension&lt;/a&gt; installed and a valid GitHub account. Also the current project should have a connected GitHub repository. With that in mind, let’s start:&lt;/p&gt;
&lt;h4 id=&quot;install-the-remote-mcp-server&quot; tabindex=&quot;-1&quot;&gt;Install the remote MCP Server &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#install-the-remote-mcp-server&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;To install a new MCP server on VS Code:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open the command palette (Cmd+Shift+p on a Mac) and run &lt;code&gt;&amp;gt; MCP: Add Server…&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;In the next step, select &lt;code&gt;HTTP (HTTP or Server Sent Events) Connect to a remote…&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;For the Server UR,L put &lt;code&gt;https://api.githubcopilot.com/mcp/&lt;/code&gt; and hit Enter to confirm&lt;/li&gt;
&lt;li&gt;Then, name the server &lt;code&gt;github-remote-mcp-server&lt;/code&gt; or something you feel is appropriate and hit Enter&lt;/li&gt;
&lt;li&gt;After that, select &lt;code&gt;Global&lt;/code&gt; or &lt;code&gt;Workspace&lt;/code&gt;. In my case, I selected &lt;code&gt;Global&lt;/code&gt; so that it runs on all projects&lt;/li&gt;
&lt;li&gt;Then it will ask you to allow the extension, click on “Allow”&lt;/li&gt;
&lt;li&gt;After that, it will ask for authentication. For that, select your GitHub account, which was &lt;code&gt;geshan&lt;/code&gt; in my case&lt;/li&gt;
&lt;li&gt;This will take you to the GitHub auth page to give the correct permissions.&lt;/li&gt;
&lt;li&gt;To test if it is connected, run this curl &lt;code&gt;curl -I https://api.githubcopilot.com/mcp/_ping&lt;/code&gt;. You will see an output like below (and your VS Code will look similar):&lt;/li&gt;
&lt;/ol&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/github-mcp-vscode/02github-remote-mcp-running.jpg&quot; loading=&quot;lazy&quot; title=&quot;Remote GitHub MCP server connected, authenticated and running on VS Code&quot; alt=&quot;Remote GitHub MCP server connected, authenticated and running on VS Code&quot; /&gt;
&lt;p&gt;Great! You have successfully connected the remote GitHub MCP server with our VS Code. If you want to give only read-only access, add the following, below the URL in the &lt;code&gt;mcp.json&lt;/code&gt; file:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;headers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;X-MCP-Readonly&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, you will list pull requests for a repo.&lt;/p&gt;
&lt;h4 id=&quot;list-the-pull-requests-for-a-repo&quot; tabindex=&quot;-1&quot;&gt;List the pull requests for a repo &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#list-the-pull-requests-for-a-repo&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;To list pull requests, you can type &lt;code&gt;#list_pull_requests&lt;/code&gt; in your GitHub Copilot &lt;code&gt;Agent&lt;/code&gt; mode, it will figure out the GitHub repo and try to list the open pull requests if any. If there are none, type in &lt;code&gt;list last three merged pull requests&lt;/code&gt; in a new GitHub Copilot chat, it should list them as below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/github-mcp-vscode/03github-mcp-list-pull-requests.jpg&quot; loading=&quot;lazy&quot; title=&quot;Listing pull requests on VS Code with GitHub Copilot Agent Mode on the current project&quot; alt=&quot;Listing pull requests on VS Code with GitHub Copilot Agent Mode on the current project&quot; /&gt;
&lt;h4 id=&quot;other-things-to-do-with-remote-github-mcp-server&quot; tabindex=&quot;-1&quot;&gt;Other things to do with remote GitHub MCP Server &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#other-things-to-do-with-remote-github-mcp-server&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;You can ask Copilot &lt;code&gt;What operations can you do on GitHub with the mpc server?&lt;/code&gt; It will list down the things it can do, as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/github-mcp-vscode/04github-copilot-mcp-operations.jpg&quot; loading=&quot;lazy&quot; title=&quot;Asking GitHub Copilot what operation can the GitHub MCP server do&quot; alt=&quot;Asking GitHub Copilot what operation can the GitHub MCP server do&quot; /&gt;
&lt;p&gt;From here, you can chat and know or do things you want with GitHub, like listing gists, creating gists, interacting with issues, or even opening a pull request directly from VS Code.&lt;/p&gt;
&lt;h4 id=&quot;mcp-server-settings&quot; tabindex=&quot;-1&quot;&gt;MCP server settings &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#mcp-server-settings&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;You can also go to the settings and turn on or off any of the remote GitHub MCP server tools as per your need, as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/github-mcp-vscode/05github-mcp-tools.jpg&quot; loading=&quot;lazy&quot; title=&quot;Listing all the tools in the remote GitHub MCP server in the GitHub Copilot settings&quot; alt=&quot;Listing all the tools in the remote GitHub MCP server in the GitHub Copilot settings&quot; /&gt;
&lt;p&gt;There you have it, a way to interact and do things with GitHub without leaving your VS Code editor.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/08/github-mcp-vscode/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this post, you learned about what MCP is and how to use the GitHub MCP Server. You can use the GitHub MCP server locally with Docker or without installing anything with the remote option.  After that, you learned how to use the remote GitHub MCP server on VS Code with GitHub Copilot. First, connect to the MCP server and authenticate, then perform a couple of tasks, such as listing the pull requests for the current repository. You also took a quick look at the tools of the GitHub MCP server and learned how to turn these tools on or off as needed.&lt;/p&gt;
&lt;p&gt;I hope you have gained some new knowledge about MCP in general and the official GitHub remote MCP server. Carry on learning!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to run Gemma 3 on Google Cloud Run, the easiest way with AI Studio</title>
		<link href="https://geshan.com.np/blog/2025/06/gemma3-on-cloud-run/"/>
		<updated>2025-06-08T10:59:24Z</updated>
		<id>https://geshan.com.np/blog/2025/06/gemma3-on-cloud-run/</id>
		<content type="html">&lt;p&gt;Gemma is a collection of lightweight, modern open models built by Google. They are designed to run fast on devices like phones, on machines in the cloud, to help developers create AI applications. In this post, you will learn the easiest and fastest way to run the latest version of &lt;a href=&quot;https://blog.google/technology/developers/gemma-3/&quot;&gt;Gemma, 3&lt;/a&gt; (4 B), on Google Cloud Run deployed from Google AI Studio. Let’s get started!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemma3-on-cloud-run/01gemma3-on-cloud-run.jpg&quot; title=&quot;How to run Gemma 3 on Google Cloud Run with AI Studio and the magic behind it&quot; alt=&quot;How to run Gemma 3 on Google Cloud Run with AI Studio and the magic behind it&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of Contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/06/gemma3-on-cloud-run/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/06/gemma3-on-cloud-run/#gemma-3-on-cloud-run&quot;&gt;Gemma 3 on Cloud Run&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/06/gemma3-on-cloud-run/#create-google-cloud-project&quot;&gt;Create Google Cloud Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/06/gemma3-on-cloud-run/#deploy-gemma-3-from-ai-studio&quot;&gt;Deploy Gemma 3 from AI Studio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/06/gemma3-on-cloud-run/#the-docker-image&quot;&gt;The Docker image&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/06/gemma3-on-cloud-run/#how-to-run-it-with-one-command&quot;&gt;How to run it with one command&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/06/gemma3-on-cloud-run/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;gemma-3-on-cloud-run&quot; tabindex=&quot;-1&quot;&gt;Gemma 3 on Cloud Run &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/06/gemma3-on-cloud-run/#gemma-3-on-cloud-run&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To deploy Gemma 3 (4 billion parameters model) on Google Cloud Run from Google AI Studio. Gemma 3 models’ size &lt;a href=&quot;https://ollama.com/library/gemma3&quot;&gt;ranges&lt;/a&gt; from 815 MB for 1B parameters to 17 GB for the 27B parameters. The model you will deploy is the 4B parameters, which is 3.3 GB.&lt;/p&gt;
&lt;p&gt;You will first create a new Google Cloud Project. You can deploy Gemma 3 from AI Studio with just a few clicks. When deployed from AI Studio, it uses Ollama under the hood to run Gemma 3 inside a container. In that container, there is a slim Go server/proxy to &lt;a href=&quot;https://github.com/google-gemini/gemma-cookbook/blob/main/Demos/Gemma-on-Cloudrun/proxy.go#L86&quot;&gt;verify&lt;/a&gt; the API key.&lt;/p&gt;
&lt;p&gt;You will also learn about a command you can run on Google Cloud Shell that will have a similar effect later in this tutorial. You will create a new Google Cloud Project in the next section to get going.&lt;/p&gt;
&lt;h3 id=&quot;create-google-cloud-project&quot; tabindex=&quot;-1&quot;&gt;Create Google Cloud Project &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/06/gemma3-on-cloud-run/#create-google-cloud-project&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To create a new Google Cloud Project, make sure you are logged into your Google Account. Then you can go to the &lt;a href=&quot;https://console.cloud.google.com/projectcreate&quot;&gt;Create new project&lt;/a&gt; page on GCP and fill in the following details:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemma3-on-cloud-run/02new-gcp-project.jpg&quot; loading=&quot;lazy&quot; title=&quot;Create a new GCP project to run Gemma 3 on Cloud Run&quot; alt=&quot;Create a new GCP project to run Gemma 3 on Cloud Run&quot; /&gt;
&lt;p&gt;After that, click the &lt;code&gt;Create&lt;/code&gt; blue button to create the project. It may take some time, and your project will be created, and you will be notified about that:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemma3-on-cloud-run/03gcp-project-created.jpg&quot; loading=&quot;lazy&quot; title=&quot;Created a new GCP project to run Gemma 3 on Cloud Run&quot; alt=&quot;Created a new GCP project to run Gemma 3 on Cloud Run&quot; /&gt;
&lt;p&gt;Note the project name you just created. Then, go to Google AI Studio and follow the steps shown in the next section.&lt;/p&gt;
&lt;h3 id=&quot;deploy-gemma-3-from-ai-studio&quot; tabindex=&quot;-1&quot;&gt;Deploy Gemma 3 from AI Studio &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/06/gemma3-on-cloud-run/#deploy-gemma-3-from-ai-studio&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;On &lt;a href=&quot;https://aistudio.google.com/&quot;&gt;Google AI Studio&lt;/a&gt;, go to the &lt;code&gt;Chat&lt;/code&gt; section, which should open by default:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemma3-on-cloud-run/04google-ai-studio-chat.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio with the default chat screen&quot; alt=&quot;Google AI Studio with the default chat screen&quot; /&gt;
&lt;p&gt;Under the &lt;code&gt;Run setting&lt;/code&gt; on the right side bar, click on the dropdown that has the model name selected, like &lt;code&gt;Gemini 2.5 Flash…&lt;/code&gt;, then select &lt;code&gt;Gemma&lt;/code&gt;, and after that click &lt;code&gt;Gemma 3 4B&lt;/code&gt;, as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemma3-on-cloud-run/05gemma3-4b-on-ai-studio.jpg&quot; loading=&quot;lazy&quot; title=&quot;Select Gemma 3 with 4 billion parameters on Google AI Studio&quot; alt=&quot;Select Gemma 3 with 4 billion parameters on Google AI Studio&quot; /&gt;
&lt;p&gt;On the selected &lt;code&gt;Gemma 3 4B&lt;/code&gt; model, bring the temperature down to &lt;code&gt;0.3&lt;/code&gt; and the Top P setting to &lt;code&gt;0.4&lt;/code&gt; , as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemma3-on-cloud-run/06gemma3-settings.jpg&quot; loading=&quot;lazy&quot; title=&quot;Setting the temparature (creativity) and top p settings for Gemma 3:4B on AI Studio&quot; alt=&quot;Setting the temparature (creativity) and top p settings for Gemma 3:4B on AI Studio&quot; /&gt;
&lt;p&gt;The above setting doesn&#39;t matter when you deploy. If you want, you can chat with Gemma 3 like ask it &lt;code&gt;why is the sky blue?, give the shortest possible answer&lt;/code&gt;. It should give back a one sentence answer.&lt;/p&gt;
&lt;p&gt;After that, click on the black and white Rocket icon (🚀) besides the &lt;code&gt;Run settings&lt;/code&gt; and click &lt;code&gt;Deploy to Cloud Run&lt;/code&gt; as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemma3-on-cloud-run/07ai-studio-gemma3-to-cloud-run.jpg&quot; loading=&quot;lazy&quot; title=&quot;Deploy Gemma 3 to Google Cloud Run from AI Studio&quot; alt=&quot;Deploy Gemma 3 to Google Cloud Run from AI Studio&quot; /&gt;
&lt;p&gt;Then, you can select the project created in the previous step, which was &lt;code&gt;gemma3-on-cr&lt;/code&gt; in my case:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemma3-on-cloud-run/08ai-studio-select-project.jpg&quot; loading=&quot;lazy&quot; title=&quot;Select GCP Project on Google AI Studio&quot; alt=&quot;Select GCP Project on Google AI Studio&quot; /&gt;
&lt;p&gt;After that, click the &lt;code&gt;Deploy to Google Cloud&lt;/code&gt; blue button. It will take some time to say &lt;code&gt;Deploying to Cloud Run&lt;/code&gt;. If all goes well after a couple of minutes, you will get a URL where Gemma 3 (4B) is running on Google Cloud Run with an API key as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemma3-on-cloud-run/09gemma3-deployed.jpg&quot; loading=&quot;lazy&quot; title=&quot;Gemma3 deployed on Cloud Run from Google AI Studio&quot; alt=&quot;Gemma3 deployed on Cloud Run from Google AI Studio&quot; /&gt;
&lt;p&gt;You can click the &lt;code&gt;Get code&lt;/code&gt; blue button to try a curl command to verify that Gemma 3 on Cloud Run works as expected, select &lt;code&gt;REST&lt;/code&gt; on the left select box, and copy the code:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemma3-on-cloud-run/10curl-to-test-gemma3-on-cloud-run.jpg&quot; loading=&quot;lazy&quot; title=&quot;Curl code to test Gemma3 deployed on Cloud Run from Google AI Studio&quot; alt=&quot;Curl code to test Gemma3 deployed on Cloud Run from Google AI Studio&quot; /&gt;
&lt;p&gt;When you run the copied code in the command line, add &lt;code&gt;give your answer in 1 sentence&lt;/code&gt;, then only run the code. The final code I ran was:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://gemma-3-4b-it-some-long-number-region.run.app/v1beta/models/gemma-3-4b-it:streamGenerateContent?key=the-api-key&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt;   &lt;span class=&quot;token parameter variable&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Content-Type: application/json&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt;   &lt;span class=&quot;token parameter variable&quot;&gt;-X&lt;/span&gt; POST &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt;   &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{&lt;br /&gt;     &quot;contents&quot;: [{&lt;br /&gt;       &quot;parts&quot;:[{&quot;text&quot;: &quot;How does AI work? give your answer in 1 sentence&quot;}]&lt;br /&gt;       }]&lt;br /&gt;      }&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which resulted in:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemma3-on-cloud-run/11gemma3-working.jpg&quot; loading=&quot;lazy&quot; title=&quot;Gemma 3 working on Cloud Run&quot; alt=&quot;Gemma 3 working on Cloud Run&quot; /&gt;
&lt;p&gt;Hurray! You have Gemma 3 running on Google Cloud Run. Now you can use it in your applications. You can add &lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/&quot;&gt;Open WebUI&lt;/a&gt; if you like.&lt;/p&gt;
&lt;h2 id=&quot;the-docker-image&quot; tabindex=&quot;-1&quot;&gt;The Docker image &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/06/gemma3-on-cloud-run/#the-docker-image&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;From the surface, it looks partially like magic, but most of the heavy lifting is being done by a prebuilt Docker image available on the Google Cloud Artifact registry (pkg.dev) built with Google Cloud Biuld.&lt;/p&gt;
&lt;p&gt;When you read the official docs about &lt;a href=&quot;https://github.com/google-gemini/gemma-cookbook/tree/main/Demos/Gemma-on-Cloudrun&quot;&gt;Gemma on Cloud Run&lt;/a&gt;, you can find out that there are pre-built Docker images like &lt;a href=&quot;http://us-docker.pkg.dev/cloudrun/container/gemma/gemma3-4b&quot;&gt;Gemma 3:4B&lt;/a&gt; on the package registry. As &lt;a href=&quot;https://cloud.google.com/run/docs/configuring/services/gpu&quot;&gt;GPUs on Cloud Run&lt;/a&gt; have become available on demand with no reservations needed, deploying any model with Ollama on Cloud Run has become much easier.&lt;/p&gt;
&lt;p&gt;The Dockerfile also has a &lt;a href=&quot;https://github.com/google-gemini/gemma-cookbook/blob/main/Demos/Gemma-on-Cloudrun/proxy.go&quot;&gt;proxy server&lt;/a&gt; to add the API key validation on top of a regular Ollama instance. It would be good to go through the &lt;a href=&quot;https://github.com/google-gemini/gemma-cookbook/tree/main/Demos/Gemma-on-Cloudrun&quot;&gt;readme&lt;/a&gt; to know more about this and other features.&lt;/p&gt;
&lt;p&gt;In the next section, you will learn about the single command for deploying Gemma 3 on Cloud Run.&lt;/p&gt;
&lt;h3 id=&quot;how-to-run-it-with-one-command&quot; tabindex=&quot;-1&quot;&gt;How to run it with one command &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/06/gemma3-on-cloud-run/#how-to-run-it-with-one-command&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To run Gemma 3:4B on Cloud Run, you can run the following command on &lt;a href=&quot;https://geshan.com.np/blog/2024/01/cloud-shell-editor/#google-cloud-shell-terminal&quot;&gt;Google Cloud Shell&lt;/a&gt; of your respective Google Cloud Project:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;gcloud run deploy gemma3-4b-dwc &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--image&lt;/span&gt; us-docker.pkg.dev/cloudrun/container/gemma/gemma3-4b &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--concurrency&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--cpu&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt; --set-env-vars &lt;span class=&quot;token assign-left variable&quot;&gt;OLLAMA_NUM_PARALLEL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt; --set-env-vars&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;API_KEY&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;gf2lv74w79ubm5lr &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--gpu&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt; --gpu-type nvidia-l4 &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt; --max-instances &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--memory&lt;/span&gt; 32Gi &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt; --allow-unauthenticated &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt; --no-cpu-throttling &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--timeout&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;600&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--region&lt;/span&gt; us-central1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can run it on Google Cloud Shell as:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemma3-on-cloud-run/12cloud-run-deploy-gemma3-4b.jpg&quot; loading=&quot;lazy&quot; title=&quot;Gcloud run deploy command to deploy Gemma 3 4B on Cloud Run&quot; alt=&quot;Gcloud run deploy command to deploy Gemma 3 4B on Cloud Run&quot; /&gt;
&lt;p&gt;It might ask you do deploy with &lt;code&gt;no zonal redundancy&lt;/code&gt;, write &lt;code&gt;y&lt;/code&gt; for yes, and it should deploy the service and give you back a URL as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemma3-on-cloud-run/13gemma3-deploy-with-cli.jpg&quot; loading=&quot;lazy&quot; title=&quot;Gemma 3 deploy with Gcloud run command&quot; alt=&quot;Gemma 3 deploy with Gcloud run command&quot; /&gt;
&lt;p&gt;If you hit the URL key with the API key, you can see the &lt;code&gt;Ollama is running&lt;/code&gt; message as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/gemma3-on-cloud-run/14gemma3-running.jpg&quot; loading=&quot;lazy&quot; title=&quot;Gemma 3 running deployed with Gcloud run command&quot; alt=&quot;Gemma 3 running deployed with Gcloud run command&quot; /&gt;
&lt;p&gt;There you have it. Now you know you have decoded the secret of the magic AI studio doing in the background to enable the API key. Gemma 3 is running on Google Cloud Run with Ollama and a proxy server written in Go.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/06/gemma3-on-cloud-run/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this post, you learned about deploying Gemma 3 on Google Cloud Run through Google AI Studio&#39;s intuitive interface, which simplifies a complex process into a few clicks. You also learned that this deployment leverages Ollama and pre-built Docker images from the Google Cloud Artifact Registry, enhanced with a Go-based proxy server for API key validation.&lt;/p&gt;
&lt;p&gt;Additionally, you could decode the magic using a single gcloud command within the Google Cloud Shell, offering flexibility and control over deployment parameters like concurrency, CPU, GPU, and memory. Both methods result in a functional Gemma 3 instance on Cloud Run, ready to be integrated into applications, providing developers like you with powerful AI model capabilities with minimal effort. Keep experimenting!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Google AI Studio: How to go from a prompt to a geo-location guessing app in minutes</title>
		<link href="https://geshan.com.np/blog/2025/05/google-ai-studio-apps/"/>
		<updated>2025-05-22T10:58:57Z</updated>
		<id>https://geshan.com.np/blog/2025/05/google-ai-studio-apps/</id>
		<content type="html">&lt;p&gt;Can you code and deploy a basic but functional app with minimal coding experience? With the latest Google AI Studio feature, you can build and deploy apps by instructing an agent in minutes. You can also deploy the app on Google Cloud Run and make changes easily. This post will show you how. Let’s get started!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/01google-ai-studio-apps.jpg&quot; title=&quot;Generate, create and deploy a geo-location guessing app using Google AI Studio and run it on Google Cloud Run&quot; alt=&quot;Generate, create and deploy a geo-location guessing app using Google AI Studio and run it on Google Cloud Run&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/05/google-ai-studio-apps/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/05/google-ai-studio-apps/#the-goal&quot;&gt;The goal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/05/google-ai-studio-apps/#build-an-app-with-a-prompt-on-google-ai-studio&quot;&gt;Build an app with a prompt on Google AI Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/05/google-ai-studio-apps/#deploy-to-google-cloud-run&quot;&gt;Deploy to Google Cloud Run&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/05/google-ai-studio-apps/#making-a-change-and-redeploy&quot;&gt;Making a change and redeploy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/05/google-ai-studio-apps/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-goal&quot; tabindex=&quot;-1&quot;&gt;The goal &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/05/google-ai-studio-apps/#the-goal&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Your goal is to build a Gen AI (LLM)- powered application that will take an image (of a popular place) and then give you back the Country, City, state, place, and the geolocation coordinates of that place. A creative use of this can be stalking and knowing where your friends went by using their Instagram photos. Other usages are up to you. This is more of a proof-of-concept fun project to demonstrate the power of LLM and Gen AI with Gemini 2.5 models.&lt;/p&gt;
&lt;h2 id=&quot;build-an-app-with-a-prompt-on-google-ai-studio&quot; tabindex=&quot;-1&quot;&gt;Build an app with a prompt on Google AI Studio &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/05/google-ai-studio-apps/#build-an-app-with-a-prompt-on-google-ai-studio&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Go to &lt;a href=&quot;https://aistudio.google.com/&quot;&gt;Google AI Studio&lt;/a&gt;, then click on the &lt;code&gt;Build&lt;/code&gt; link in left menu as shown below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/02google-ai-studio-build.jpg&quot; loading=&quot;lazy&quot; title=&quot;Go to Google AI Studio and click on the Build link on the left menu&quot; alt=&quot;Go to Google AI Studio and click on the Build link on the left menu&quot; /&gt;
&lt;p&gt;Then paste the following in the prompt text area;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Build an app that can guess Geo location from a given image:
You are an OSINT investigator. Your job is to geolocate where the photos are taken.
Provide the country, region, and city name of the location. 
Please pinpoint the exact location with latitude and longitude where the photo was taken.  

Could you always explain your methodology and how you concluded? 
Provide steps to verify your work. 
Also, mention the percentage of how sure you are of the place you have identified it to be 
and add a Google Maps link to the exact location
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will look something like the below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/03google-ai-studio-app-prompt.jpg&quot; loading=&quot;lazy&quot; title=&quot;In the Build (apps) page input the above prompt and click the blue Build button&quot; alt=&quot;In the Build (apps) page input the above prompt and click the blue Build button&quot; /&gt;
&lt;p&gt;After that, click the blue &lt;code&gt;Build&lt;/code&gt; button. It will use a code agent/assistant like &lt;a href=&quot;https://jules.google/&quot;&gt;Google Jules AI&lt;/a&gt; and start “thinking” and writing the whole application as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/04google-ai-studio-building-app.jpg&quot; loading=&quot;lazy&quot; title=&quot;It thinks for some time (under a minute) an the starts creating the files for the Javascript (React, vite) app&quot; alt=&quot;It thinks for some time (under a minute) an the starts creating the files for the Javascript (React, vite) app&quot; /&gt;
&lt;p&gt;It will take a couple of minutes (or a bit longer), and then it will generate the full app in React and TypeScript. It uses Tailwind CSS for styling. When the app generation is complete, it will look as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/05google-ai-studio-app-created.jpg&quot; loading=&quot;lazy&quot; title=&quot;In a couple of minutes the React, Vite app is created with Tailwind CSS styling that can guess the geo location for a given picture, it also has a dark and light theme switcher&quot; alt=&quot;In a couple of minutes the React, Vite app is created with Tailwind CSS styling that can guess the geo location for a given picture, it also has a dark and light theme switcher&quot; /&gt;
&lt;p&gt;The application preview is available on the right panel, so you can upload and test a picture like &lt;a href=&quot;https://geshan.com.np/images/google-ai-studio-apps/statue-of-liberty-1075752_1920.jpg&quot;&gt;this&lt;/a&gt; one (Statue of Liberty). It will analyze the photo and guess the geo location as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/06geo-location-guess-ny.jpg&quot; loading=&quot;lazy&quot; title=&quot;Testing the Geo location gussing app in preview with a picture of Statue of Liberty, New York&quot; alt=&quot;Testing the Geo location gussing app in preview with a picture of Statue of Liberty, New York&quot; /&gt;
&lt;p&gt;You can even click the provided Google Maps link and see where the place is. You can scroll down to see the methodology and the verification steps as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/07sl-ny-location-details.jpg&quot; loading=&quot;lazy&quot; title=&quot;Checking methodology and verification details of the picture of Statue of Liberty New York in the Geo location guessing app&quot; alt=&quot;Checking methodology and verification details of the picture of Statue of Liberty New York in the Geo location guessing app&quot; /&gt;
&lt;p&gt;In the next section,  you will deploy the generated (vibe-coded) app to Google Cloud Run.&lt;/p&gt;
&lt;h2 id=&quot;deploy-to-google-cloud-run&quot; tabindex=&quot;-1&quot;&gt;Deploy to Google Cloud Run &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/05/google-ai-studio-apps/#deploy-to-google-cloud-run&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://geshan.com.np/blog/2023/04/serverless-containers/#google-cloud-run&quot;&gt;Google Cloud Run&lt;/a&gt; is a fully managed compute platform that automatically scales your stateless containers. It is a great way to deploy your applications without worrying about the underlying infrastructure.&lt;/p&gt;
&lt;p&gt;You will need an existing project and some credits in your Google Cloud Account to deploy to Google Cloud Run. If you do not have an existing project on Google Cloud, you can create a &lt;a href=&quot;https://geshan.com.np/blog/2025/05/google-ai-studio-apps/%E2%80%8B%E2%80%8Bhttps://console.cloud.google.com/projectcreate&quot;&gt;new one&lt;/a&gt; as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/08new-gcp-project.jpg&quot; loading=&quot;lazy&quot; title=&quot;Create a new GCP project to deploy the Geo location app on Google Cloud Run&quot; alt=&quot;Create a new GCP project to deploy the Geo location app on Google Cloud Run&quot; /&gt;
&lt;p&gt;It will take some time, and the project will be created; you will be notified of that. In my case, the project name is &lt;code&gt;geo-location-app&lt;/code&gt;, and it will look like the following:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/09gcp-project-created.jpg&quot; loading=&quot;lazy&quot; title=&quot;New GCP project created to deploy the Geo location app on Google Cloud Run&quot; alt=&quot;New GCP project created to deploy the Geo location app on Google Cloud Run&quot; /&gt;
&lt;p&gt;To deploy the generated (vibe-coded) application that you have tested. Go back to the &lt;code&gt;Build&lt;/code&gt; page of the generated app. In the &lt;code&gt;Preview&lt;/code&gt; section on the right, click the Rocket (🚀)  black and white icon on the top right corner above &lt;code&gt;Preview&lt;/code&gt;:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/10google-ai-studio-deploy.jpg&quot; loading=&quot;lazy&quot; title=&quot;Click deploy icon on top of the Preview section in Google AI Studio Build page&quot; alt=&quot;Click deploy icon on top of the Preview section in Google AI Studio Build page&quot; /&gt;
&lt;p&gt;Then, search and select the project you just created on Google Cloud Console, in my case it is &lt;code&gt;geo-location-app&lt;/code&gt;, then click the &lt;code&gt;Deploy app&lt;/code&gt; blue button as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/11select-project.jpg&quot; loading=&quot;lazy&quot; title=&quot;To deploy the generated app to Cloud Run select the project you just created - geo-location-app in my case&quot; alt=&quot;To deploy the generated app to Cloud Run select the project you just created - geo-location-app in my case&quot; /&gt;
&lt;p&gt;It will take some time to deploy the React App on Google Cloud Run, starting with verifying the project:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/12verifying-project.jpg&quot; loading=&quot;lazy&quot; title=&quot;Before deploying Google AI Studio will verify the project&quot; alt=&quot;Before deploying Google AI Studio will verify the project&quot; /&gt;
&lt;p&gt;Then it will show &lt;code&gt;Deploying to Cloud Run&lt;/code&gt; and finally give you a link to try out your Geo location guessing app, as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/13project-deployed.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio has deployed the project successfully on Google Cloud Run&quot; alt=&quot;Google AI Studio has deployed the project successfully on Google Cloud Run&quot; /&gt;
&lt;p&gt;You can click the &lt;code&gt;App URL&lt;/code&gt; link or the &lt;code&gt;View app&lt;/code&gt; button to see the app working on a publicly accessible URL, the same as the one you tested in the preview. When you click the &lt;code&gt;View app&lt;/code&gt; blue button, you will see the app in action:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/14running-app.jpg&quot; loading=&quot;lazy&quot; title=&quot;The Geo location guessing React App is running on Google Cloud Run deployed by a click on Google AI Studio&quot; alt=&quot;The Geo location guessing React App is running on Google Cloud Run deployed by a click on Google AI Studio&quot; /&gt;
&lt;p&gt;You can upload the same Statue of Liberty &lt;a href=&quot;https://geshan.com.np/images/google-ai-studio-apps/statue-of-liberty-1075752_1920.jpg&quot;&gt;photo&lt;/a&gt; or any other famous landmark and see how it works:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/15app-tested.jpg&quot; loading=&quot;lazy&quot; title=&quot;The Geo location guessing React App tested on Google Cloud Run with the Statue of Liberty photo&quot; alt=&quot;The Geo location guessing React App tested on Google Cloud Run with the Statue of Liberty photo&quot; /&gt;
&lt;p&gt;You can also upload a picture of the Eiffel Tower, and it will guess the location as Paris, France. Give it a shot. You can also switch from light to dark theme and back.&lt;/p&gt;
&lt;p&gt;Your app is auto-saved and you can find it in the &lt;code&gt;Your Apps&lt;/code&gt; tab in the Google AI Studio’s &lt;code&gt;Build&lt;/code&gt; page:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/16app-saved.jpg&quot; loading=&quot;lazy&quot; title=&quot;The Geo location guessing React App is auto saved by Google AI Studio and available in the Your apps tab&quot; alt=&quot;The Geo location guessing React App is auto saved by Google AI Studio and available in the Your apps tab&quot; /&gt;
&lt;p&gt;Next, you will learn how to make a change and redeploy the app to Cloud Run.&lt;/p&gt;
&lt;h2 id=&quot;making-a-change-and-redeploy&quot; tabindex=&quot;-1&quot;&gt;Making a change and redeploy &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/05/google-ai-studio-apps/#making-a-change-and-redeploy&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can make a change to the app and redeploy it. In my case, I want to remove the mention of &lt;code&gt;OSINT&lt;/code&gt; from the interface, and I will instruct/vibe code the &lt;code&gt;Code assistant&lt;/code&gt; section of the app with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Remove all the mentions of &amp;quot;OSINT&amp;quot; from the user interface, but keep it in the prompt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can input the new instruction as follows and hit the blue up button as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/17prompt-to-change.jpg&quot; loading=&quot;lazy&quot; title=&quot;The Geo location guessing React App is changed on Google AI Studio with a prompt to remove OSINT&quot; alt=&quot;The Geo location guessing React App is changed on Google AI Studio with a prompt to remove OSINT&quot; /&gt;
&lt;p&gt;It will take some time to do the given task, after some thinking (in my case, 10 seconds), it started editing the files. The app looked like the following after the change was made:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/18app-updated.jpg&quot; loading=&quot;lazy&quot; title=&quot;The Geo location guessing React App is updated on Google AI Studio with OSINT removed from the UI&quot; alt=&quot;The Geo location guessing React App is updated on Google AI Studio with OSINT removed from the UI&quot; /&gt;
&lt;p&gt;As the change has been made and the app has been tested in preview. You can save the new change by hitting the save icon above the preview. You can redeploy it to Google Cloud Run. To do this, click the Rocket (🚀)  black and white icon on the top right corner above &lt;code&gt;Preview&lt;/code&gt; and select the same project (it was &lt;code&gt;geo-location-app&lt;/code&gt; in my case):&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/19select-project-redeploy.jpg&quot; loading=&quot;lazy&quot; title=&quot;Select project to redeploy the app to get the new change on Cloud Run&quot; alt=&quot;Select project to redeploy the app to get the new change on Cloud Run&quot; /&gt;
&lt;p&gt;It verifies the project and, given that the app is already deployed in that project, it gives you a &lt;code&gt;Redeploy app&lt;/code&gt; link, which you can click to redeploy the change to Google Cloud Run:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/20redeploy-app.jpg&quot; loading=&quot;lazy&quot; title=&quot;Redeploy the app on the same project to get the new change&quot; alt=&quot;Redeploy the app on the same project to get the new change&quot; /&gt;
&lt;p&gt;It will take some time to redeploy the app, and you will see the &lt;code&gt;Deploying to Cloud Run&lt;/code&gt; message.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/21redeploying-app.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio redeploying the app to the same Google Cloud Project&quot; alt=&quot;Google AI Studio redeploying the app to the same Google Cloud Project&quot; /&gt;
&lt;p&gt;It will redeploy the app and give you the same link to the app, which you can test and verify that the change has been deployed and released. After you click &lt;code&gt;View app&lt;/code&gt;, I can see that the update has been done:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/22app-updated.jpg&quot; loading=&quot;lazy&quot; title=&quot;App updated after redeployment from Google AI Studio to Cloud Run&quot; alt=&quot;App updated after redeployment from Google AI Studio to Cloud Run&quot; /&gt;
&lt;p&gt;After the change, I tested the app to ensure it worked as expected. There is no mention of &lt;code&gt;OSINT&lt;/code&gt; anymore, which is what I wanted. Google Cloud credits are provided for this project. Thanks to Google.&lt;/p&gt;
&lt;p&gt;There you have it—you vibe coded a fully functioning app that started with a simple idea and a single prompt. You also deployed it on a publicly accessible URL, which you can share with friends. As it is running on Google Cloud, it will cost you money, so be sure to check your costs on Google Cloud Billing and stop the app if you need to. After testing, you can delete the project with the app running on Google Cloud Run.&lt;/p&gt;
&lt;p&gt;In my case, the primary prompt and calling the API were in the &lt;a href=&quot;https://github.com/geshan/geo-guesser-ai/blob/master/services/geminiService.ts&quot;&gt;services/geminiService.ts&lt;/a&gt; file, which was using &lt;code&gt;gemini-2.5-flash-preview-04-17&lt;/code&gt; with a pretty well-crafted prompt. The whole app is available in this open-source &lt;a href=&quot;https://github.com/geshan/geo-guesser-ai/tree/master&quot;&gt;GitHub repository&lt;/a&gt;. From the code I read, it looks like a frontend-only app, so how it handles the API key and its security is your responsibility.&lt;/p&gt;
&lt;p&gt;You can read the &lt;a href=&quot;https://aistudio.google.com/apps?source=faq&quot;&gt;FAQs&lt;/a&gt; on Google AI Studio Build/Apps page, which tell you that it is a frontend only app and other details about how it runs in an Iframe on Google Cloud Run.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-ai-studio-apps/23gogole-ai-studio-apps-faq.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google AI Studio Build (apps) page FAQs&quot; alt=&quot;Google AI Studio Build (apps) page FAQs&quot; /&gt;
&lt;p&gt;The goal was to have a working app, and you have it, even with a dark and light theme switcher. It is a good starting point, but I would not consider it production-ready; use it cautiously and carefully. If you think something is wrong, delete the app from Cloud Run and/or delete the whole project. I don’t want you bleeding money on Google Cloud Platform.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/05/google-ai-studio-apps/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this tutorial, you started with the goal of having a working Gen AI-powered and generated app that can guess the geolocation from a picture. You then generated the full app using Google AI Studio Apps/build feature. After that, you created and deployed a Google Cloud project to Google Cloud Run. Finally, you made changes to remove the &lt;code&gt;OSINT&lt;/code&gt; mention from the user interface and redeployed the app to Google Cloud Run in the same Google Cloud Project.&lt;/p&gt;
&lt;p&gt;It is pretty easy to go from an idea and prompt to a fully functional app accessible over the Internet and deployed on Google Cloud Run. To manage costs effectively, remember to monitor your Google Cloud billing and stop the app if needed. Keep learning and using Gemini and Google AI Studio!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Cloud Run Jobs: A Beginner&#39;s Guide to Running Tasks to Completion on a schedule</title>
		<link href="https://geshan.com.np/blog/2025/04/cloud-run-jobs/"/>
		<updated>2025-04-29T11:38:57Z</updated>
		<id>https://geshan.com.np/blog/2025/04/cloud-run-jobs/</id>
		<content type="html">&lt;p&gt;With Cloud Run, just bring your code! Google handles the complex server stuff and scaling, so you don&#39;t have to. Typically, you could run only web services with a URL on Google Cloud Run as services. For some time now, you can also run Cloud Run Jobs to execute a task to completion, which might take longer than minutes or even hours. In this beginner-friendly post, you will learn how to run jobs on Cloud Run Jobs on a schedule. Let’s get going!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/01cloud-run-jobs.jpg&quot; title=&quot;Create and run Cloud Run Jobs on a schedlue with Google Cloud Scheduler&quot; alt=&quot;Create and run Cloud Run Jobs on a schedlue with Google Cloud Scheduler&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of Contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/04/cloud-run-jobs/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/04/cloud-run-jobs/#cloud-run-jobs&quot;&gt;Cloud Run Jobs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/04/cloud-run-jobs/#how-cloud-run-jobs-handles-parallel-tasks&quot;&gt;How Cloud Run Jobs handles parallel tasks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/04/cloud-run-jobs/#simple-cloud-run-job-example&quot;&gt;Simple Cloud Run job example&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/04/cloud-run-jobs/#create-a-cloud-run-job-using-google-cloud-shell&quot;&gt;Create a Cloud Run Job using Google Cloud Shell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/04/cloud-run-jobs/#create-a-job-schedule-with-google-cloud-scheduler&quot;&gt;Create a job schedule with Google Cloud Scheduler&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/04/cloud-run-jobs/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;cloud-run-jobs&quot; tabindex=&quot;-1&quot;&gt;Cloud Run Jobs &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/04/cloud-run-jobs/#cloud-run-jobs&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Unlike Google Cloud Run services, which are executed when a web server receives a web request (such as a GET or POST), &lt;a href=&quot;https://cloud.google.com/run/docs/create-jobs&quot;&gt;Cloud Run Jobs&lt;/a&gt; are specifically designed for tasks that need to run, perform some work, and then terminate once that work is complete. They don&#39;t listen for incoming requests like services do.&lt;/p&gt;
&lt;p&gt;Cloud Run Jobs are task-oriented, executing a specific piece of work, such as scraping a website, converting a PDF invoice to database records, taking a screenshot,  fine-tuning an LLM, or resizing images. They do not require a web server and can be triggered one-off, at a specific time (such as 2 am each morning) or as a &lt;a href=&quot;https://cloud.google.com/workflows/docs/tutorials/execute-cloud-run-jobs&quot;&gt;part&lt;/a&gt; of a &lt;a href=&quot;https://cloud.google.com/workflows?hl=en&quot;&gt;GCP Workflow&lt;/a&gt;. These jobs run to completion and can run up to 10,000 tasks in parallel. Tasks have an index number and a count of runs; tasks can also be configured to retry.&lt;/p&gt;
&lt;p&gt;In essence, if you have a containerized task that needs to run periodically, on demand, or part of a workflow and complete its work without serving requests, and then shut down, Cloud Run Jobs are a suitable serverless option on Google Cloud.&lt;/p&gt;
&lt;h2 id=&quot;how-cloud-run-jobs-handles-parallel-tasks&quot; tabindex=&quot;-1&quot;&gt;How Cloud Run Jobs handles parallel tasks &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/04/cloud-run-jobs/#how-cloud-run-jobs-handles-parallel-tasks&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the powerful features of Cloud Run Jobs is its ability to handle parallel task execution. This is particularly useful for batch processing workloads where you can divide the work into independent chunks that can be processed concurrently. You can execute up to 1,000 jobs per project per region, as outlined in the Cloud Run &lt;a href=&quot;https://cloud.google.com/run/quotas&quot;&gt;quotas&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When you define a Cloud Run Job, you can specify the &lt;code&gt;parallelism&lt;/code&gt; &lt;a href=&quot;https://geshan.com.np/blog/2025/04/cloud-run-jobs/(https://cloud.google.com/run/docs/configuring/parallelism)&quot;&gt;setting&lt;/a&gt;. This setting determines the maximum number of Task Instances that can run concurrently within a single Job Execution.&lt;/p&gt;
&lt;p&gt;Imagine you have a job that requires processing 100 items, and your container is designed to process one item at a time. If you set &lt;code&gt;parallelism&lt;/code&gt; to 10, when you execute the job, Cloud Run Jobs will attempt to run up to 10 Task Instances simultaneously. Each Task Instance will receive information about which specific item(s) it should process.&lt;/p&gt;
&lt;p&gt;How does a Task Instance know which part of the work to do? Cloud Run Jobs provides environment variables to each Task Instance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CLOUD_RUN_TASK_INDEX&lt;/code&gt;: This variable provides a unique index for each Task Instance within a Job Execution, starting from 0 up to &lt;code&gt;parallelism - 1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CLOUD_RUN_TASK_COUNT&lt;/code&gt;: This variable provides the total number of Task Instances expected for this Job Execution, which is equal to the &lt;code&gt;parallelism&lt;/code&gt; setting.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Your container&#39;s code can read these environment variables to determine its specific slice of the work. For example, if you have 100 items to process and &lt;code&gt;parallelism&lt;/code&gt; is set to 10, Task Instance 0 might process items 1-10, Task Instance 1 processes items 11-20, and so on, up to Task Instance 9 processing items 90-100. Your code would use &lt;code&gt;CLOUD_RUN_TASK_INDEX&lt;/code&gt; and &lt;code&gt;CLOUD_RUN_TASK_COUNT&lt;/code&gt; to calculate the range of items it&#39;s responsible for.&lt;/p&gt;
&lt;p&gt;Cloud Run Jobs manages the lifecycle of these Task Instances. If a Task Instance fails (e.g., due to an error in your code or a temporary infrastructure issue), Cloud Run Jobs can be configured to retry that specific Task Instance up to a specified number of times. This ensures that even if some parts of your batch fail, the overall job execution can still complete successfully by retrying the failed tasks.&lt;/p&gt;
&lt;p&gt;The ability to run tasks in parallel significantly speeds up the execution of batch workloads. Instead of processing 100 items sequentially in one container, you can process them concurrently across multiple containers, which drastically reduces the total time required for job execution. This is similar to having various workers tackle different parts of a large project simultaneously, rather than having one worker complete everything step by step.&lt;/p&gt;
&lt;p&gt;By default, each task runs for a maximum of 10 minutes. You can modify the default value by changing the task timeout setting, up to a maximum of 168 hours (7 days). Support for timeouts greater than 24 hours is available in Preview.&lt;/p&gt;
&lt;h2 id=&quot;simple-cloud-run-job-example&quot; tabindex=&quot;-1&quot;&gt;Simple Cloud Run job example &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/04/cloud-run-jobs/#simple-cloud-run-job-example&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This tutorial focuses on learning how to create and run Google Cloud Run Jobs on Google Cloud Platform (GCP). The code example you will use is the official Node.js quickstart for Cloud Run Jobs.&lt;/p&gt;
&lt;p&gt;You will use the &lt;code&gt;gcloud&lt;/code&gt; &lt;a href=&quot;https://cloud.google.com/cli?hl=en&quot;&gt;cli command&lt;/a&gt; over Google Cloud Shell to do most of the work, and you will not need to install anything on your local machine. Let’s get started!&lt;/p&gt;
&lt;p&gt;The main &lt;code&gt;index.js&lt;/code&gt; file has the following contents:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Retrieve Job-defined env vars&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;CLOUD_RUN_TASK_INDEX&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CLOUD_RUN_TASK_ATTEMPT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Retrieve User-defined env vars&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;SLEEP_MS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;FAIL_RATE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Define main script&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Starting Task #&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;CLOUD_RUN_TASK_INDEX&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;, Attempt #&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;CLOUD_RUN_TASK_ATTEMPT&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Simulate work&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;SLEEP_MS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;SLEEP_MS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Simulate errors&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;FAIL_RATE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token function&quot;&gt;randomFailure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;FAIL_RATE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      err&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Task #&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;CLOUD_RUN_TASK_INDEX&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;, Attempt #&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;CLOUD_RUN_TASK_ATTEMPT&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; failed.&#92;n&#92;n&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Completed Task #&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;CLOUD_RUN_TASK_INDEX&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Wait for a specific amount of time&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;sleep&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;ms&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ms&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Throw an error based on fail rate&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;randomFailure&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;rate&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  rate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseFloat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;rate &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; rate &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; rate &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;warn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Invalid FAIL_RATE env var value: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;rate&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;. Must be a float between 0 and 1 inclusive.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; randomFailure &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;randomFailure &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; rate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Task failed.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Start script&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Retry Job Task by exiting the process&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The main things you need to understand here are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The script executes with the &lt;code&gt;main&lt;/code&gt; call on line no. 49, which has a catch attached to it. It would have been easier with a &lt;a href=&quot;https://geshan.com.np/blog/2024/06/javascript-try-catch/&quot;&gt;JavaScript try catch&lt;/a&gt; block, but this is the official example. So, let’s just roll with it.&lt;/li&gt;
&lt;li&gt;Before the &lt;code&gt;main&lt;/code&gt; function on line 7, four environment variables are taken out of the &lt;code&gt;process.env&lt;/code&gt; with object destructuring. Those are &lt;code&gt;CLOUD_RUN_TASK_INDEX&lt;/code&gt; and &lt;code&gt;CLOUD_RUN_TASK_ATTEMPT&lt;/code&gt;, which are used to determine the task&#39;s position within the job and the retry attempt (if the job has failed).&lt;/li&gt;
&lt;li&gt;The other two are &lt;code&gt;SLEEP_MS&lt;/code&gt; and &lt;code&gt;FAIL_RATE&lt;/code&gt;, which are used to sleep for a given number of milliseconds and specify the failure rate as a percentage, respectively. For example, &lt;code&gt;0.1&lt;/code&gt; represents 10% and &lt;code&gt;1.0&lt;/code&gt; represents 100%, which will never work.&lt;/li&gt;
&lt;li&gt;The main task (in the job is the &lt;code&gt;main&lt;/code&gt; function), which logs the task number and the attempts first.&lt;/li&gt;
&lt;li&gt;Then it waits for the specified milliseconds and, next, randomizes the failure according to the failure rate.&lt;/li&gt;
&lt;li&gt;Lastly, it logs the index of the computed tasks.&lt;/li&gt;
&lt;li&gt;Below that, there is a &lt;code&gt;sleep&lt;/code&gt; function to just block the process and wait for the specified number of milliseconds.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next, you will see how to add it as a Cloud Run job using the Google Cloud Shell.&lt;/p&gt;
&lt;h3 id=&quot;create-a-cloud-run-job-using-google-cloud-shell&quot; tabindex=&quot;-1&quot;&gt;Create a Cloud Run Job using Google Cloud Shell &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/04/cloud-run-jobs/#create-a-cloud-run-job-using-google-cloud-shell&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To get started, you will need some knowledge of Git, GitHub, and Google Cloud Shell.&lt;/p&gt;
&lt;p&gt;Given that you are logged into your Google account. First, you will create a new Google Cloud Project on this &lt;a href=&quot;https://console.cloud.google.com/projectcreate&quot;&gt;page&lt;/a&gt;. You can name it &lt;code&gt;cloud-run-jobs&lt;/code&gt; as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/02create-gcp-project.jpg&quot; loading=&quot;lazy&quot; title=&quot;Create a GCP Project named cloud-run-jobs and copy the Project ID&quot; alt=&quot;Create a GCP Project named cloud-run-jobs and copy the Project ID&quot; /&gt;
&lt;p&gt;Ensure that you copy the &lt;code&gt;Project ID&lt;/code&gt;, as you will need it later, and then click the &lt;code&gt;Create&lt;/code&gt; button at the end of the form. It will take a couple of minutes, and you will be taken to the dashboard of the new project as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/03select-gcp-project.jpg&quot; loading=&quot;lazy&quot; title=&quot;Select the GCP Project named cloud-run-jobs&quot; alt=&quot;Select the GCP Project named cloud-run-jobs&quot; /&gt;
&lt;p&gt;Ensure that the recently created project is selected; alternatively, you can click &lt;code&gt;Select Project&lt;/code&gt; from the notification message.&lt;/p&gt;
&lt;p&gt;After that, click on the &lt;code&gt;Cloud Shell&lt;/code&gt; icon besides the bell icon on the top right (or press g and s, on your keyboard). The Cloud Shell will appear at the bottom of the screen and ask for permission. Click &lt;code&gt;Authorize&lt;/code&gt;:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/04authorize-cloud-shell.jpg&quot; loading=&quot;lazy&quot; title=&quot;Open Cloud shell and authorize it in GCP Console&quot; alt=&quot;Open Cloud shell and authorize it in GCP Console&quot; /&gt;
&lt;p&gt;In the shell, type in (or copy and paste) the following command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; projects &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; projects &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone https://github.com/geshan/cloud-run-jobs.git &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; cloud-run-jobs&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The command will create a directory called projects, go into that folder and clone the demo repository with the above code, and go into the &lt;code&gt;cloud-run-jobs&lt;/code&gt; repository folder as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/05clone-project.jpg&quot; loading=&quot;lazy&quot; title=&quot;Create projects directory and clone project into it, then go into cloud-run-jobs directory&quot; alt=&quot;Create projects directory and clone project into it, then go into cloud-run-jobs directory&quot; /&gt;
&lt;p&gt;After that, set the project ID variable to the variable you copied while creating the project (or copy it from your Google Cloud CLI), it should look like &lt;code&gt;cloud-run-jobs-&amp;lt;some-numbers-here&amp;gt;&lt;/code&gt;, which in my case was &lt;code&gt;cloud-run-jobs-458310&lt;/code&gt;. The command is below:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;PROJECT_ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;cloud-run-jobs-&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;some-numbers-here-replace-this&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$PROJECT_ID&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, to create the Cloud run job after building from source with a build pack (not using a Docker container), run the following command on your Google Cloud Shell:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;gcloud run &lt;span class=&quot;token function&quot;&gt;jobs&lt;/span&gt; deploy job-quickstart &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token parameter variable&quot;&gt;--source&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token parameter variable&quot;&gt;--tasks&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt;    --set-env-vars &lt;span class=&quot;token assign-left variable&quot;&gt;SLEEP_MS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt;    --set-env-vars &lt;span class=&quot;token assign-left variable&quot;&gt;FAIL_RATE&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0.1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt;    --max-retries &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token parameter variable&quot;&gt;--region&lt;/span&gt; us-central1 &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token parameter variable&quot;&gt;--project&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$PROJECT_ID&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here you are asking Google Cloud Command to create a Cloud Run job called &lt;code&gt;job-quickstart&lt;/code&gt; , where the code is taken from the local directory &lt;code&gt;.&lt;/code&gt;. You are specifying that the job has five tasks and will sleep for 5 seconds (5000 milliseconds) with a 10% failure rate (0.1) and can be retried up to 3 times on failure.&lt;/p&gt;
&lt;p&gt;For the region you are using &lt;code&gt;us-central1&lt;/code&gt;, and the project ID is the same as you set in the previous command. It looks like the below when it executes:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/06deploy-cloud-run-jobs.jpg&quot; loading=&quot;lazy&quot; title=&quot;Deploy cloud run jobs with PROJECT ID as a variable using gcloud command&quot; alt=&quot;Deploy cloud run jobs with PROJECT ID as a variable using gcloud command&quot; /&gt;
&lt;p&gt;It will ask you to enable APIs, hit &lt;code&gt;Y&lt;/code&gt; to enable all related APIs, as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/07enable-apis.jpg&quot; loading=&quot;lazy&quot; title=&quot;Agree to enable APIs while deploying cloud run jobs using gcloud command&quot; alt=&quot;Agree to enable APIs while deploying cloud run jobs using gcloud command&quot; /&gt;
&lt;p&gt;If you encounter an Error, it may be because the APIs require some time to become enabled. So, try again after a couple of minutes. When it works, it will look something like the following:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/08deploy-success.jpg&quot; loading=&quot;lazy&quot; title=&quot;Deploying cloud run jobs using gcloud command - Build phase&quot; alt=&quot;Deploying cloud run jobs using gcloud command - Build phase&quot; /&gt;
&lt;p&gt;It will take some minutes for the code to be copied to a bucket and then built with build packs on Google Cloud Build. If you want to follow the build process, you can open the visible URL on a new browser tab, ti will look something like this:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/09gcb-logs.jpg&quot; loading=&quot;lazy&quot; title=&quot;Deploying cloud run jobs using gcloud command - Google Cloud Build logs&quot; alt=&quot;Deploying cloud run jobs using gcloud command - Google Cloud Build logs&quot; /&gt;
&lt;p&gt;When it is successful, it will show you something like the following:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/10cloud-run-jobs-deployed.jpg&quot; loading=&quot;lazy&quot; title=&quot;Deployed cloud run jobs using gcloud command&quot; alt=&quot;Deployed cloud run jobs using gcloud command&quot; /&gt;
&lt;p&gt;At this point, search for &lt;code&gt;Cloud Run&lt;/code&gt; and click the first result:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/11search-cloud-run.jpg&quot; loading=&quot;lazy&quot; title=&quot;Search cloud run on Google Cloud Console search bar&quot; alt=&quot;Search cloud run on Google Cloud Console search bar&quot; /&gt;
&lt;p&gt;After that, click the &lt;code&gt;Jobs&lt;/code&gt; tab, and you will see your Cloud Run job has been created:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/12cloud-run-jobs-page.jpg&quot; loading=&quot;lazy&quot; title=&quot;Cloud Run Jobs tab with recently created job&quot; alt=&quot;Cloud Run Jobs tab with recently created job&quot; /&gt;
&lt;p&gt;But this job has never run, to run the job on demand, execute &lt;code&gt;gcloud run jobs execute job-quickstart --region=us-central1&lt;/code&gt; on the Google Cloud Console as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/13cloud-run-jobs-pending.jpg&quot; loading=&quot;lazy&quot; title=&quot;Cloud Run Jobs pending after running from Cloud Shell&quot; alt=&quot;Cloud Run Jobs pending after running from Cloud Shell&quot; /&gt;
&lt;p&gt;You will see the job run. If you click &lt;code&gt;Running&lt;/code&gt; and wait for the task to execute, you will see that all five tasks in the job have run successfully:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/14cloud-run-jobs-running.jpg&quot; loading=&quot;lazy&quot; title=&quot;Cloud Run Jobs running after being triggered from Cloud Shell&quot; alt=&quot;Cloud Run Jobs pending running after being triggered from Cloud Shell&quot; /&gt;
&lt;p&gt;You can also view logs of each task if you want:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/15cloud-run-jobs-ran.jpg&quot; loading=&quot;lazy&quot; title=&quot;Cloud Run Jobs ran successfully after being triggered from Cloud Shell&quot; alt=&quot;Cloud Run Jobs an successfully after being triggered from Cloud Shell&quot; /&gt;
&lt;h3 id=&quot;create-a-job-schedule-with-google-cloud-scheduler&quot; tabindex=&quot;-1&quot;&gt;Create a job schedule with Google Cloud Scheduler &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/04/cloud-run-jobs/#create-a-job-schedule-with-google-cloud-scheduler&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To run jobs on a schedule, please follow the &lt;a href=&quot;https://cloud.google.com/run/docs/execute/jobs-on-schedule#command-line&quot;&gt;guide&lt;/a&gt;, which outlines the process of scheduling jobs using Google Cloud Scheduler.&lt;/p&gt;
&lt;p&gt;It can be done by running the following command on Google Cloud Shell to run the job every 15 minutes:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;gcloud scheduler &lt;span class=&quot;token function&quot;&gt;jobs&lt;/span&gt; create http quickstart-schedule &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token parameter variable&quot;&gt;--location&lt;/span&gt; us-central1 &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token parameter variable&quot;&gt;--schedule&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;*/15 * * * *&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token parameter variable&quot;&gt;--uri&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://us-central1-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/cloud-run-jobs-458310/jobs/job-quickstart:run&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt;  --http-method POST &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;&lt;br /&gt;  --oauth-service-account-email &lt;span class=&quot;token number&quot;&gt;944865726665&lt;/span&gt;-compute@developer.gserviceaccount.com&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can find the project number on the project dashboard page, you will need to modify the command to your project id and number. It looks like the below when run:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/16cloud-scheduler-command.jpg&quot; loading=&quot;lazy&quot; title=&quot;Cloud schdeuler command to create new schedule&quot; alt=&quot;Cloud schdeuler command to create new schedule&quot; /&gt;
&lt;p&gt;If you go to your &lt;a href=&quot;https://console.cloud.google.com/cloudscheduler&quot;&gt;cloud scheduler&lt;/a&gt; page for the project, you will find the schedule you just created:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/17cloud-scheduler-page.jpg&quot; loading=&quot;lazy&quot; title=&quot;Cloud schdeuler page showing newly created schedule&quot; alt=&quot;Cloud schdeuler page showing newly created schedule&quot; /&gt;
&lt;p&gt;You can do a &lt;code&gt;Force Run&lt;/code&gt; selecting the option from the &lt;code&gt;...&lt;/code&gt; on the right side of the schedule. I tried it and it worked for me. I waited for a few minutes so that it would be triggered again on time.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/cloud-run-jobs/18cloud-run-job-on-schedule.jpg&quot; loading=&quot;lazy&quot; title=&quot;Cloud run job triggered successfully by the scheduler&quot; alt=&quot;Cloud run job triggered successfully by the scheduler&quot; /&gt;
&lt;p&gt;That&#39;s it; it is best to delete the schedule and the job if you&#39;re testing it out.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/04/cloud-run-jobs/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this post, you learned about Google Cloud Run Jobs and their usage. You also learned how to create and run Cloud Run jobs on a schedule with Google Cloud Schedule with a simple Node.js Example. I hope you can utilize Cloud Run Jobs to execute tasks efficiently. Keep learning!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to deploy a container image to Amazon Elastic Container Service (ECS) with Fargate: a beginner’s tutorial [Part 2]</title>
		<link href="https://geshan.com.np/blog/2025/03/amazon-ecs-tutorial/"/>
		<updated>2025-03-26T11:48:57Z</updated>
		<id>https://geshan.com.np/blog/2025/03/amazon-ecs-tutorial/</id>
		<content type="html">&lt;p&gt;Amazon Elastic Container Service (ECS) is a fully managed container orchestration service that simplifies the deployment, management, and scaling of containerized applications on AWS. It manages containers without the need to learn Kubernetes. With Fargate, resource management can also be serverless. In this post, you will learn how to deploy a built container image from Amazon Elastic Container Registry (ECR) to Amazon Elastic Container Service (ECS) provisioned with Fargate. The goal is to do the bare minimum to get a URL/IP from a container image on ECR (image built and pushed in &lt;a href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecr-push-image/&quot;&gt;part 1&lt;/a&gt; of this series), let’s get going!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/01amazon-ecs-tutorial.jpg&quot; title=&quot;Deploy a Docker image from ECR to ECS with resources managed by AWS Fargate&quot; alt=&quot;Deploy a Docker image from ECR to ECS with resources managed by AWS Fargate&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecs-tutorial/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecs-tutorial/#what-is-amazon-elastic-container-service-ecs&quot;&gt;What is Amazon Elastic Container Service (ECS)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecs-tutorial/#create-an-elastic-container-service-cluster&quot;&gt;Create an Elastic Container Service cluster&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecs-tutorial/#create-a-task-definition-for-ecs&quot;&gt;Create a task definition for ECS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecs-tutorial/#create-an-esc-service&quot;&gt;Create an ECS Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecs-tutorial/#important-note&quot;&gt;Important note&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecs-tutorial/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-is-amazon-elastic-container-service-(ecs)&quot; tabindex=&quot;-1&quot;&gt;What is Amazon Elastic Container Service (ECS) &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecs-tutorial/#what-is-amazon-elastic-container-service-(ecs)&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://aws.amazon.com/ecs/&quot;&gt;Amazon ECS&lt;/a&gt; is a fully managed container orchestration service that helps you to more efficiently deploy, manage, and scale containerized applications. You can provision the underlying resource with Fargate or Elastic Compute 2 (EC2) instances. With &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html&quot;&gt;Fargate&lt;/a&gt;, you can use Amazon ECS to run containers without having to manage servers or clusters of Amazon EC2 instances.&lt;/p&gt;
&lt;p&gt;Below is a diagram of how Amazon ECS with Fargate fits in the pipeline with AWS CodePipeline, ECR, and other services including Docker in the mix:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/02aws-cp-ecr-ecs.jpg&quot; loading=&quot;lazy&quot; title=&quot;How Amazon ECS with Fargate fits in the pipeline with AWS CodePipeline, ECR and other services&quot; alt=&quot;How Amazon ECS with Fargate fits in the pipeline with AWS CodePipeline, ECR and other services&quot; /&gt;
&lt;p&gt;You can also use the AWS CLI to create the cluster, service, and task definition. For this tutorial, however, you will use the AWS console UI to keep things simple.&lt;/p&gt;
&lt;h2 id=&quot;create-an-elastic-container-service-cluster&quot; tabindex=&quot;-1&quot;&gt;Create an Elastic Container Service cluster &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecs-tutorial/#create-an-elastic-container-service-cluster&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, you must create an Amazon Elastic Container Service (ECS) cluster to deploy your Docker Image. For this, after logging in to your AWS console with a user having the correct IAM permissions, search for &lt;code&gt;ecs&lt;/code&gt; on the search bar and click on the &lt;code&gt;Clusters&lt;/code&gt; link under &lt;code&gt;Top Features&lt;/code&gt; as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/03search-for-ecs.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing search for ecs to go to Elastic Container Service - Clusters&quot; alt=&quot;AWS console showing search for ecs to go to Elastic Container Service - Clusters&quot; /&gt;
&lt;p&gt;After the clusters listing page loads, click on the &lt;code&gt;Create Cluster&lt;/code&gt; orange button on the top right of the page:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/04ecs-create-cluster.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS Clusters empty page with Create Cluster button&quot; alt=&quot;AWS console showing ECS Clusters empty page with Create Cluster button&quot; /&gt;
&lt;p&gt;Then, in the form that loads, type in the cluster&#39;s name. I am using &lt;code&gt;dev-cluster&lt;/code&gt; as an example. In the &lt;code&gt;Infrastructure&lt;/code&gt; section, make sure &lt;code&gt;AWS Fargate (serverless)&lt;/code&gt; is checked, as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/05ecs-create-cluster-form.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS create cluster form with name and infrastructure section&quot; alt=&quot;AWS console showing ECS create cluster form with name and infrastructure section&quot; /&gt;
&lt;p&gt;Don’t change any of the other optional settings and scroll to the bottom of the form, where you will see the &lt;code&gt;Create&lt;/code&gt; button, click that:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/06ecs-create-cluster-button.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS create cluster form&#39;s end section with Create button&quot; alt=&quot;AWS console showing ECS create cluster form&#39;s end section with Create button&quot; /&gt;
&lt;p&gt;It might take a couple of minutes for the cluster to be created, and it will show up on the Clusters listing page as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/07ecs-cluster-created.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS cluster created called dev-cluster&quot; alt=&quot;AWS console showing ECS cluster created called dev-cluster&quot; /&gt;
&lt;p&gt;Hurray! Your ECS Cluster with Fargate has been created. In the next section, you will create a task definition.&lt;/p&gt;
&lt;h2 id=&quot;create-a-task-definition-for-ecs&quot; tabindex=&quot;-1&quot;&gt;Create a task definition for ECS &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecs-tutorial/#create-a-task-definition-for-ecs&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A task is your application&#39;s &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html&quot;&gt;blueprint&lt;/a&gt;. It can be created from a JSON file or the AWS Web UI. There are many parameters for a task, but you will only focus on the important ones for the tutorial&#39;s scope.&lt;/p&gt;
&lt;p&gt;To create a task definition, click on &lt;code&gt;Task definitions&lt;/code&gt; as seen in the previous screenshot, it will take you to the &lt;code&gt;Task definitions&lt;/code&gt; listing page. Here, click on the &lt;code&gt;Create new task definition&lt;/code&gt; orange button and select &lt;code&gt;Create new task definition&lt;/code&gt; as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/08ecs-create-task-link.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS Create new task definition link on the Task defintions page&quot; alt=&quot;AWS console showing ECS Create new task definition link on the Task defintions page&quot; /&gt;
&lt;p&gt;On the task definition form, put in the &lt;code&gt;Task definition family&lt;/code&gt; as &lt;code&gt;nodejs-apps&lt;/code&gt; and make sure you have &lt;code&gt;AWS Fargate&lt;/code&gt; selected in the Launch type of &lt;code&gt;Infrastructure requirements&lt;/code&gt; :&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/09ecs-task-form.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS Create new task definition form with task definition family and infrastructure options&quot; alt=&quot;AWS console showing ECS Create new task definition form with task definition family and infrastructure options&quot; /&gt;
&lt;p&gt;In the task size section, select CPU as &lt;code&gt;.5 vCPU&lt;/code&gt; and Memory as &lt;code&gt;1 GB&lt;/code&gt;. As we are running a simple Hello World Node.js application, these resources would be more than enough.  Then, select the &lt;code&gt;Task role&lt;/code&gt; and &lt;code&gt;Task execution role&lt;/code&gt; as &lt;code&gt;ecsTaskExecutionRole&lt;/code&gt;.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/10ecs-task-size-role.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS Create new task definition form with task resources and roles&quot; alt=&quot;AWS console showing ECS Create new task definition form with task resources and roles&quot; /&gt;
&lt;p&gt;Now scroll down to the &lt;code&gt;Container-1&lt;/code&gt; section and name the app as &lt;code&gt;hello-world&lt;/code&gt;, for the Image URL part, copy the image URI you pushed in &lt;a href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecr-push-image/&quot;&gt;part 1&lt;/a&gt; of this series from the container registry page as shown below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/11ecr-copy-image-uri.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECR image page to copy the image URI for the built and pushed image&quot; alt=&quot;AWS console showing ECR image page to copy the image URI for the built and pushed image&quot; /&gt;
&lt;p&gt;Then paste the URI in the &lt;code&gt;Image URI&lt;/code&gt; field, as it is a single container task; this container will be &lt;code&gt;Essential Container&lt;/code&gt; - Yes. In the port mapping section, expose port 3000 in the &lt;code&gt;Container port&lt;/code&gt; field with the &lt;code&gt;Protocol&lt;/code&gt; being TCP, name the port &lt;code&gt;nodejs-3000&lt;/code&gt;, and keep &lt;code&gt;App Protocol&lt;/code&gt; as HTTP as selected. It will look like the following:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/12ecs-task-container.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS Create new task definition form with task container settings like name, Image URI, port, protocol, etc&quot; alt=&quot;AWS console showing ECS Create new task definition form with task container settings like name, Image URI, port, protocol, etc&quot; /&gt;
&lt;p&gt;Scroll down to the &lt;code&gt;Environment variables&lt;/code&gt; and add an environment variable called &lt;code&gt;PORT&lt;/code&gt; with the value &lt;code&gt;3000&lt;/code&gt;:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/13ecs-task-container-port-env.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS Create new task definition form with task container settings adding PORT environment variable&quot; alt=&quot;AWS console showing ECS Create new task definition form with task container settings adding PORT environment variable&quot; /&gt;
&lt;p&gt;After that, scroll to the bottom of the form and click the &lt;code&gt;Create&lt;/code&gt; button:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/14ecs-task-create.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS Create new task definition form submisstion with Create button&quot; alt=&quot;AWS console showing ECS Create new task definition form submisstion with Create button&quot; /&gt;
&lt;p&gt;You will see the service definition has been created:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/15ecs-task-created.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS task created&quot; alt=&quot;AWS console showing ECS task created&quot; /&gt;
&lt;p&gt;Until now, you have only created a service definition, not a service, so no containers are running. In the next section, you will create a service with a task that will bring up the container.&lt;/p&gt;
&lt;h2 id=&quot;create-an-esc-service&quot; tabindex=&quot;-1&quot;&gt;Create an ESC Service &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecs-tutorial/#create-an-esc-service&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To create a service, click &lt;code&gt;Clusters&lt;/code&gt; on the previous screenshot and then click on the cluster name, which should be &lt;code&gt;dev-cluster&lt;/code&gt;. In the cluster detail page, on the &lt;code&gt;Services&lt;/code&gt; tab, click the &lt;code&gt;Create&lt;/code&gt; button on the bottom right of the page to create a service:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/16ecs-service-create-link.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS service create link in the Cluster page, Services tab&quot; alt=&quot;AWS console showing ECS service create link in the Cluster page, Services tab&quot; /&gt;
&lt;p&gt;On the create service form, select the &lt;code&gt;Compute options&lt;/code&gt; as &lt;code&gt;Launch type&lt;/code&gt; with &lt;code&gt;FARGATE&lt;/code&gt; as &lt;code&gt;Launch type&lt;/code&gt; and the &lt;code&gt;Platform version&lt;/code&gt; as &lt;code&gt;LATEST&lt;/code&gt;:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/17ecs-service-create-form.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS service create form with compute configuration&quot; alt=&quot;AWS console showing ECS service create form with compute configuration&quot; /&gt;
&lt;p&gt;In the &lt;code&gt;Deployment Configuration&lt;/code&gt; section, &lt;code&gt;Application type&lt;/code&gt; would be pre-selected as &lt;code&gt;Service&lt;/code&gt;, in the &lt;code&gt;Family&lt;/code&gt; field, select in &lt;code&gt;nodejs-apps&lt;/code&gt; and select the &lt;code&gt;Revision&lt;/code&gt; to be &lt;code&gt;LATEST&lt;/code&gt;. Then name the service &lt;code&gt;hello-world-service&lt;/code&gt;, then leave the other settings as-is like &lt;code&gt;Replica&lt;/code&gt; has &lt;code&gt;Desired tasks&lt;/code&gt; of  1:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/18ecs-service-deployment-config.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS service create form with deployment configuration&quot; alt=&quot;AWS console showing ECS service create form with deployment configuration&quot; /&gt;
&lt;p&gt;Then scroll down to the &lt;code&gt;Networking&lt;/code&gt; section, this is the important part. Expand it, make sure the VPC is selected as is. In the &lt;code&gt;Subnets&lt;/code&gt; section click &lt;code&gt;Clear current selection&lt;/code&gt; and from the drop-down, choose only one subnet that has &lt;code&gt;us-east-1a&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;Security group&lt;/code&gt; section, choose &lt;code&gt;Create new security group&lt;/code&gt;. In the &lt;code&gt;Security group name&lt;/code&gt; field, type in &lt;code&gt;port-3000-open-from-anywhere&lt;/code&gt;. Similarly, type in &lt;code&gt;Open port 3000 from anywhere&lt;/code&gt; in the &lt;code&gt;Security group description&lt;/code&gt; field.&lt;/p&gt;
&lt;p&gt;After that, in the &lt;code&gt;Inbound rule for security groups&lt;/code&gt; part, choose Customized TCP as &lt;code&gt;Type&lt;/code&gt;; in the Port Range field, type in &lt;code&gt;3000,&lt;/code&gt; and select&#39; Anywhere&#39; for the source field. Also, make sure that the &lt;code&gt;Public IP&lt;/code&gt; is &lt;code&gt;Turned On&lt;/code&gt;:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/19ecs-service-networking.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS service create form with networking and security group configuration&quot; alt=&quot;AWS console showing ECS service create form with networking and security group configuration&quot; /&gt;
&lt;p&gt;After that, scroll to the bottom of the form and click &lt;code&gt;Create&lt;/code&gt; to create the service.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/20ecs-service-create-button.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS service create form with the Create button at the end&quot; alt=&quot;AWS console showing ECS service create form with the Create button at the end&quot; /&gt;
&lt;p&gt;It will take some time for the service to come up, you can click on the Service name &lt;code&gt;hello-world-service&lt;/code&gt;:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/21ecs-service-creating.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS service created and service showing up in the Services tab&quot; alt=&quot;AWS console showing ECS service created and service showing up in the Services tab&quot; /&gt;
&lt;p&gt;Then, on the &lt;code&gt;Tasks&lt;/code&gt; tab on the service page, click on the task ID:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/22ecs-service-running.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS service running and Tasks tab selected&quot; alt=&quot;AWS console showing ECS service running and Tasks tab selected&quot; /&gt;
&lt;p&gt;On the task page, click on the &lt;code&gt;Networking&lt;/code&gt; Tab and click the &lt;code&gt;open address&lt;/code&gt; beside the &lt;code&gt;Public IP&lt;/code&gt; as shown below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/23ecs-service-task-networking.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS console showing ECS service task and the networking tab with the Public IP&quot; alt=&quot;AWS console showing ECS service task and the networking tab with the Public IP&quot; /&gt;
&lt;p&gt;When the IP opens in a new tab browser (if it is Chrome, allow the tab to load it insecurely without HTTPs), then append &lt;code&gt;:3000&lt;/code&gt; to the IP as the Hello World Node.js app is set to run on 3000 with the &lt;code&gt;PORT&lt;/code&gt; environment variable, you should see the app run by printing &lt;code&gt;Hello World!&lt;/code&gt; on the browser:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecs-tutorial/24ecs-service-running-on-browser.jpg&quot; loading=&quot;lazy&quot; title=&quot;ESC Service and task accessible using the IP on a browser tab&quot; alt=&quot;ESC Service and task accessible using the IP on a browser tab&quot; /&gt;
&lt;p&gt;Congratulations, your Node.js Hello World container is now running on ECS with Fargate. You should read about the difference between an ESC &lt;a href=&quot;https://davidlhw.dev/notes/aws-ecs-diff-bwt-task-and-service/&quot;&gt;Task and a service&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;important-note&quot; tabindex=&quot;-1&quot;&gt;Important note &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecs-tutorial/#important-note&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is a simple example: in a real-life, production-ready application, you would have added a Load Balancer and some DNS records. You would also configure the Security groups, Subnets, VPCs, and IAM settings much more precisely.&lt;/p&gt;
&lt;p&gt;You would have written some form of CI/CD pipeline to deploy the new changes automatically. You would have also added some monitoring and logging to the application.&lt;/p&gt;
&lt;p&gt;Delete the cluster, service definition, and container registry if you don’t need them anymore.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecs-tutorial/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As a recap, you learned about Amazon Elastic Container Service (ECS) and how to provision it with Fargate to have serverless resources. Then, this tutorial taught you how to create an ECS task definition. After that, you deployed a service with the correct parameters to expose the service via a public IP without using a Load Balancer. Keep updating your AWS knowledge!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to create an Amazon Elastic Container Registry (ECR) and push a docker image to it [Part 1]</title>
		<link href="https://geshan.com.np/blog/2025/03/amazon-ecr-push-image/"/>
		<updated>2025-03-25T11:41:57Z</updated>
		<id>https://geshan.com.np/blog/2025/03/amazon-ecr-push-image/</id>
		<content type="html">&lt;p&gt;Amazon Elastic Container Registry (ECR) is a fully managed container registry that can store (Docker) container images, making it easy to pull, share, and deploy container images. This post will teach you how to create a private Amazon ECR and push Docker container images of a simple Node.js Hello World app with Express. Let’s get started!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecr-push-image/01amazon-ecr-push-image.jpg&quot; title=&quot;Push a Docker image to Amazon Elastic Container Registery (ECR)&quot; alt=&quot;Push a Docker image to Amazon Elastic Container Registery (ECR)&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecr-push-image/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecr-push-image/#what-is-amazon-ecr&quot;&gt;What is Amazon ECR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecr-push-image/#the-node.js-hello-world-app&quot;&gt;The Node.js Hello World app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecr-push-image/#create-private-amazon-ecr&quot;&gt;Create private Amazon ECR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecr-push-image/#build-and-push-node.js-docker-image&quot;&gt;Build and push Node.js Docker image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecr-push-image/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-is-amazon-ecr&quot; tabindex=&quot;-1&quot;&gt;What is Amazon ECR &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecr-push-image/#what-is-amazon-ecr&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Amazon Elastic Container Registry (ECR) is an Amazon Web Service (AWS) service that stores and manages Docker images, making it easy to pull and deploy them to services like Elastic Container Service (ECS), Elastic Kubernetes Service (EKS), and/or AWS Lambda functions. Below is a quick overview of how it works from the &lt;a href=&quot;https://aws.amazon.com/ecr/&quot;&gt;official website&lt;/a&gt;.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecr-push-image/02amazon-ecr-works.jpg&quot; loading=&quot;lazy&quot; title=&quot;How Amazon ECR fits in the pipeline&quot; alt=&quot;How Amazon ECR fits in the pipeline&quot; /&gt;
&lt;p&gt;Amazon ECR also has &lt;a href=&quot;https://docs.aws.amazon.com/cli/latest/reference/ecr/&quot;&gt;commands&lt;/a&gt; in the AWS CLI to do everything you can from the user interface. For this post, you will use the user interface to build and push a Docker image for a simple &lt;a href=&quot;https://geshan.com.np/blog/2021/05/nodejs-express-tutorial/&quot;&gt;Node.js Express&lt;/a&gt; Hello World app.&lt;/p&gt;
&lt;h2 id=&quot;the-node.js-hello-world-app&quot; tabindex=&quot;-1&quot;&gt;The Node.js Hello World app &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecr-push-image/#the-node.js-hello-world-app&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It is assumed that you have Node.js 20+ installed on your local machine. If not, you can clone &lt;a href=&quot;https://github.com/geshan/nodejs-aws-ecs-fargate&quot;&gt;this&lt;/a&gt; repository in your &lt;a href=&quot;https://docs.aws.amazon.com/cloudshell/latest/userguide/welcome.html&quot;&gt;AWS CloudShell&lt;/a&gt;. AWS CloudShell has Node 20 installed by default.&lt;/p&gt;
&lt;p&gt;The Node.js Hello World app used for this tutorial is an Express 5.x app. You can start a Node.js app with &lt;code&gt;npm init&lt;/code&gt;, and to install Express 5.x, you can run &lt;code&gt;npm install express@next&lt;/code&gt;. Then, in the folder that has the &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;package-lock.json&lt;/code&gt;, you can create an &lt;code&gt;index.js&lt;/code&gt; file with the following code:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; express &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;express&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; port &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PORT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Hello World!&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Example app listening on port &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;port&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is a simple Node.js app with only one route &lt;code&gt;/&lt;/code&gt; that prints &lt;code&gt;Hello World&lt;/code&gt; using Express.  If you run &lt;code&gt;node index.js&lt;/code&gt; , you will see the following:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; index.js&lt;br /&gt;Example app listening on port &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After that, if you hit &lt;code&gt;http://localhost&lt;/code&gt; on your favorite browser, you will see the text &lt;code&gt;Hello World&lt;/code&gt; on the browser tab.&lt;/p&gt;
&lt;p&gt;The next important file in the repository is the &lt;code&gt;Dockerfile&lt;/code&gt; with the following content:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;#buld stage&lt;/span&gt;&lt;br /&gt;FROM public.ecr.aws/docker/library/node:22 AS build&lt;br /&gt;&lt;br /&gt;WORKDIR /srv&lt;br /&gt;COPY package*.json ./&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Install dependencies based on the `package.json` and `package-lock.json`&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# files in the host folder&lt;/span&gt;&lt;br /&gt;RUN &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; ci &lt;span class=&quot;token parameter variable&quot;&gt;--omit&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;dev&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Production stage, only includes what is needed for production&lt;/span&gt;&lt;br /&gt;FROM public.ecr.aws/docker/library/node:22-alpine&lt;br /&gt;&lt;br /&gt;ENV &lt;span class=&quot;token assign-left variable&quot;&gt;NODE_ENV&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;production&lt;br /&gt;&lt;span class=&quot;token environment constant&quot;&gt;USER&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;COPY &lt;span class=&quot;token parameter variable&quot;&gt;--from&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;build /srv &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;&lt;br /&gt;ADD &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Specify the command to run when launching the container&lt;/span&gt;&lt;br /&gt;EXPOSE &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;br /&gt;CMD &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;node&quot;&lt;/span&gt;, &lt;span class=&quot;token string&quot;&gt;&quot;index.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is a Dockerfile using  &lt;a href=&quot;https://geshan.com.np/blog/2019/11/how-to-use-docker-multi-stage-build/&quot;&gt;Docker multi-stage build&lt;/a&gt; to create the build and the production stage.&lt;/p&gt;
&lt;p&gt;The easiest way to get started is to clone this repository in your AWS Cloud Shell and build the image there. Before that, you will first create the private Amazon ECR.&lt;/p&gt;
&lt;h2 id=&quot;create-private-amazon-ecr&quot; tabindex=&quot;-1&quot;&gt;Create private Amazon ECR &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecr-push-image/#create-private-amazon-ecr&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Amazon Elastic Container Registry (ECR) can be public or private. For example, this &lt;a href=&quot;https://gallery.ecr.aws/docker/library/node&quot;&gt;Node.js docker image&lt;/a&gt; is being served from the public ECR. No authentication is required to pull the node image. Conversely, the apps you develop will to be accessible to the public, so they are in a private ECR, which has some form of access control to ensure only the right users have access to it.&lt;/p&gt;
&lt;p&gt;To create a private Amazon Elastic Container Registry (ECR), you must be logged into your AWS account and have the correct IAM permissions. This post does not cover the IAM permissions. In your AWS console, search for &lt;code&gt;ecr&lt;/code&gt; as shown below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecr-push-image/03search-for-ecr.jpg&quot; loading=&quot;lazy&quot; title=&quot;Search for ecr on Amazon web console&quot; alt=&quot;Search for ecr on Amazon web console&quot; /&gt;
&lt;p&gt;Then click on &lt;code&gt;Elastic Container Registry&lt;/code&gt; which will take you to the following page:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecr-push-image/04create-amazon-ecr-button.jpg&quot; loading=&quot;lazy&quot; title=&quot;UI button to create Amazon ECR (private)&quot; alt=&quot;UI button to create Amazon ECR (private)&quot; /&gt;
&lt;p&gt;On this page, click on the &lt;code&gt;Create&lt;/code&gt; yellow button, which will take you to the form below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecr-push-image/05private-ecr-app-name.jpg&quot; loading=&quot;lazy&quot; title=&quot;UI button to create Amazon ECR (private)&quot; alt=&quot;UI button to create Amazon ECR (private)&quot; /&gt;
&lt;p&gt;On the form, fill in the repository name as &lt;code&gt;nodejs/hello-world&lt;/code&gt;, where &lt;code&gt;nodejs&lt;/code&gt; is the namespace and &lt;code&gt;hello-world&lt;/code&gt; is the app name.&lt;/p&gt;
&lt;p&gt;It is better to keep the tags immutable so they are not overwritten. To do this, click the &lt;code&gt;Immutable&lt;/code&gt; radio button in the &lt;code&gt;Image tag mutability&lt;/code&gt; section. After that, keep the Encryption settings as is and click the &lt;code&gt;Create&lt;/code&gt; button at the bottom of this page.&lt;/p&gt;
&lt;p&gt;It might take some seconds for the EC registry to be created, and you will be taken to the &lt;code&gt;Private repositories&lt;/code&gt; listing page as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecr-push-image/06private-ecr-created.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS Console UI showing the private Amazon ECR created&quot; alt=&quot;AWS Console UI showing the private Amazon ECR created&quot; /&gt;
&lt;p&gt;In the next part, you will learn how to build and push a Docker container image using AWS Cloudshell. You are using AWS Cloudshell, so there is nothing to install on your machine. You can also do the same using your machine.&lt;/p&gt;
&lt;h2 id=&quot;build-and-push-node.js-docker-image&quot; tabindex=&quot;-1&quot;&gt;Build and push Node.js Docker image &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecr-push-image/#build-and-push-node.js-docker-image&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To build and push the Node.js Hello World (with Express.js) Docker image, you must first go to the repository by clicking its name, as seen in the previous screenshot.&lt;/p&gt;
&lt;p&gt;You will land on the &lt;code&gt;Images&lt;/code&gt; page of the repository, which will look like the below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecr-push-image/07ecr-without-images.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS Console UI showing just created private Amazon ECR without any Docker images&quot; alt=&quot;AWS Console UI showing just created private Amazon ECR without any Docker images&quot; /&gt;
&lt;p&gt;Before doing anything else, please click the &lt;code&gt;CloudShell&lt;/code&gt; link at the bottom left side of the page. It will provision and run a shell for you:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecr-push-image/08aws-cloudshell.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS Console UI showing AWS CloudShell without any command&quot; alt=&quot;AWS Console UI showing AWS CloudShell without any command&quot; /&gt;
&lt;p&gt;Type in the following command in the shell:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; projects &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; projects &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone https://github.com/geshan/nodejs-aws-ecs-fargate.git &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; nodejs-aws-ecs-fargate&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above command creates a folder called &lt;code&gt;projects&lt;/code&gt; and then goes into it. After that, it clones the above Node.js (Express) Hello World App, which also has the abovementioned Dockerfile. Subsequently, the last command takes you into the &lt;code&gt;nodejs-aws-ecs-fargate&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;It will result in the following state:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecr-push-image/09aws-cloudshell-with-commands.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS Console UI showing AWS CloudShell with create project related commands&quot; alt=&quot;AWS Console UI showing AWS CloudShell with create project related commands&quot; /&gt;
&lt;p&gt;After that, click on the &lt;code&gt;View push commands&lt;/code&gt; button on the left side of the page it will show a pop-up as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecr-push-image/10ecr-show-push-commands.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS Console UI showing  ECR login, docker build related commands&quot; alt=&quot;AWS Console UI showing  ECR login, docker build related commands&quot; /&gt;
&lt;p&gt;Copy all four visible commands and paste them into Notepad or your IDE.  The commands I got were:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;aws ecr get-login-password &lt;span class=&quot;token parameter variable&quot;&gt;--region&lt;/span&gt; us-east-1 &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; login &lt;span class=&quot;token parameter variable&quot;&gt;--username&lt;/span&gt; AWS --password-stdin &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;long-id-here&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;.dkr.ecr.us-east-1.amazonaws.com&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; build &lt;span class=&quot;token parameter variable&quot;&gt;-t&lt;/span&gt; nodejs/hello-world &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; tag nodejs/hello-world:latest &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;long-id-here&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;.dkr.ecr.us-east-1.amazonaws.com/nodejs/hello-world:latest&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; push &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;long-id-here&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;.dkr.ecr.us-east-1.amazonaws.com/nodejs/hello-world:latest&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, run them individually on your console, maintaining the order. After the first command, you will see &lt;code&gt;Login Succeeded&lt;/code&gt;. That command is used to log in to the Elastic container registry.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecr-push-image/11aws-cloudshell-erc-login.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS Console UI showing AWS CloudShell with ECR login command output&quot; alt=&quot;AWS Console UI showing AWS CloudShell with ECR login command output&quot; /&gt;
&lt;p&gt;The &lt;code&gt;docker build&lt;/code&gt; command will take up to 5 minutes, wait for it.  After the build is done, it will look something like the below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecr-push-image/12aws-cloudshell-docker-build.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS Console UI showing AWS CloudShell with Docker build command output&quot; alt=&quot;AWS Console UI showing AWS CloudShell with Docker build command output&quot; /&gt;
&lt;p&gt;The third command tags the built container with &lt;code&gt;nodejs/hello-world:latest &lt;/code&gt;, which results in nothing. The fourth command pushes the image to the private Amazon ECR. If everything goes well, when it finishes, it will look like the following:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecr-push-image/13aws-cloudshell-docker-tag-push-image.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS Console UI showing AWS CloudShell with Docker tag and push command output&quot; alt=&quot;AWS Console UI showing AWS CloudShell with Docker tag and push command output&quot; /&gt;
&lt;p&gt;After that, close the cloud shell and refresh the &lt;code&gt;Images&lt;/code&gt; page of the private Amazon ECR. You will see the pushed Docker image in the registry as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecr-push-image/14amazon-ecr-with-pushed-image.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS Console UI showing Amazon ECR with the pushed Docker image of a Node.js Express Hello World App&quot; alt=&quot;AWS Console UI showing Amazon ECR with the pushed Docker image of a Node.js Express Hello World App&quot; /&gt;
&lt;p&gt;You can see the image’s details by clicking the &lt;code&gt;latest&lt;/code&gt; link, which will show you:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/amazon-ecr-push-image/14amazon-ecr-with-pushed-image.jpg&quot; loading=&quot;lazy&quot; title=&quot;AWS Console UI showing Amazon ECR with the pushed Docker image details&quot; alt=&quot;AWS Console UI showing Amazon ECR with the pushed Docker image details&quot; /&gt;
&lt;p&gt;You can deploy the image&#39;s URL as a container in ECS, EKS, or even a Lambda function. The &lt;a href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecs-tutorial/&quot;&gt;next part&lt;/a&gt; of this blog post series you will deploy the built and pushed container to Amazon Elastic Container Service (ECS).&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/03/amazon-ecr-push-image/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this post, you learned about Amazon Elastic Container Registry (ECR), a service in Amazon Web Services (AWS). Then, you built a simple Hello World Node.js app with Express 5.x. After that, using the AWS interface, you created a private AWS ECR Docker image registry. Consequently, look at the command provided. You used AWS CodeShell to build and push the Hello World Node.js app image after cloning the repository from GitHub.&lt;/p&gt;
&lt;p&gt;I hope you learned the basics of Amazon ECR, in the next part, you will deploy the container on Amazon Elastic Container Service (ECS) using Fargate for serverless resource provisioning. Keep learing!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to use Ollama and Open WebUI with Docker Compose [Part 4]</title>
		<link href="https://geshan.com.np/blog/2025/02/ollama-docker-compose/"/>
		<updated>2025-02-11T11:43:57Z</updated>
		<id>https://geshan.com.np/blog/2025/02/ollama-docker-compose/</id>
		<content type="html">&lt;p&gt;Ollama gives you one of the easiest ways to run most open LLMs on your machine. It is open-source and easy to use. In addition to using it with a command line or its APIs, you can use it with a web user interface using &lt;a href=&quot;https://openwebui.com/&quot;&gt;Open WebUI&lt;/a&gt;. This post will teach you how to run Ollama and Open WebUI to run any open LLM with a web-based chat interface like ChatGPT. Let’s get started!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-docker-compose/01ollama-docker-compose.jpg&quot; title=&quot;How to use Ollama and Open WebUI with Docker Compose [Part 4]&quot; alt=&quot;How to use Ollama and Open WebUI with Docker Compose [Part 4]&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#recap-of-the-ollama-series&quot;&gt;Recap of the Ollama series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#prerequisites&quot;&gt;Prerequisites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#open-webui&quot;&gt;Open WebUI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#ollama-docker-compose&quot;&gt;Ollama Docker Compose&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#ollama-open-webui-docker-services&quot;&gt;Ollama Open WebUI Docker Services&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#running-ollama-and-open-webui-with-docker-compose&quot;&gt;Running Ollama and Open WebUI with Docker compose&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#the-docker-images-are-huge&quot;&gt;The docker images are huge&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#hosting-ollama-on-the-cloud&quot;&gt;Hosting Ollama on the cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;recap-of-the-ollama-series&quot; tabindex=&quot;-1&quot;&gt;Recap of the Ollama series &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#recap-of-the-ollama-series&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is part 4 of the Ollama blog series. In the &lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/&quot;&gt;first part&lt;/a&gt;, you learned &lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#what-is-ollama&quot;&gt;what an Ollama is&lt;/a&gt;, its features, and how to run it on your local machine.&lt;/p&gt;
&lt;p&gt;The second part delved into the &lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/&quot;&gt;Ollama commands&lt;/a&gt; you can execute on the CLI. Part 3 of the series shed light on some of the important &lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/&quot;&gt;Ollama APIs&lt;/a&gt; focusing on the &lt;code&gt;generate&lt;/code&gt; and &lt;code&gt;chat&lt;/code&gt; endpoints.&lt;/p&gt;
&lt;p&gt;This part involves running &lt;a href=&quot;https://hub.docker.com/r/ollama/ollama&quot;&gt;Ollama’s Docker image&lt;/a&gt; and adding a web UI, the &lt;a href=&quot;https://github.com/open-webui/open-webui&quot;&gt;Open WebUI&lt;/a&gt;, to provide a chat interface for any model Ollama can run. Like Ollama, Open WebUI is also open-source, with the code primarily in JavaScript, Python, and TypeScript. It also has a docker image pushed on the Google Container Registry, created from its &lt;a href=&quot;https://github.com/open-webui/open-webui/blob/main/Dockerfile&quot;&gt;Dockerfile&lt;/a&gt;. You will use Docker Compose to run these two images together for a working application.&lt;/p&gt;
&lt;h2 id=&quot;prerequisites&quot; tabindex=&quot;-1&quot;&gt;Prerequisites &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#prerequisites&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before you start running some Docker Compose commands, be informed of some of the software that needs to be running on your machine:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You will need Docker running on your machine, for this example, I am using Docker 27.4.0 on Mac&lt;/li&gt;
&lt;li&gt;Make sure you have Docker Compose available as well (it used to be a different install when it was &lt;code&gt;docker-compose&lt;/code&gt; when it was in v1, from &lt;a href=&quot;https://stackoverflow.com/a/66516826&quot;&gt;v2&lt;/a&gt; it is coupled with the Docker Desktop installation). I am using Docker Compose version v2.31.0-desktop.2 on a Mac)&lt;/li&gt;
&lt;li&gt;It would be good to know about Docker volumes, docker ports, and basic &lt;a href=&quot;https://geshan.com.np/blog/2022/05/docker-commands/&quot;&gt;docker commands&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can read the &lt;a href=&quot;https://geshan.com.np/blog/2024/04/docker-for-beginners/&quot;&gt;Docker for beginners&lt;/a&gt; tutorial for a refresher on Docker. Please read this &lt;a href=&quot;https://geshan.com.np/blog/2024/04/docker-compose-tutorial/&quot;&gt;docker compose tutorial&lt;/a&gt; to learn more about Docker Compose.&lt;/p&gt;
&lt;h2 id=&quot;open-webui&quot; tabindex=&quot;-1&quot;&gt;Open WebUI &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#open-webui&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Open Web UI is a user interface for interacting with large language models. It offers a streamlined and intuitive way to communicate with and manage these models, making them more accessible and user-friendly.&lt;/p&gt;
&lt;p&gt;Open Web UI aims to simplify working with large language models. It allows users to harness their power for various applications, including content creation, research, and software development.&lt;/p&gt;
&lt;h2 id=&quot;ollama-docker-compose&quot; tabindex=&quot;-1&quot;&gt;Ollama Docker Compose &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#ollama-docker-compose&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Docker images for both Ollama and Open WebUI are not small. Ollama’s latest (version 0.5.7 at the time of writing) is 4.76 GB uncompressed, and Open WebUI’s main tag is 3.77 GB uncompressed. Below is the &lt;code&gt;docker-compose.yaml&lt;/code&gt; file that has both Ollama and Open Web UI:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;services:&lt;br /&gt;  ollama:&lt;br /&gt;    image: ollama/ollama:latest&lt;br /&gt;    ports:&lt;br /&gt;      - &lt;span class=&quot;token number&quot;&gt;11434&lt;/span&gt;:11434&lt;br /&gt;    volumes:&lt;br /&gt;      - ollama:/root/.ollama&lt;br /&gt;    container_name: ollama&lt;br /&gt;    tty: &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;br /&gt;    restart: unless-stopped&lt;br /&gt;&lt;br /&gt;  open-webui:&lt;br /&gt;    image: ghcr.io/open-webui/open-webui:main&lt;br /&gt;    container_name: open-webui&lt;br /&gt;    volumes:&lt;br /&gt;      - open-webui:/app/backend/data&lt;br /&gt;    depends_on:&lt;br /&gt;      - ollama&lt;br /&gt;    ports:&lt;br /&gt;      - &lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;:8080&lt;br /&gt;    environment:&lt;br /&gt;      - &lt;span class=&quot;token string&quot;&gt;&#39;OLLAMA_BASE_URL=http://ollama:11434&#39;&lt;/span&gt;&lt;br /&gt;      - &lt;span class=&quot;token string&quot;&gt;&#39;WEBUI_SECRET_KEY=&#39;&lt;/span&gt;&lt;br /&gt;    extra_hosts:&lt;br /&gt;      - host.docker.internal:host-gateway&lt;br /&gt;    restart: unless-stopped&lt;br /&gt;&lt;br /&gt;volumes:&lt;br /&gt;  ollama: &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  open-webui: &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This file sets up your local environment to run any AI model (such as a large language model or LLM) and interact with it through a user-friendly web interface. It&#39;s like setting up a mini-cloud service on your machine.&lt;/p&gt;
&lt;p&gt;This docker-compose.yml file sets up a two-part application:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Ollama runs large language models (LLMs) locally on your computer. Think of it like the &amp;quot;engine&amp;quot; that powers the AI. It&#39;s like having your mini-ChatGPT running.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open WebUI is a user-friendly web interface that allows you to interact with Ollama. It&#39;s like a dashboard that allows you to talk to the AI engine. It provides a nice visual way to send prompts and see responses.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;ollama-open-webui-docker-services&quot; tabindex=&quot;-1&quot;&gt;Ollama Open WebUI Docker Services &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#ollama-open-webui-docker-services&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let’s look at the &lt;code&gt;services&lt;/code&gt; section of the above &lt;code&gt;docker-compose.yaml&lt;/code&gt; file:&lt;/p&gt;
&lt;p&gt;Services is the main section where you define your application&#39;s different parts (containers). Each &amp;quot;service&amp;quot; is a separate program running in its isolated environment.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ollama&lt;/code&gt;: This defines the first service, named &amp;quot;ollama&amp;quot;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;image: ollama/ollama:latest&lt;/code&gt;: This tells Docker which pre-built &amp;quot;image&amp;quot; to use. An image is like a template for a container. &lt;code&gt;ollama/ollama:lates&lt;/code&gt;t means you using the official Ollama image, and &lt;code&gt;latest&lt;/code&gt; means we want the most recent version.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ports: - 11434:11434&lt;/code&gt;: This maps port 11434 on your host machine (your computer) to port 11434 inside the Ollama container. Ollama listens for requests on port 11434. This allows other applications (like Open WebUI) to talk to Ollama.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;volumes&lt;/code&gt;: - &lt;code&gt;ollama:/root/.ollama&lt;/code&gt; creates a persistent storage area. &lt;code&gt;/root/.ollama&lt;/code&gt; is where Ollama stores its data (like downloaded models). ollama: (defined at the bottom of the file) is a named volume. This means the data will persist even if you stop and restart the container. Without this, you&#39;d lose all your downloaded models every time you stopped Ollama. It&#39;s like giving Ollama a dedicated hard drive that doesn&#39;t get erased.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;container_name&lt;/code&gt;: &lt;code&gt;ollama&lt;/code&gt;: This gives the container a specific name, &amp;quot;ollama,&amp;quot; making it easier to refer to.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;tty: true&lt;/code&gt; allocates a pseudo-TTY, which can be helpful for interactive sessions. It helps the container handle input and output, making it behave more like a regular terminal. Programs that expect to interact with a user often need this.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;restart: unless-stopped&lt;/code&gt;: This tells Docker to automatically restart the Ollama container if it crashes or stops for any reason unless you explicitly stop it yourself (e.g., using docker compose down). It&#39;s like setting an auto-restart feature.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;open-webui: This defines the second service, named &amp;quot;open-webui&amp;quot;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;image: ghcr.io/open-webui/open-webui:main&lt;/code&gt;: This uses the Open WebUI image from the GitHub Container Registry (&lt;a href=&quot;http://ghcr.io/&quot;&gt;ghcr.io&lt;/a&gt;). &lt;code&gt;main&lt;/code&gt; specifies a particular version (the main branch).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;container_name: open-webui&lt;/code&gt;: Gives the container a specific name.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;volumes&lt;/code&gt;: - &lt;code&gt;open-webui:/app/backend/data&lt;/code&gt;: Similar to Ollama, this creates persistent storage for Open WebUI&#39;s data. /app/backend/data is where Open WebUI stores its data. open-webui: is another named volume. This keeps your Open WebUI settings and data safe.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;depends_on&lt;/code&gt;: - ollama: This is crucial. It tells Docker Compose that the Open WebUI service depends on the Ollama service. Docker Compose will start Ollama before starting Open WebUI. This is essential because Open WebUI needs Ollama to run and function. It&#39;s like saying, &amp;quot;Don&#39;t start the dashboard until the engine runs”. Read more about &lt;a href=&quot;https://geshan.com.np/blog/2024/02/docker-compose-depends-on/&quot;&gt;Docker compose depends on&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ports&lt;/code&gt;: &lt;code&gt;- 3000:8080&lt;/code&gt; This maps port 3000 on your host machine to port 8080 inside the Open WebUI container. Open WebUI runs on port 8080. This means you&#39;ll access the Open WebUI interface by going to &lt;a href=&quot;http://localhost:3000/&quot;&gt;http://localhost:3000&lt;/a&gt; in your web browser.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;environment&lt;/code&gt;: This sets environment variables inside the Open WebUI container. These are configuration settings.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;OLLAMA_BASE_URL=http://ollama:11434&lt;/code&gt;: This tells Open WebUI where to find Ollama. Notice it&#39;s using the service name ollama (not localhost). Docker Compose sets up internal networking so services can communicate using their service names. This is how Open WebUI knows how to connect to the Ollama &amp;quot;engine.&amp;quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;WEBUI_SECRET_KEY=&lt;/code&gt;: This is a security setting for Open WebUI. You should set it to a strong, random value for production use. It&#39;s like a password for the web interface. Leaving it blank is fine for local testing but not for a public-facing server.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;extra_hosts&lt;/code&gt;: as &lt;code&gt;- host.docker.internal:host-gateway:&lt;/code&gt; This is a bit more advanced. It allows the container to access services running on your host machine. &lt;code&gt;host.docker.internal&lt;/code&gt; is a special hostname that resolves to your host&#39;s internal IP address. This is useful if, for example, you have another service running directly on your computer (not inside a container) that Open WebUI needs to access.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;restart: unless-stopped&lt;/code&gt;: As with Ollama, this ensures that Open WebUI restarts automatically unless you manually stop it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;volumes&lt;/code&gt;: This section defines the named volumes used above. Volumes persist data even if the containers are restarted.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ollama: {}&lt;/code&gt; defines the ollama volume. The empty {} means we&#39;re using the default Docker volume driver.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;open-webui: {}&lt;/code&gt; defines the open-webui volume using the default driver where Docker manages where and how to save it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This docker-compose file sets up a system with Ollama (likely a large language model server) and Open-WebUI (a web interface to interact with Ollama).  It ensures that Ollama starts first, that both services have persistent storage, and that Open-WebUI knows how to connect to Ollama.  You&#39;ll be able to access Open-WebUI on your computer at port 3000.  Remember to set a &lt;code&gt;WEBUI_SECRET_KEY&lt;/code&gt;!&lt;/p&gt;
&lt;h2 id=&quot;running-ollama-and-open-webui-with-docker-compose&quot; tabindex=&quot;-1&quot;&gt;Running Ollama and Open WebUI with Docker compose &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#running-ollama-and-open-webui-with-docker-compose&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To run the above Docker Compose file, please execute:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; compose up&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or you could run &lt;code&gt;docker-compose up&lt;/code&gt; depending on the version of Docker Compose installed on your machine. Running this command for the first time will take some time, depending on your internet speed, because it will download around 4 GB of data in total (2.5 GB for Ollama and 1.5 GB or a bit more for Open WebUI). So you can make your coffee now and come back with it when the download finishes:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-docker-compose/02ollama-open-webui-pull-docker-images.jpg&quot; loading=&quot;lazy&quot; title=&quot;Pulling GBs or data for Ollama and Open WebUI Docker Images&quot; alt=&quot;Pulling GBs or data for Ollama and Open WebUI Docker Images&quot; /&gt;
&lt;p&gt;After it downloads both the docker images and runs them, you will see something like the below on the CLI:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-docker-compose/03ollama-open-webui-running-with-docker-compose.jpg&quot; loading=&quot;lazy&quot; title=&quot;Ollama and Open WebUI running inside Docker with Docker Compose up&quot; alt=&quot;Ollama and Open WebUI running inside Docker with Docker Compose up&quot; /&gt;
&lt;p&gt;Now you can go to &lt;code&gt;http://localhost:3000&lt;/code&gt; on the browser of your choice (probably Google Chrome), and you will see the following welcome screen of Open WebUI:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-docker-compose/04open-webui-welcome.jpg&quot; loading=&quot;lazy&quot; title=&quot;First welcome screen of Open WebUI running inside Docker with Docker Compose&quot; alt=&quot;First welcome screen of Open WebUI running inside Docker with Docker Compose&quot; /&gt;
&lt;p&gt;Click the &lt;code&gt;Get Started&lt;/code&gt; link, and then you will need to fill out the form as shown below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-docker-compose/05open-webui-admin-registration-form.jpg&quot; loading=&quot;lazy&quot; title=&quot;Open WebUI Registration form to register the admin user&quot; alt=&quot;Open WebUI Registration form to register the admin user&quot; /&gt;
&lt;p&gt;After you fill out the form, you will reach the Open WebUI Dashboard with an announcement:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-docker-compose/06open-webui-registered.jpg&quot; loading=&quot;lazy&quot; title=&quot;Admin registered on Open WebUI and landing on the logged in page for the first time&quot; alt=&quot;Admin registered on Open WebUI and landing on the logged in page for the first time&quot; /&gt;
&lt;p&gt;Click on &lt;code&gt;Ok let’s go&lt;/code&gt; to see the Open WebUI main screen. As no models are downloaded, you will download the &lt;code&gt;smollm2:135m&lt;/code&gt; model using the UI. This can also be done from the CLI with &lt;code&gt;docker compose exec ollama ollama pull smollm2:135m&lt;/code&gt;, but you will use the UI for now.&lt;/p&gt;
&lt;p&gt;To pull/download the model onto your local Ollama instance, click the &lt;code&gt;Select a model&lt;/code&gt; drop down and type in &lt;code&gt;smollm2:135m&lt;/code&gt; then click on &lt;code&gt;Pull smollm2:135m from Ollama.com&lt;/code&gt; to download the model as shown below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-docker-compose/07open-webui-download-smollm2.jpg&quot; loading=&quot;lazy&quot; title=&quot;Download the Smollm2:135m model from the Open WebUI interface&quot; alt=&quot;Download the Smollm2:135m model from the Open WebUI interface&quot; /&gt;
&lt;p&gt;It is a relatively small model at 271 MB, so depending on your internet speed, it will finish in seconds or a couple of minutes as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-docker-compose/08open-webui-downloading-smollm2.jpg&quot; loading=&quot;lazy&quot; title=&quot;Downloading the Smollm2:135m model from the Open WebUI interface&quot; alt=&quot;Downloading the Smollm2:135m model from the Open WebUI interface&quot; /&gt;
&lt;p&gt;After the model is downloaded locally on your machine and in the Ollama instance, you can start chatting or prompting the model. You can ask questions like &lt;code&gt;who are you?&lt;/code&gt; or &lt;code&gt;why is the sky blue? give the shortest possible answer in under 20 words&lt;/code&gt; as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-docker-compose/09open-webui-smollm2-chat.jpg&quot; loading=&quot;lazy&quot; title=&quot;Chatting with Smollm2 135 million params on Open WebUI&quot; alt=&quot;Chatting with Smollm2 135 million params on Open WebUI&quot; /&gt;
&lt;p&gt;The model will reply. You can also configure the models by clicking the &lt;code&gt;settings&lt;/code&gt; icon at the top right of the screen. Parameters like temperature, top K, Top P, and others can be changed on the Open WebUI configs as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-docker-compose/10open-webui-ollama-configs.jpg&quot; loading=&quot;lazy&quot; title=&quot;You can change Ollama configs on Open WebUI interface&quot; alt=&quot;You can change Ollama configs on Open WebUI interface&quot; /&gt;
&lt;p&gt;You now have your mini chatGPT running locally. Since it is Ollama and the model has been downloaded, it can run even without the internet on a plane. Depending on the resources available, such as disk space, CPU/GPU, and memory, you can download other models, such as Llama, Microsoft Phi, Gemma 2, or DeepSeek, from Ollama’s &lt;a href=&quot;https://ollama.com/search&quot;&gt;model registry&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-docker-images-are-huge&quot; tabindex=&quot;-1&quot;&gt;The docker images are huge &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#the-docker-images-are-huge&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The uncompressed Docker image for Ollama is 4.5 GB, which will grow bigger when you download a model. Similarly, the uncompressed image for Open WebUI is 3.77 GB. Both of them are huge, as you can see below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-docker-compose/11ollama-open-webui-docker-images-size.jpg&quot; loading=&quot;lazy&quot; title=&quot;Ollama and Open Web UI have big Docker images&quot; alt=&quot;Ollama and Open Web UI have big Docker images&quot; /&gt;
&lt;p&gt;Make sure to have at least 9-10 GB of free space on your hard disk before downloading these large Docker images.&lt;/p&gt;
&lt;h2 id=&quot;hosting-ollama-on-the-cloud&quot; tabindex=&quot;-1&quot;&gt;Hosting Ollama on the cloud &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#hosting-ollama-on-the-cloud&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can follow this step-by-step tutorial to run &lt;a href=&quot;https://geshan.com.np/blog/2025/01/ollama-google-cloud-run/&quot;&gt;Ollama on Google Cloud Run&lt;/a&gt;. If you are looking for a more production-ready Ollama docker image with a model (Gemma 2:9b) already pulled, have a look at this &lt;a href=&quot;https://github.com/geshan/ollama-cloud-run/blob/master/Dockerfile&quot;&gt;Dockerfile&lt;/a&gt;. You can easily change the version of Ollama and also download another model of your choice to host it on Google Cloud Run in &lt;a href=&quot;https://geshan.com.np/blog/2023/04/serverless-containers/&quot;&gt;serverless containers&lt;/a&gt;. You can follow this &lt;a href=&quot;https://codelabs.developers.google.com/codelabs/how-to-use-ollama-sidecar-open-webui-frontend-cloud-run-gpu#0&quot;&gt;codelab&lt;/a&gt; to create a multi-container Cloud Run service with Ollama and Open WebUI together on Google Cloud Run where Open WebUI is the main pod (ingress frontend) and Ollama is a sidecar.&lt;/p&gt;
&lt;p&gt;As it is a Docker container, you can also run it on your Kubernetes cluster on GKE.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This blog post explains how to run Ollama and Open WebUI with Docker Compose. Ollama is an open-source tool for running large language models (LLMs) on your machine, and Open WebUI provides a web-based chat interface for interacting with the models.&lt;/p&gt;
&lt;p&gt;The blog post first recaps the Ollama blog series and lists the prerequisites for running Ollama and Open WebUI with Docker Compose. It then explains Open WebUI and provides the Ollama Docker Compose file. Next, it explains the Ollama Open WebUI Docker services and how to run them with Docker Compose. It also notes that the Docker images are large, and the post provides guidance for hosting Ollama on the cloud. Keep exploring!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Using Ollama APIs to generate responses and much more [Part 3]</title>
		<link href="https://geshan.com.np/blog/2025/02/ollama-api/"/>
		<updated>2025-02-09T11:47:32Z</updated>
		<id>https://geshan.com.np/blog/2025/02/ollama-api/</id>
		<content type="html">&lt;p&gt;Ollama is open-source software that makes running most open LLMs seamlessly on your own machine (or even on the cloud). Written in Go lang, Ollama is user-friendly and easy to start. In this post, part 3 of the Ollama blog posts series, you will learn about using Ollama’s APIs for generating responses (LLM inference) and much more; let’s get going!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-api/01ollama-api.jpg&quot; title=&quot;Using Ollama APIs to generate responses and much more [Part 3]&quot; alt=&quot;Using Ollama APIs to generate responses and much more [Part 3]&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#quick-review-of-the-ollama-series&quot;&gt;Quick review of the Ollama series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#curl-and-jq&quot;&gt;Curl and Jq&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#ollama-api-endpoints&quot;&gt;Ollama API Endpoints&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#generate-endpoint&quot;&gt;Generate endpoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#chat-endpoint&quot;&gt;Chat endpoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#list-models&quot;&gt;List models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#pull-a-model&quot;&gt;Pull a model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#show-model-information&quot;&gt;Show model information&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#other-ollama-apis&quot;&gt;Other Ollama APIs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#important-caveat&quot;&gt;Important caveat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;quick-review-of-the-ollama-series&quot; tabindex=&quot;-1&quot;&gt;Quick review of the Ollama series &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#quick-review-of-the-ollama-series&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This blog post is part 3 of the Ollama series. In the first part, you learned about &lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#what-is-ollama&quot;&gt;what Ollama is&lt;/a&gt;, including its &lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#ollama-features&quot;&gt;features&lt;/a&gt; and also &lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#how-to-run-ollama-locally&quot;&gt;how to run Ollama&lt;/a&gt; on your local machine with a couple of models.&lt;/p&gt;
&lt;p&gt;In part two, you explored some useful &lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/&quot;&gt;Ollama commands&lt;/a&gt;, like &lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#ollama-serve&quot;&gt;ollama serve&lt;/a&gt; to start Ollama and serve available models, &lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#ollama-run&quot;&gt;ollama run&lt;/a&gt; to pull (download) and run a model.&lt;/p&gt;
&lt;p&gt;In this part, you will learn about the Ollama APIs. In addition to the inference API endpoints &lt;code&gt;/api/generate&lt;/code&gt; and &lt;code&gt;/api/chat&lt;/code&gt;, you will also learn about other useful API endpoints. The Ollama commands call these APIs behind the scenes to provide the outputs.&lt;/p&gt;
&lt;p&gt;In the next part, part 4, you will learn how to run &lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/&quot;&gt;Ollama in Docker&lt;/a&gt; with Docker Compose. You will also add Open WebUI with Docker Compose to have a WebUI to interact with LLMs running on Ollama.&lt;/p&gt;
&lt;h2 id=&quot;curl-and-jq&quot; tabindex=&quot;-1&quot;&gt;Curl and Jq &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#curl-and-jq&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For this guide, you will use cURL to call the APIs with &lt;a href=&quot;https://jqlang.org/&quot;&gt;Jq&lt;/a&gt;. To install JQ, follow their official &lt;a href=&quot;https://jqlang.org/download/&quot;&gt;download&lt;/a&gt; guides for instance, on a Mac, you can run &lt;code&gt;brew install jq&lt;/code&gt;, similarly on an Ubuntu machine, you can execute &lt;code&gt;sudo apt-get install jq&lt;/code&gt; on a Windows machine, you can use chocolatey. Or you can get the binary and make it executable, too.&lt;/p&gt;
&lt;p&gt;You can use other programming languages, such as Python and JavaScript, with the official libraries for &lt;a href=&quot;https://github.com/ollama/ollama-python&quot;&gt;Python&lt;/a&gt; and &lt;a href=&quot;https://github.com/ollama/ollama-js&quot;&gt;JavaScript&lt;/a&gt;, and frameworks like &lt;a href=&quot;https://docs.litellm.ai/docs/providers/ollama&quot;&gt;LiteLLM&lt;/a&gt; or &lt;a href=&quot;https://python.langchain.com/docs/integrations/llms/ollama/&quot;&gt;LangChain&lt;/a&gt; to call the Ollama APIs.&lt;/p&gt;
&lt;h2 id=&quot;ollama-api-endpoints&quot; tabindex=&quot;-1&quot;&gt;Ollama API Endpoints &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#ollama-api-endpoints&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are more than 10 Ollama API endpoints. This tutorial will focus on some of the most important ones. To use the APIs, you will need Ollama to run either with &lt;code&gt;ollama serve&lt;/code&gt; or as a service. You will also need at least one model pulled for the API calls.&lt;/p&gt;
&lt;p&gt;For this guide, you will use &lt;a href=&quot;https://github.com/huggingface/smollm&quot;&gt;smollm2&lt;/a&gt;:135m, one of the smaller LLMs at 221 MB. You can use any bigger model if it runs on the available resources. The reason to choose &lt;code&gt;smollm2:135m&lt;/code&gt; is because most machines, even with 512 MB or memory, can run it.&lt;/p&gt;
&lt;p&gt;To start, run &lt;code&gt;ollama serve,&lt;/code&gt; in another CLI tab, and run &lt;code&gt;ollama pull smollm2:135m&lt;/code&gt;. If you have pulled &lt;code&gt;smollm2:135m&lt;/code&gt; from the previous parts of this tutorial series, the download will be very fast as the files already exist.&lt;/p&gt;
&lt;h3 id=&quot;generate-endpoint&quot; tabindex=&quot;-1&quot;&gt;Generate endpoint &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#generate-endpoint&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As the name points out, this API endpoint is available at &lt;code&gt;/api/generate&lt;/code&gt; you can POST data to generate a response from the selected model for the provided prompt. It responds as a stream by default; you can configure it to return all the responses in one go and not as a stream. It has four parameters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;model: the model&#39;s name, for example, &lt;code&gt;smollm2:135m&lt;/code&gt;, is a required parameter.&lt;/li&gt;
&lt;li&gt;prompt: is the prompt you want to send to the selected model like &lt;code&gt;Why is the sky blue?&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;suffix: can be used if you want to append some text after the response&lt;/li&gt;
&lt;li&gt;images: a list of base64-encoded images if you want to use it with multimodal models like Llava or SmolVLM.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are other advanced parameters, too, like &lt;code&gt;stream,&lt;/code&gt; which you can read about in the official &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md#generate-a-completion&quot;&gt;docs&lt;/a&gt;. For now, you can run the following curl command to get a response from &lt;code&gt;smollm2:!35m&lt;/code&gt; model:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; http://localhost:11434/api/generate &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{&lt;br /&gt;  &quot;model&quot;: &quot;smollm2:135m&quot;,&lt;br /&gt;  &quot;prompt&quot;: &quot;Why is the sky blue? Give the shortest answer possible in under 20 words&quot;,&lt;br /&gt;  &quot;stream&quot;: false&lt;br /&gt;}&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; jq &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the above &lt;code&gt;curl&lt;/code&gt; command, you are using the &lt;code&gt;/api/generate&lt;/code&gt; API endpoint and asking about the &lt;code&gt;smollm2:135m&lt;/code&gt; model. &lt;code&gt;Why is the sky blue? Give the shortest answer possible in under 20 words&lt;/code&gt;, and ask Ollama not to stream the output, so give the full answer in one go. Then, the output is piped to &lt;code&gt;jq&lt;/code&gt;. This gives the following output:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;smollm2:135m&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;created_at&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2025-02-08T11:02:55.115275Z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;response&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;The sky&#39;s clear and deep color due to tiny oxygen molecules (O2) scattering the sun&#39;s light allowing us to perceive it as blue.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;done&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;done_reason&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;stop&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;context&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;//a long array of numbers here&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;total_duration&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;302810709&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;load_duration&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;13315375&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;prompt_eval_count&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;47&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;prompt_eval_duration&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;132000000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;eval_count&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;eval_duration&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;156000000&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you were calling this API from another script or software system, you would be more concerned about the &lt;code&gt;response&lt;/code&gt; column. If you just want to see the response from the model, you can use &lt;code&gt;jq&lt;/code&gt; for that in the following way:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; http://localhost:11434/api/generate &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{&lt;br /&gt;  &quot;model&quot;: &quot;smollm2:135m&quot;,&lt;br /&gt;  &quot;prompt&quot;: &quot;Why is the sky blue? Give the shortest answer possible in under 20 words&quot;,&lt;br /&gt;  &quot;stream&quot;: false&lt;br /&gt;}&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; jq &lt;span class=&quot;token string&quot;&gt;&#39;.[&quot;response&quot;]&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You are asking &lt;code&gt;jq&lt;/code&gt; to show only the &lt;code&gt;response&lt;/code&gt; attribute from the JSON response rather than the whole response. It will look as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-api/02ollama-generate-api.jpg&quot; loading=&quot;lazy&quot; title=&quot;Output of calling the ollama generate API endpoint with cURL and jq&quot; alt=&quot;Output of calling the ollama generate API endpoint with cURL and jq&quot; /&gt;
&lt;p&gt;You can make many types of requests on the generated API endpoint. One useful one is &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md#request-structured-outputs&quot;&gt;structured output&lt;/a&gt;, where you can specify the output structure as a JSON object. Using the seed option, you can have &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md#request-reproducible-outputs&quot;&gt;reproducible outputs&lt;/a&gt;. If you provide an empty prompt, the model is loaded into memory. It would be advisable that you read the official &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md#generate-a-completion&quot;&gt;docs&lt;/a&gt; about the &lt;code&gt;generate&lt;/code&gt; endpoint.&lt;/p&gt;
&lt;h3 id=&quot;chat-endpoint&quot; tabindex=&quot;-1&quot;&gt;Chat endpoint &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#chat-endpoint&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The chat endpoint available at &lt;code&gt;/api/chat&lt;/code&gt;, which also works with POST, is similar to the &lt;code&gt;generate&lt;/code&gt; API. It generates the next message in a chat with a selected model. It is a streaming endpoint that will have a series of responses. You can turn off the streaming with the &lt;code&gt;”stream::false&lt;/code&gt; parameter as seen below:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; http://localhost:11434/api/chat &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{&lt;br /&gt;  &quot;model&quot;: &quot;smollm2:135m&quot;,&lt;br /&gt;  &quot;stream&quot;:false,&lt;br /&gt;  &quot;messages&quot;: [&lt;br /&gt;    {&lt;br /&gt;      &quot;role&quot;: &quot;user&quot;,&lt;br /&gt;      &quot;content&quot;: &quot;Why is the sky blue? Give the shortest answer possible in under 20 words&quot;&lt;br /&gt;    }&lt;br /&gt;  ]&lt;br /&gt;}&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; jq &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The output of the above cURL will be similar to the following:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;smollm2:135m&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;created_at&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2025-02-08T11:22:15.229839Z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;The sky appears blue because when sunlight passes through Earth&#39;s atmosphere, it contains tiny molecules like water vapor and oxygen. These molecules scatter shorter wavelengths of light (such as blue and violet) more than the longer wavelengths (like red and orange), making the sky appear blue to our eyes. Thank you for pointing this out!&quot;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;done_reason&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;stop&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;done&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;total_duration&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;407998750&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;load_duration&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6202542&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;prompt_eval_count&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;47&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;prompt_eval_duration&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;36000000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;eval_count&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;65&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;eval_duration&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;363000000&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As seen in the above response, the structure of the response is a bit different than the &lt;code&gt;generate&lt;/code&gt; API endpoint. This one has a &lt;code&gt;message&lt;/code&gt; attribute, which is an object, and a &lt;code&gt;content&lt;/code&gt; attribute inside it. If you want to extract the content from the response using Jq, you can run the following command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; http://localhost:11434/api/chat &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{&lt;br /&gt;  &quot;model&quot;: &quot;smollm2:135m&quot;,&lt;br /&gt;  &quot;stream&quot;:false,&lt;br /&gt;  &quot;messages&quot;: [&lt;br /&gt;    {&lt;br /&gt;      &quot;role&quot;: &quot;user&quot;,&lt;br /&gt;      &quot;content&quot;: &quot;Why is the sky blue? Give the shortest answer possible in under 20 words&quot;&lt;br /&gt;    }&lt;br /&gt;  ]&lt;br /&gt;}&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; jq &lt;span class=&quot;token string&quot;&gt;&#39;.[&quot;message&quot;][&quot;content&quot;]&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The extracted content from the response of the &lt;code&gt;/api/chat&lt;/code&gt; will look as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-api/03ollama-chat-api.jpg&quot; loading=&quot;lazy&quot; title=&quot;Output of calling the ollama chat API endpoint with cURL and jq&quot; alt=&quot;Output of calling the ollama chat API endpoint with cURL and jq&quot; /&gt;
&lt;p&gt;You can do &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md#chat-request-structured-outputs&quot;&gt;structured outputs&lt;/a&gt; with the chat endpoint. Being a chat endpoint, you can send in the &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md#chat-request-with-history&quot;&gt;history&lt;/a&gt; of the conversation to the the endpoint. For all the other types of reqeust, you can send to this &lt;code&gt;/api/chat&lt;/code&gt; endpoint, it would be best to go through the &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md#generate-a-chat-completion&quot;&gt;official Ollama docs&lt;/a&gt; about it.&lt;/p&gt;
&lt;h3 id=&quot;list-models&quot; tabindex=&quot;-1&quot;&gt;List models &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#list-models&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To list the local models available, you can call the &lt;code&gt;/api/tags&lt;/code&gt; endpoint, which works with a GET request. This endpoint lists models available locally that you can send as the model name parameter in the generate and chat endpoints. Below is an example call of this API:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; http://localhost:11434/api/tags &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; jq &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will output a JSON similar to the one seen below:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;models&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;smollm2:135m&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;smollm2:135m&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;modified_at&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2025-02-08T15:33:44.760304367+11:00&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;size&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;270898672&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;digest&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;9077fe9d2ae1a4a41a868836b56b8163731a8fe16621397028c2c76f838c6907&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;details&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;parent_model&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;format&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;gguf&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;family&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;llama&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;families&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token string&quot;&gt;&quot;llama&quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;parameter_size&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;134.52M&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;quantization_level&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;F16&quot;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;    &lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;qwen2.5:0.5b&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;qwen2.5:0.5b&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;modified_at&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2025-02-06T15:59:09.320362549+11:00&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;size&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;397821319&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;digest&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;a8b0c51577010a279d933d14c2a8ab4b268079d44c5c8830c0a93900f1827c67&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;details&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;parent_model&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;format&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;gguf&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;family&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;qwen2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;families&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token string&quot;&gt;&quot;qwen2&quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;parameter_size&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;494.03M&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;quantization_level&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Q4_K_M&quot;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;deepseek-r1:8b&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;deepseek-r1:8b&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;modified_at&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2025-02-02T13:33:29.069046707+11:00&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;size&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4920738407&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;digest&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;28f8fd6cdc677661426adab9338ce3c013d7e69a5bea9e704b364171a5d61a10&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;details&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;parent_model&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;format&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;gguf&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;family&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;llama&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;families&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token string&quot;&gt;&quot;llama&quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;parameter_size&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;8.0B&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;&quot;quantization_level&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Q4_K_M&quot;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I have these three models available on my machine. Your response might be slightly different, but the output structure will remain the same.&lt;/p&gt;
&lt;h3 id=&quot;pull-a-model&quot; tabindex=&quot;-1&quot;&gt;Pull a model &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#pull-a-model&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To download a new model from Ollama &lt;a href=&quot;https://ollama.com/search&quot;&gt;model registry&lt;/a&gt; you can use the &lt;code&gt;/api/pull&lt;/code&gt; API endpoint that works with a POST call. As the official doc states, canceled pulls are resumed, and in case of multiple pull calls they will share the same download progress.&lt;/p&gt;
&lt;p&gt;A model name is required to pull a model, and you can choose to stream or not stream the response. Below is an example of calling the &lt;code&gt;/api/pull&lt;/code&gt; endpoint without streaming to pull/download the &lt;code&gt;snowflake-arctic-embed:22m&lt;/code&gt;, which is an embedding model at 46 MB:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; http://localhost:11434/api/pull &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{&lt;br /&gt;  &quot;model&quot;: &quot;snowflake-arctic-embed:22m&quot;&lt;br /&gt;}&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; jq &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It gives out a very long output with all the information about the pull (download) and ends with:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;pulling 2977e9705f4b&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;digest&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;sha256:2977e9705f4b122813b1aeb50fc0c6563113da0b626f540c3daa8149827e30d3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;total&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;333&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;completed&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;333&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;verifying sha256 digest&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;writing manifest&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;success&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Given that the model is downloaded, the easiest way to verify this is by running the &lt;code&gt;ollama list&lt;/code&gt; command, and you will see the &lt;code&gt;snowflake-arctic-embed:22m&lt;/code&gt; on the list, a 45 MB model. Using this model, you can use the &lt;code&gt;/api/embed&lt;/code&gt; endpoint to generate the embeddings.&lt;/p&gt;
&lt;h3 id=&quot;show-model-information&quot; tabindex=&quot;-1&quot;&gt;Show model information &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#show-model-information&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;By calling the &#39;/api/show &#39; endpoint with a POST call, you can view the model information, including details, model file, template, parameters, license, and system prompt. The model name is a required parameter. Passing the &lt;code&gt;verbose&lt;/code&gt; optional parameter will return the full data with verbose fields in the response.&lt;/p&gt;
&lt;p&gt;Below is an example call to the show model information endpoint without the verbose flag for the &lt;code&gt;smollm2:135m&lt;/code&gt; model, some fields have been truncated for brevity:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;license&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&#92;nApache License&#92;n Version 2.0, January 2004...the full apache license here&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;modelfile&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;# Modelfile generated by &#92;&quot;ollama show&#92;&quot;&#92;n# To build a new Modelfile based on this, replace FROM with:&#92;n# FROM smollm2:135m&#92;n&#92;nFROM /path/to/.ollama/models/blobs/sha256-f535f83ec568d040f88ddc04a199fa6da90923bbb41d4dcaed02caa924d6ef57&#92;nTEMPLATE &#92;&quot;&#92;&quot;&#92;&quot;template and parameter info here&#92;nLICENSE &#92;&quot;&#92;&quot;&#92;&quot;&#92;nApache License&#92;n    Version 2.0, January 2004...the full apache license here&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;parameters&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;stop&#92;&quot;&amp;lt;|im_start|&gt;&#92;&quot;&#92;nstop&#92;&quot;&amp;lt;|im_end|&gt;&#92;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;template&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;template info here&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;system&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;You are a helpful AI assistant named SmolLM, trained by Hugging Face&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;details&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;parent_model&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/path/to/.ollama/models/blobs/sha256-f535f83ec568d040f88ddc04a199fa6da90923bbb41d4dcaed02caa924d6ef57&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;format&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;gguf&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;family&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;llama&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;families&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token string&quot;&gt;&quot;llama&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;parameter_size&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;134.52M&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;quantization_level&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;F16&quot;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;model_info&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;general.architecture&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;llama&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;general.basename&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;smollm2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;general.file_type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;general.finetune&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;8k-lc100k-mix1-ep2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;general.languages&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token string&quot;&gt;&quot;en&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;general.license&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;apache-2.0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;general.organization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;HuggingFaceTB&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;general.parameter_count&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;134515008&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;general.quantization_version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;general.size_label&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;135M&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;general.type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;llama.attention.head_count&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;llama.attention.head_count_kv&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;llama.attention.layer_norm_rms_epsilon&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.00001&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;llama.block_count&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;llama.context_length&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8192&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;llama.embedding_length&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;576&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;llama.feed_forward_length&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1536&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;llama.rope.dimension_count&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;llama.rope.freq_base&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;llama.vocab_size&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;49152&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;tokenizer.ggml.add_bos_token&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;tokenizer.ggml.add_space_prefix&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;tokenizer.ggml.bos_token_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;tokenizer.ggml.eos_token_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;tokenizer.ggml.merges&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token null keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;tokenizer.ggml.model&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;gpt2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;tokenizer.ggml.padding_token_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;tokenizer.ggml.pre&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;smollm&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;tokenizer.ggml.token_type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token null keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;tokenizer.ggml.tokens&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token null keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;tokenizer.ggml.unknown_token_id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;modified_at&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2025-02-08T15:33:44.760304367+11:00&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Depending on the level of security needed for your Ollama instance, the show model API should not be accessible outside of the app.&lt;/p&gt;
&lt;h3 id=&quot;other-ollama-apis&quot; tabindex=&quot;-1&quot;&gt;Other Ollama APIs &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#other-ollama-apis&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Other Ollama APIs can &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md#list-running-models&quot;&gt;list running models&lt;/a&gt;, &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md#delete-a-model&quot;&gt;delete a model&lt;/a&gt; (you would not want someone to delete a pulled model), &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md#create-a-model&quot;&gt;create a model&lt;/a&gt; from another model, &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md#copy-a-model&quot;&gt;copy a model&lt;/a&gt;, and even &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md#generate-embeddings&quot;&gt;generate embeddings&lt;/a&gt;. You can explore them all in the official &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md&quot;&gt;documents&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Suppose you have used Postman and its collections. You can also use this &lt;a href=&quot;https://www.postman.com/postman-student-programs/ollama-api/documentation/suc47x8/ollama-rest-api&quot;&gt;Postman collection&lt;/a&gt; that lists most of the Ollama API calls in a neat, easy to test collection. In the next part (part 4) of the Ollama blog series, you will learn how to run Ollama in Docker with Docker Compose.&lt;/p&gt;
&lt;h2 id=&quot;important-caveat&quot; tabindex=&quot;-1&quot;&gt;Important caveat &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#important-caveat&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you plan to host Ollma on a publicly accessible URL or with some form of authentication and authorization, please remember to expose only the generate (&lt;code&gt;/api/generate&lt;/code&gt;) and the chat  (&lt;code&gt;/api/chat&lt;/code&gt;) endpoints. You will not want users to call the pull or even delete model API endpoints.&lt;/p&gt;
&lt;p&gt;You can do it by putting a reverse proxy in front of Ollama’s Gin server (running at port 11434, by default). You can choose between &lt;a href=&quot;https://github.com/kesor/ollama-proxy&quot;&gt;Nginx reverse proxy&lt;/a&gt; or &lt;a href=&quot;https://caddyserver.com/docs/caddyfile/directives/reverse_proxy&quot;&gt;Caddy&lt;/a&gt;. With a reverse proxy, you can pass through only the traffic that comes to &lt;code&gt;/api/generate&lt;/code&gt; and &lt;code&gt;/api/chat&lt;/code&gt; forward to Ollama. As Ollama’s server is written in Go/Gin, you may even try that path to secure your APIs if you know how to write Go and Gin. There is an &lt;a href=&quot;https://github.com/ollama/ollama/issues/1053&quot;&gt;issue&lt;/a&gt; on the official Ollama GitHub repository about something similar if you want to follow that.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this post, you learned about some of the Ollama API endpoints, focusing on the ones that help you get a response from an open model. You learned about the Ollama API endpoints for pulling a model, listing models, and showing model information.&lt;/p&gt;
&lt;p&gt;More importantly, you are aware of a crucial caveat: you should not expose all the available Ollama APIs to the outside world. If someone calls the delete model API endpoint, your Ollama API will stop functioning, so be careful. Keep learning!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Ollama commands: How to use Ollama in the command line [Part 2]</title>
		<link href="https://geshan.com.np/blog/2025/02/ollama-commands/"/>
		<updated>2025-02-06T11:45:37Z</updated>
		<id>https://geshan.com.np/blog/2025/02/ollama-commands/</id>
		<content type="html">&lt;p&gt;Ollama is an open-source tool that helps you run open LLMs on your machine or a server. It is the glue layer between your machine (or hardware) and the open LLM of your choice. In this post, you will learn about the Ollama command you can use to get the most out of it; let’s get going!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-commands/01ollama-commands.jpg&quot; title=&quot;Ollama commands: How to use Ollama in the command line [Part 2]&quot; alt=&quot;Ollama commands: How to use Ollama in the command line [Part 2]&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#quick-recap&quot;&gt;Quick recap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#ollama-commands&quot;&gt;Ollama commands&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#ollama-serve&quot;&gt;Ollama serve&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#ollama-run&quot;&gt;Ollama run&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#ollama-list&quot;&gt;Ollama list&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#ollama-pull&quot;&gt;Ollama pull&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#ollama-ps&quot;&gt;Ollama ps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#ollama-create&quot;&gt;Ollama create&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#other-ollama-commands&quot;&gt;Other Ollama commands&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;quick-recap&quot; tabindex=&quot;-1&quot;&gt;Quick recap &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#quick-recap&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This blog post is part 2 of the Ollama series. In the &lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/&quot;&gt;first part&lt;/a&gt;, you covered topics like &lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#what-is-ollama&quot;&gt;what is Ollama&lt;/a&gt;, it’s &lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#ollama-features&quot;&gt;features&lt;/a&gt; and &lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#how-to-run-ollama-locally&quot;&gt;how to run Ollama&lt;/a&gt; with examples of Smollm2 and DeepSeek R1 models.&lt;/p&gt;
&lt;p&gt;In this part, you will learn about some useful Ollama commands like serve, run, and ps. Before diving deeper into code mode, please ensure you have Ollama installed and working in your system by reading &lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/&quot;&gt;part 1&lt;/a&gt;. Part 1 also covers the installation of Ollama and running the Smollm2 135 million parameter model and DeepSeek R1 8 billion parameter model.&lt;/p&gt;
&lt;p&gt;The part 3 of this Ollama series covers the &lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/&quot;&gt;Ollama APIs&lt;/a&gt;, which are used by the CLI and can be used by other systems to interact with the LLMs.&lt;/p&gt;
&lt;p&gt;In part 4, you will learn about running &lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/&quot;&gt;Ollama in Docker with Docker Compose&lt;/a&gt;. You will also add Open WebUI in a Docker container to interact with the LLMs running on Ollama with Docker Compose.&lt;/p&gt;
&lt;h2 id=&quot;ollama-commands&quot; tabindex=&quot;-1&quot;&gt;Ollama commands &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#ollama-commands&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ollama has multiple commands to achieve relative goals. To know the sub-commands you can run with Ollama, you can execute the following:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt; ollama &lt;span class=&quot;token parameter variable&quot;&gt;--help&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will give you the following output:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-commands/02ollama-help.jpg&quot; loading=&quot;lazy&quot; title=&quot;Output of ollama --help showing all available Ollama commands&quot; alt=&quot;Output of ollama --help showing all available Ollama commands&quot; /&gt;
&lt;p&gt;You can also run &lt;code&gt;ollama --version&lt;/code&gt; to check the version of Ollama when writing the version of Ollama is  &lt;code&gt;0.5.7&lt;/code&gt;. If you want help with a specific sub-command, you can add &lt;code&gt;--help&lt;/code&gt; after the sub-command; for example: &lt;code&gt;ollama run --help&lt;/code&gt; will give you the following output:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-commands/03ollama-run-help.jpg&quot; loading=&quot;lazy&quot; title=&quot;Output of ollama run --help showing available flag and environment variables&quot; alt=&quot;Output of ollama run --help showing available flag and environment variables&quot; /&gt;
&lt;p&gt;Now that you know the basics, let’s look at some useful Ollama commands.&lt;/p&gt;
&lt;h3 id=&quot;ollama-serve&quot; tabindex=&quot;-1&quot;&gt;Ollama serve &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#ollama-serve&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Ollama &lt;code&gt;serve&lt;/code&gt; is the main command that starts the Ollama server. It can be configured with many environment variables, such as &lt;code&gt;OLLAMA_DEBUG&lt;/code&gt; to enable or disable debugging, &lt;code&gt;OLLAMA_HOST&lt;/code&gt; to specify the server&#39;s host, and &lt;code&gt;OLLAMA_MAX_QUEUE&lt;/code&gt; to configure the maximum number of queued requests. To learn more about these environment variables, run &lt;code&gt;ollama serve --help&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Ollama runs &lt;a href=&quot;https://github.com/ollama/blob/main/server/routes.go#L27&quot;&gt;Gin&lt;/a&gt;  (written in Go) as the underlying server to add an API layer to the downloaded (pulled) models. Both the CLI and any other services that need to use LLM inference will use the server started with &lt;code&gt;ollama serve&lt;/code&gt;, which will give an output similar to the below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-commands/04ollama-serve.jpg&quot; loading=&quot;lazy&quot; title=&quot;Output of ollama serve showing applied environment variables&quot; alt=&quot;Output of ollama serve showing applied environment variables&quot; /&gt;
&lt;p&gt;The Gin server runs on port &lt;code&gt;11434&lt;/code&gt; by default, so if you hit &lt;code&gt;http://localhost:11434/&lt;/code&gt; on the browser of your choice (probably Chrome), you will see the text &lt;code&gt;Ollama is running&lt;/code&gt;. The next part of this Ollama series will discuss the API in detail.&lt;/p&gt;
&lt;p&gt;Given that the server is running, you will run a model next with &lt;code&gt;ollama run&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;ollama-run&quot; tabindex=&quot;-1&quot;&gt;Ollama run &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#ollama-run&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The Ollama &lt;code&gt;run&lt;/code&gt; command runs an open model available in the Ollama models &lt;a href=&quot;https://ollama.com/search&quot;&gt;page&lt;/a&gt;. It will pull (download) the model to your machine and then run it, exposing it via the API started with &lt;code&gt;ollama serve&lt;/code&gt;. Like the previous part, you will run the Smollm2 135 million parameter because it will run on most machines with even less memory (like 512 MB), as the model is 271 MB.&lt;/p&gt;
&lt;p&gt;To run Smollm2 135M parameters model, you can execute:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;ollama run smollm2:135m&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will result in something like the following:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-commands/05ollama-run-smollm2.jpg&quot; loading=&quot;lazy&quot; title=&quot;Output of ollama run smollm2:145m on the CLI when the model is already downloaded&quot; alt=&quot;Output of ollama run smollm2:145m on the CLI when the model is already downloaded&quot; /&gt;
&lt;p&gt;If you ran the model for the first time, it would have downloaded and run, as seen in the last &lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/&quot;&gt;part&lt;/a&gt; of this Ollama series. However, running an already pulled (downloaded) model runs quickly the second time.&lt;/p&gt;
&lt;p&gt;If you type &lt;code&gt;/?&lt;/code&gt; within the run command, you will see the help. You can set variables for the model like &lt;code&gt;num_ctx&lt;/code&gt;, which can be used to configure the &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/faq.md#how-can-i-specify-the-context-window-size&quot;&gt;context window&lt;/a&gt; of the model. For instance, you can type in &lt;code&gt;/set parameter num_ctx 8129&lt;/code&gt; to set the context window to 8129 tokens.&lt;/p&gt;
&lt;p&gt;You can also try &lt;code&gt;/show info&lt;/code&gt;, and it will show you the model’s information like:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; /show info&lt;br /&gt;  Model&lt;br /&gt;    architecture        llama      &lt;br /&gt;    parameters          &lt;span class=&quot;token number&quot;&gt;134&lt;/span&gt;.52M    &lt;br /&gt;    context length      &lt;span class=&quot;token number&quot;&gt;8192&lt;/span&gt;       &lt;br /&gt;    embedding length    &lt;span class=&quot;token number&quot;&gt;576&lt;/span&gt;        &lt;br /&gt;    quantization        F16        &lt;br /&gt;&lt;br /&gt;  Parameters&lt;br /&gt;    stop    &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;|im_start|&gt;&quot;&lt;/span&gt;    &lt;br /&gt;    stop    &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;|im_end|&gt;&quot;&lt;/span&gt;      &lt;br /&gt;&lt;br /&gt;  System&lt;br /&gt;    You are a helpful AI assistant named SmolLM, trained by Hugging Face    &lt;br /&gt;&lt;br /&gt;  License&lt;br /&gt;    Apache License               &lt;br /&gt;    Version &lt;span class=&quot;token number&quot;&gt;2.0&lt;/span&gt;, January &lt;span class=&quot;token number&quot;&gt;2004&lt;/span&gt;    &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can play with the other commands you run in the running model context. You can also chat with the model, asking it questions like &lt;code&gt;what is the speed of light?&lt;/code&gt; gave me the following output with the smollm2 135M parameter model:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; what is the speed of light?&lt;br /&gt;The speed of light &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; space is approximately &lt;span class=&quot;token number&quot;&gt;299,792&lt;/span&gt;,458 meters per second. This value is an approximation based on observations and calculations made using special relativity theory. While it&lt;span class=&quot;token string&quot;&gt;&#39;s difficult to measure precisely with our current technology, scientists have used the latest methods to estimate this value for both magnitude (1) as well as relative motion (the speed of light squared). &lt;br /&gt;&lt;br /&gt;It&#39;&lt;/span&gt;s worth noting that even &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; we can&#39;t directly calculate the exact speed of light &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; a vacuum using modern instruments and techniques, scientists often rely on estimates like those mentioned above.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To exit the running model context, type &lt;code&gt;/bye&lt;/code&gt; and return to the command line. Ollama run is a versatile command that executes prompts directly within the terminal, facilitating quick and efficient interactions with your models.&lt;/p&gt;
&lt;h3 id=&quot;ollama-list&quot; tabindex=&quot;-1&quot;&gt;Ollama list &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#ollama-list&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The Ollma list command lists all the open models pulled (downloaded) from Ollama’s registry and saved to your machine. When I ran &lt;code&gt;ollama list&lt;/code&gt; on my machine, I got the following output:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;ollama list    &lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;NAME                           ID                 SIZE      MODIFIED   &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;deepseek-r1:8b    28f8fd6cdc67      &lt;span class=&quot;token number&quot;&gt;4.9&lt;/span&gt; GB     &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; days ago    &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;smollm2:135m      9077fe9d2ae1    &lt;span class=&quot;token number&quot;&gt;270&lt;/span&gt; MB    &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; days ago    &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, I have two models, &lt;code&gt;smollm2:135m&lt;/code&gt; and &lt;code&gt;deepseek-r1:8b&lt;/code&gt;, which are 270MB and 4.9 GB, respectively.&lt;/p&gt;
&lt;h3 id=&quot;ollama-pull&quot; tabindex=&quot;-1&quot;&gt;Ollama pull &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#ollama-pull&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can download other models from the Ollama registry on your machine using the &lt;code&gt;ollama pull&lt;/code&gt; command. For instance, if you want to pull in Qwen 2.5 half a billion parameter model (398 MB), you can execute:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;ollama pull qwen2.5:0.5b&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That will result in something like:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;ollama pull qwen2.5:0.5b&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;pulling manifest&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;pulling c5396e06af29&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;. &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;% ▕██████████████████████████▏ &lt;span class=&quot;token number&quot;&gt;397&lt;/span&gt; MB&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;pulling 66b9ea09bd5b&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;. &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;% ▕██████████████████████████▏   &lt;span class=&quot;token number&quot;&gt;68&lt;/span&gt; B&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;pulling eb4402837c78&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;. &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;% ▕██████████████████████████▏ &lt;span class=&quot;token number&quot;&gt;1.5&lt;/span&gt; KB&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;pulling 832dd9e00a68&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;. &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;% ▕██████████████████████████▏  &lt;span class=&quot;token number&quot;&gt;11&lt;/span&gt; KB&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;pulling 005f95c74751&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;. &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;% ▕██████████████████████████▏  &lt;span class=&quot;token number&quot;&gt;490&lt;/span&gt; B&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;verifying sha256 digest&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;writing manifest&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;success&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will take some minutes, depending on your internet speed. If you run &lt;code&gt;ollama list&lt;/code&gt; after pulling the Qwen model, it will be listed too like below:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;ollama list&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;NAME                   ID            SIZE      MODIFIED       &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;qwen2.5:0.5b      a8b0c5157701       &lt;span class=&quot;token number&quot;&gt;397&lt;/span&gt; MB    &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt; seconds ago    &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;deepseek-r1:8b    28f8fd6cdc67       &lt;span class=&quot;token number&quot;&gt;4.9&lt;/span&gt; GB    &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; days ago        &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;smollm2:135m      9077fe9d2ae1       &lt;span class=&quot;token number&quot;&gt;270&lt;/span&gt; MB    &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; days ago    &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly, running the Qwen model now will run directly rather than downloading and running it after downloading. You can also look at the CLI tab running &lt;code&gt;ollama serve&lt;/code&gt; to see all the API calls these commands make in the background. Ollama pull seamlessly downloads and integrates pre-trained models from the vast Ollama model library to be used on your machine.&lt;/p&gt;
&lt;h3 id=&quot;ollama-ps&quot; tabindex=&quot;-1&quot;&gt;Ollama ps &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#ollama-ps&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Like other &lt;code&gt;ps&lt;/code&gt; commands that list processes, the &lt;code&gt;ollama ps&lt;/code&gt; command will list running models. For this, you will first need to run a model; you can run the Qwen2 0.5 B parameters model with &lt;code&gt;ollama run qwen2.5:0.5b&lt;/code&gt;. Then, in a new CLI tab, you can run &lt;code&gt;ollama ps&lt;/code&gt;, which will give an output similar to the following:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;ollama &lt;span class=&quot;token function&quot;&gt;ps&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;NAME            ID              SIZE      PROCESSOR    UNTIL              &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;qwen2.5:0.5b    a8b0c5157701    &lt;span class=&quot;token number&quot;&gt;1.4&lt;/span&gt; GB    &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;% GPU     &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; minutes from now  &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To exit the run context, type &lt;code&gt;/bye&lt;/code&gt; to return to the command line.&lt;/p&gt;
&lt;h3 id=&quot;ollama-create&quot; tabindex=&quot;-1&quot;&gt;Ollama create &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#ollama-create&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;With the &lt;code&gt;ollama create&lt;/code&gt; command, you can create a new variant of an existing open model. For example, you will create a new variant of the &lt;code&gt;smollm2:135m&lt;/code&gt; parameter model with a context window of 16K, and the temperature (creativeness) is set to 0.1, which is significantly less creative. To do this, first, you will create a Model file named &lt;code&gt;Modelfile-smollm2-16k&lt;/code&gt; in your current folder with the following content:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;FROM smollm2:135m&lt;br /&gt;&lt;br /&gt;PARAMETER temperature &lt;span class=&quot;token number&quot;&gt;0.2&lt;/span&gt;&lt;br /&gt;PARAMETER num_ctx &lt;span class=&quot;token number&quot;&gt;16384&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Like Docker, you are saying to start from the &lt;code&gt;smollm2:135m&lt;/code&gt;, set the &lt;code&gt;temperature&lt;/code&gt; parameter to &lt;code&gt;0.2&lt;/code&gt;, and set the context with the &lt;code&gt;num_ctx&lt;/code&gt; parameter to &lt;code&gt;16384&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, to create a new model named &lt;code&gt;smollm2:135m-16k-ctx&lt;/code&gt; you will run the following command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;ollama create smollm2:135m-16k-ctx &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt; Modelfile-smollm2-16k&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will create a new variant of the Smollm2 135 million parameter model following the instructions in the model file. If you run &lt;code&gt;ollama list&lt;/code&gt;, you will see the new model on the list. Then, to run the new model, you can execute &lt;code&gt;ollama run smollm2:135m-16k-ctx&lt;/code&gt; as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-commands/06ollama-create.jpg&quot; loading=&quot;lazy&quot; title=&quot;Output of ollama create a new model with 0.2 temperature and context window of 16K tokens&quot; alt=&quot;Output of ollama create a new model with 0.2 temperature and context window of 16K tokens&quot; /&gt;
&lt;p&gt;In the running model context, where you can type &lt;code&gt;/?&lt;/code&gt; for help, if you type in &lt;code&gt;/show info&lt;/code&gt; you will see the following output:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;/show info&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  Model&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    architecture        llama      &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    parameters          &lt;span class=&quot;token number&quot;&gt;134&lt;/span&gt;.52M    &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    context length      &lt;span class=&quot;token number&quot;&gt;8192&lt;/span&gt;       &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    embedding length    &lt;span class=&quot;token number&quot;&gt;576&lt;/span&gt;        &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    quantization        F16        &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  Parameters&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    temperature    &lt;span class=&quot;token number&quot;&gt;0.2&lt;/span&gt;               &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    num_ctx        &lt;span class=&quot;token number&quot;&gt;16384&lt;/span&gt;             &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    stop           &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;|im_start|&gt;&quot;&lt;/span&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    stop           &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;|im_end|&gt;&quot;&lt;/span&gt;      &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  System&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    You are a helpful AI assistant named SmolLM, trained by Hugging Face    &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  License&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    Apache License               &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    Version &lt;span class=&quot;token number&quot;&gt;2.0&lt;/span&gt;, January &lt;span class=&quot;token number&quot;&gt;2004&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means the two parameters specified in the Model file,  &lt;code&gt;temperature&lt;/code&gt; and context window with &lt;code&gt;num_ctx&lt;/code&gt;, are applied to the model. Because the temperature is set to a low value &lt;code&gt;0.2&lt;/code&gt;, if you ask this model variant, &lt;code&gt;why is the sky blue? give me 1 sentence answer.&lt;/code&gt; even 3 times consecutively; it will give you almost the same answer as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-commands/07ollama-sky-blue.jpg&quot; loading=&quot;lazy&quot; title=&quot;Output of ollama why is the sky blue, same answer as the temperature is only 0.2&quot; alt=&quot;Output of ollama why is the sky blue, same answer as the temperature is only 0.2&quot; /&gt;
&lt;p&gt;Next, you will learn about some other Ollama commands.&lt;/p&gt;
&lt;h3 id=&quot;other-ollama-commands&quot; tabindex=&quot;-1&quot;&gt;Other Ollama commands &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#other-ollama-commands&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you can pull a model, you can &lt;code&gt;push&lt;/code&gt; a model to the Ollama registry. For this, you will need an Ollama account and API keys to &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/import.md#sharing-your-model-on-ollamacom&quot;&gt;share your model&lt;/a&gt; on Ollama.&lt;/p&gt;
&lt;p&gt;Similarly, you can copy a model with &lt;code&gt;ollama cp&lt;/code&gt; and remove a model with &lt;code&gt;ollama rm&lt;/code&gt; followed by the model&#39;s name. You can also run &lt;code&gt;ollama show &amp;lt;model-name&amp;gt;&lt;/code&gt; to see the configuration of the model; for example, &lt;code&gt;ollama show smollm2:135m&lt;/code&gt; will show the following:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;ollama show smollm2:135m &lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  Model&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    architecture        llama      &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    parameters          &lt;span class=&quot;token number&quot;&gt;134&lt;/span&gt;.52M    &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    context length      &lt;span class=&quot;token number&quot;&gt;8192&lt;/span&gt;       &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    embedding length    &lt;span class=&quot;token number&quot;&gt;576&lt;/span&gt;        &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    quantization        F16        &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  Parameters&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    stop    &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;|im_start|&gt;&quot;&lt;/span&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    stop    &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;|im_end|&gt;&quot;&lt;/span&gt;      &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  System&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    You are a helpful AI assistant named SmolLM, trained by Hugging Face    &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  License&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    Apache License               &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    Version &lt;span class=&quot;token number&quot;&gt;2.0&lt;/span&gt;, January &lt;span class=&quot;token number&quot;&gt;2004&lt;/span&gt;    &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above output is the same as running &lt;code&gt;/show info&lt;/code&gt; when the model runs within the CLI. As the new versions of Ollama are released, it may have new commands. To learn the list of Ollama commands, run &lt;code&gt;ollama --help&lt;/code&gt; and find the available commands.&lt;/p&gt;
&lt;p&gt;Ollama commands are similar to &lt;a href=&quot;https://geshan.com.np/blog/2022/05/docker-commands/&quot;&gt;Docker commands&lt;/a&gt;, like pull, push, ps, rm. In the case of Docker, it works with Docker images or containers, and for Ollama, it works with open LLM models.&lt;/p&gt;
&lt;p&gt;In the next part of this Ollama series, you will learn about the Ollama APIs. The CLI also uses these APIs; you will learn more about them so that another system can use them for LLM inference.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this comprehensive guide, you explored a wide range of essential Ollama commands, From &lt;code&gt;ollama serve&lt;/code&gt; to &lt;code&gt;ollama run&lt;/code&gt;, and from &lt;code&gt;ollama pull&lt;/code&gt; to &lt;code&gt;ollam create&lt;/code&gt;. By mastering these Ollama commands, you&#39;ll be well-equipped to harness the full potential of this powerful and easy-to-use framework, opening up a world of possibilities for your projects and applications. Whether you&#39;re a seasoned developer or just starting your journey into AI, Ollama and its commands will undoubtedly be invaluable assets in your toolkit. Keep learning!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>What is Ollama and how to use it: a quick guide [part 1]</title>
		<link href="https://geshan.com.np/blog/2025/02/what-is-ollama/"/>
		<updated>2025-02-02T11:47:52Z</updated>
		<id>https://geshan.com.np/blog/2025/02/what-is-ollama/</id>
		<content type="html">&lt;p&gt;The world of AI has been hyped for more than two years now since the release of ChatGPT in November 2022. New tools and technologies emerge daily, promising to revolutionize our work and lives. If you&#39;re looking to harness the power of large language models (LLMs) for personal projects or even professional applications, Ollama might be the key. In this post, you will learn what Ollama is, how to download, install, and use Ollama to run a small model, and then run DeepSeek R1 (the other super popular LLM); let’s get started.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/what-is-ollama/01what-is-ollama.jpg&quot; title=&quot;What is Ollama and how to use it: a quick guide [part 1]&quot; alt=&quot;What is Ollama and how to use it: a quick guide [part 1]&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#what-is-ollama&quot;&gt;What is Ollama&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#ollama-blog-post-series&quot;&gt;Ollama blog post series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#ollama-features&quot;&gt;Ollama features&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#privacy-and-offline-access&quot;&gt;Privacy and offline access&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#model-management&quot;&gt;Model management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#seamless-installation&quot;&gt;Seamless installation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#local-api&quot;&gt;Local API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#customization&quot;&gt;Customization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#hardware-acceleration&quot;&gt;Hardware acceleration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#adding-a-user-interface&quot;&gt;Adding a user interface&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#how-to-run-ollama-locally&quot;&gt;How to run Ollama locally&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#run-deepseek-r1-with-ollama&quot;&gt;Run DeepSeek R1 with Ollama&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#where-does-ollama-store-the-models&quot;&gt;Where does Ollama store the models&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-is-ollama&quot; tabindex=&quot;-1&quot;&gt;What is Ollama &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#what-is-ollama&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ollama is an &lt;a href=&quot;https://github.com/ollama/ollama&quot;&gt;open-source&lt;/a&gt; tool mainly written in Go lang (89%) that runs open LLMs on your local machine (or a server). It acts like a bridge between any open LLM and your machine, not only running them but also providing an API layer on top of them so that another application or service can use them.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ollama.com/&quot;&gt;Ollama&lt;/a&gt; is a user-friendly and powerful software for running LLMs locally. It hides the complexities of LLMs, packaging them to be accessible and easily customizable with a &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/modelfile.md&quot;&gt;model file&lt;/a&gt;. There are alternatives to Ollama, like &lt;a href=&quot;https://github.com/vllm-project/vllm&quot;&gt;vllm&lt;/a&gt; and &lt;a href=&quot;https://github.com/aphrodite-engine/aphrodite-engine&quot;&gt;aphrodite&lt;/a&gt;, but Ollama is surely the most popular one. Ollama provides a clean, user-friendly interface that allows you to interact directly with LLMs, tailoring the experience to your needs.&lt;/p&gt;
&lt;h2 id=&quot;ollama-blog-post-series&quot; tabindex=&quot;-1&quot;&gt;Ollama blog post series &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#ollama-blog-post-series&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This post is the first part of a series of posts on Ollama. In this series, you will learn about Ollama, its features, how to install and run it on your local machine, and how to use it with different models.&lt;/p&gt;
&lt;p&gt;The part 2 of this series will cover &lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/&quot;&gt;Ollama commands&lt;/a&gt;. In this part, you will learn about the various commands you can use with Ollama to interact with LLMs. You will learn how to list models, run models, pull models, and more.&lt;/p&gt;
&lt;p&gt;Similarly in part 3, you will learn about &lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-api/&quot;&gt;Ollama APIs&lt;/a&gt;, which are used by the CLI and can be used by other systems to interact with the LLMs mainly for generating responses out of an open LLM.&lt;/p&gt;
&lt;p&gt;In part 4, you will learn how to run &lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-docker-compose/&quot;&gt;Ollama with Docker Compose&lt;/a&gt;. Docker is a popular containerization tool that allows you to run applications in a container. You will also add Open WebUI to have a web interface on top of LLMs running on Ollama.&lt;/p&gt;
&lt;h2 id=&quot;ollama-features&quot; tabindex=&quot;-1&quot;&gt;Ollama features &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#ollama-features&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Below are some important features of Ollama:&lt;/p&gt;
&lt;h3 id=&quot;privacy-and-offline-access&quot; tabindex=&quot;-1&quot;&gt;Privacy and offline access &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#privacy-and-offline-access&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;One of the most important features of Ollama is privacy and offline access. You can run open models privately on your machine, even without internet access. This not only enables you to use an LLM (say, for code suggestions) on a plane but also keeps your data on your local machine. Your data and files can stay safe in your local machine, and other big tech companies do not see it or get to use it for other purposes like training an LLM. This is a big advantage of Ollama over other cloud-based LLM services which send your data to the cloud for processing and may use it for other purposes.&lt;/p&gt;
&lt;h3 id=&quot;model-management&quot; tabindex=&quot;-1&quot;&gt;Model management &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#model-management&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Adding a new model to the library of local models is easy. You can pull a model with &lt;code&gt;ollama pull&lt;/code&gt; command and run it. At the time of writing, there are 150+ models you can pull and run locally, from DeepSeek R1 to Smollm, you can run popular models like Llama 3, Phi 4, Gemma 2, Mistral to code-specific models like Codeqwen, and Codestral. There is no need to navigate any complex format or dependencies or install any other software on your machine. You can pull a model and run it; if your system&#39;s resources support it, it will run easily.&lt;/p&gt;
&lt;h3 id=&quot;seamless-installation&quot; tabindex=&quot;-1&quot;&gt;Seamless installation &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#seamless-installation&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As you will learn in the next section, Ollama&#39;s installation process is very user-friendly. Regardless of your Windows, Linux, or Mac operating system, you essentially run a command, and the Ollama CLI is available on your local machine. Thus, Ollama surely boasts a smooth and hassle-free installation and setup experience. With one command you can istall ollma CLI on a Linux or Mac operating system.&lt;/p&gt;
&lt;h3 id=&quot;local-api&quot; tabindex=&quot;-1&quot;&gt;Local API &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#local-api&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Ollama has various commands, including the &lt;code&gt;ollama serve&lt;/code&gt; command. This command starts a &lt;a href=&quot;https://github.com/gin-gonic/gin&quot;&gt;Gin server&lt;/a&gt; expoing an &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md&quot;&gt;API&lt;/a&gt; over all the LLM models available on your local system. This allows you to integrate LLMs into other applications and workflows. An API enables efficient communication between your application and LLMs. You can send prompts, get responses back, and exploit the full potential of LLMs. Using &lt;a href=&quot;https://ollama.com/blog/structured-outputs&quot;&gt;structured outputs&lt;/a&gt;, you can even get the response from the LLMs in a predefined schema.&lt;/p&gt;
&lt;h3 id=&quot;customization&quot; tabindex=&quot;-1&quot;&gt;Customization &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#customization&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;With Ollama you can tweak parameters and extract the most value out of LLMs on your local machine. For instance you can change the &lt;code&gt;num_ctx&lt;/code&gt; parameter and change the &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/faq.md#how-can-i-specify-the-context-window-size&quot;&gt;context window size&lt;/a&gt; for a model with Ollama. You can also change the configs to fine-tune LLM parameters, adjust settings and change the model behaviour to better suits your needs. You can also use a &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/modelfile.md#parameter&quot;&gt;modelfile&lt;/a&gt; to set multiple parameters like temperature, seed, top K, top P and others.&lt;/p&gt;
&lt;h3 id=&quot;hardware-acceleration&quot; tabindex=&quot;-1&quot;&gt;Hardware acceleration &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#hardware-acceleration&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Figuring out the resource and computational needs of the LLMs, Ollama can leverage the available hardware resources on your system including GPUs and CPUs. To check this you can run a &lt;code&gt;ollma ps&lt;/code&gt; command and see the &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/faq.md#how-can-i-tell-if-my-model-was-loaded-onto-the-gpu&quot;&gt;resource&lt;/a&gt; usages. Ollama makes sure the resources in your machine are utilized efficiently which enables you to run even large LLMs easily.&lt;/p&gt;
&lt;h3 id=&quot;adding-a-user-interface&quot; tabindex=&quot;-1&quot;&gt;Adding a user interface &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#adding-a-user-interface&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Ollama is a command-line interface (CLI) aimed at advanced users. To use a graphical user interface with a chat, you can download and use &lt;a href=&quot;https://openwebui.com/&quot;&gt;open web ui&lt;/a&gt; (previously known as Ollama Web UI). Open web UI is also &lt;a href=&quot;https://github.com/open-webui/open-webui&quot;&gt;open-source&lt;/a&gt;. It claims to be an extensible, feature-rich, and user-friendly self-hosted AI platform designed to operate entirely offline. You can read the official &lt;a href=&quot;https://docs.openwebui.com/getting-started/quick-start/starting-with-ollama&quot;&gt;docs&lt;/a&gt; to get started with open web UI which plays along well with Ollama.&lt;/p&gt;
&lt;p&gt;In the next seciton, you will learn how to install and use Ollama.&lt;/p&gt;
&lt;h2 id=&quot;how-to-run-ollama-locally&quot; tabindex=&quot;-1&quot;&gt;How to run Ollama locally &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#how-to-run-ollama-locally&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ollama is easy to install and use on any operating system, be it Windows, Linux or Mac. For this guide, you will install it on a Mac and run the &lt;code&gt;smollom2&lt;/code&gt; model with 135 million parameters which is 271 MB.  The &lt;a href=&quot;https://ollama.com/library/smollm&quot;&gt;smollom&lt;/a&gt; 135 M parameters is 92 MB which is one of the smallest but still useful model.&lt;/p&gt;
&lt;p&gt;To install Ollama on the operating system of your choice, you can navigate to the official Ollama &lt;a href=&quot;https://ollama.com/download&quot;&gt;download&lt;/a&gt; page. It looks as follow:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/what-is-ollama/02download-ollama.jpg&quot; loading=&quot;lazy&quot; title=&quot;Official page to downlaod Ollama for Windows, Mac or Linux&quot; alt=&quot;Official page to downlaod Ollama for Windows, Mac or Linux&quot; /&gt;
&lt;p&gt;As I am using a Mac I can download the installer from that page or run the following command to get Ollama CLI installed on a Mac:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;brew &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; ollama&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will install Ollama and all its related dependences and end like the below if all goes well:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/what-is-ollama/03brew-install-ollama-output.jpg&quot; loading=&quot;lazy&quot; title=&quot;Final successful output of brew install ollama on a Mac&quot; alt=&quot;Final successful output of brew install ollama on a Mac&quot; /&gt;
&lt;p&gt;If you installed it with brew you will need to run &lt;code&gt;ollama serve&lt;/code&gt;. You will see the ollama variables and resources.&lt;br /&gt;
Then you can run &lt;code&gt;ollama –version&lt;/code&gt; in a different CLI tab. You will see something like the bleow:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt; ➜  ollama &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt;&lt;br /&gt;ollama version is &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt;.7&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At the time of writing the latest version of Ollama is &lt;code&gt;0.5.7&lt;/code&gt;. As this point, because ollama is just installed you will not have any models. To check that you can run &lt;code&gt;ollama list&lt;/code&gt; which will show an empty list.&lt;/p&gt;
&lt;p&gt;Now, to install and run the &lt;a href=&quot;https://ollama.com/library/smollm2:135m&quot;&gt;smollom2&lt;/a&gt; 135 million parameter model you will execute the following on your command line:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;ollama run smollm2:135m&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Depending on your internet speed to download the 271MB model, it will take some time and show your the following output, where you can type your first question/promot to the model like&lt;br /&gt;
&lt;code&gt;why is the sky blue? give the shortest possible answer&lt;/code&gt;:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/what-is-ollama/04ollama-run-smollm2.jpg&quot; loading=&quot;lazy&quot; title=&quot;Running Smollm2 135 million parameters model (271 MB) with Ollama&quot; alt=&quot;Running Smollm2 135 million parameters model (271 MB) with Ollama&quot; /&gt;
&lt;p&gt;You can play around and send it prompts or questions like &lt;code&gt;who are you?&lt;/code&gt;. It will give the answers. If you write &lt;code&gt;/?&lt;/code&gt; you will see the help menu as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/what-is-ollama/05ollama-bye.jpg&quot; loading=&quot;lazy&quot; title=&quot;Exit the Ollama prompt of running model with /bye&quot; alt=&quot;Exit the Ollama prompt of running model with /bye&quot; /&gt;
&lt;p&gt;You can type in &lt;code&gt;/bye&lt;/code&gt; to stop the running model and get out of its prompt. Congrats! You have successfully run a relatively smaller LLM (pun intended) on your machine. As it is a smaller model with only 135 million parameters (271 MB) it might not perform many tasks well. So in the next section you will run the popular DeepSeek R1 8 billion parameter model.&lt;/p&gt;
&lt;h3 id=&quot;run-deepseek-r1-with-ollama&quot; tabindex=&quot;-1&quot;&gt;Run DeepSeek R1 with Ollama &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#run-deepseek-r1-with-ollama&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To run DeepSeek R1 8 billion parameter model you can run the following command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;ollama run deepseek-r1:8b&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Keep in mind, you are downloading almost 4.9 GB of data, so depending on your internet speed it might take minutes (or hours, I can’t say). With Ollama you can try many open models, have a look at their &lt;a href=&quot;https://ollama.com/search&quot;&gt;models&lt;/a&gt; page and you can choose which model you would like to run on your local machine. Make sure that you have enough resources, memory, CPU and disk space to run a really large model. For iinstance the DeepSeek R1 671B parameters model is 404 GB which will surely not run a consumer grade laptop.&lt;/p&gt;
&lt;p&gt;In my case, after a few minutes of watiing the &lt;code&gt;deepseek-r1:8b&lt;/code&gt; model was downloaded and it ran. You can run the same question/prompt of &lt;code&gt;why is the sky blue? give the shortest possible answer&lt;/code&gt; and see the response from the model as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/what-is-ollama/06ollama-deepseek-r1.jpg&quot; loading=&quot;lazy&quot; title=&quot;Running Deepseek R1 8 billion parameters model (4.9 GB) with Ollama&quot; alt=&quot;Running Deepseek R1 8 billion parameters model (4.9 GB) with Ollama&quot; /&gt;
&lt;p&gt;As you can see above, DeepSeek R1 (R for reasoning) apparently “thinks” and then gives back a response. Thats is something new. To stop the model and exit the chat you can type &lt;code&gt;/bye&lt;/code&gt; and then get back to the bash.&lt;/p&gt;
&lt;h3 id=&quot;where-does-ollama-store-the-models&quot; tabindex=&quot;-1&quot;&gt;Where does Ollama store the models &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#where-does-ollama-store-the-models&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Depending on your operationg system and how you installed Ollama it may vary. In my case, on a Mac it was stored in the user directory at &lt;code&gt;~/.ollama/models&lt;/code&gt; as you can see below with the command &lt;code&gt;ls -al ~/.ollama/models&lt;/code&gt;:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/what-is-ollama/07ollama-model-storage.jpg&quot; loading=&quot;lazy&quot; title=&quot;Ollama stores models at ~/.ollama/models&quot; alt=&quot;Ollama stores models at ~/.ollama/models&quot; /&gt;
&lt;p&gt;Ollama store the models at &lt;code&gt;~/.ollama/models&lt;/code&gt; on Linux machines as well. It can be changed by setting an &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/faq.md#setting-environment-variables-on-linux&quot;&gt;environment variable&lt;/a&gt; called &lt;code&gt;OLLAMA_MODELS&lt;/code&gt;.  In the next part of this series, you will learn about &lt;a href=&quot;https://geshan.com.np/blog/2025/02/ollama-commands/&quot;&gt;Ollama commands&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/02/what-is-ollama/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ollama is a game-changer for anyone working with LLMs. It simplifies the often daunting complexities of LLM interactions, making this powerful technology accessible to a much broader audience. Ollama&#39;s intuitive interface and user-friendly design make it the perfect tool for maximizing the power of LLMs and effortlessly incorporating them into your workflow.&lt;/p&gt;
&lt;p&gt;In this post you learned how to install Ollama and run Smollom2 and DeepSeek R1 models on it using the command line. You also found out where Ollama stores the downloaded models. Happy AI exploration!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to use Gemini over Vertex AI to summarize and categorize job listings with controlled generation</title>
		<link href="https://geshan.com.np/blog/2025/01/controlled-generation-gemini/"/>
		<updated>2025-01-26T11:34:52Z</updated>
		<id>https://geshan.com.np/blog/2025/01/controlled-generation-gemini/</id>
		<content type="html">&lt;p&gt;LLMs generally reply in a nondeterministic format; it does not always comply with the formatting instructions given. This is where controlled generation (structured output) comes into play, where you ask an LLM to reply to comply with a given schema. In this post, you will learn how to use Gemini over Vertex AI and controlled generation to get structured output that follows a schema on job listings to summarize and categorize them. Let&#39;s get going!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/controlled-generation-gemini/01controlled-generation-gemini.jpg&quot; title=&quot;How to use Gemini over Vertex AI to summarize and categorize job listings with controlled generation&quot; alt=&quot;How to use Gemini over Vertex AI to summarize and categorize job listings with controlled generation&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#the-solution-to-enhance&quot;&gt;The solution to enhance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#summairze-and-classify-using-gemini-over-vertex-ai&quot;&gt;Summairze and classify using Gemini over Vertex AI&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#vertex-ai-freeform&quot;&gt;Vertex AI Freeform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#the-prompt&quot;&gt;The prompt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#using-better-settings&quot;&gt;Using better settings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#schema-for-controlled-generation&quot;&gt;Schema for controlled generation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#test-it&quot;&gt;Test it&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#generate-code&quot;&gt;Generate code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#controlled-generation-is-useful&quot;&gt;Controlled generation is useful&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-solution-to-enhance&quot; tabindex=&quot;-1&quot;&gt;The solution to enhance &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#the-solution-to-enhance&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is a real-life scenario where one of our side projects - &lt;a href=&quot;https://app.autechjobs.com/&quot;&gt;AU Tech Jobs&lt;/a&gt; which aggregates jobs from multiple (like 60+) company job listing pages. If interested, you can read the &lt;a href=&quot;https://geshan.com.np/blog/2021/06/life-changing-side-project/&quot;&gt;story of ATJ&lt;/a&gt;. Currently, the job details page has two useful features on the job detail page, built by calling two different APIs.&lt;/p&gt;
&lt;p&gt;The first one is if the “computer percent” for a particular job is less than a given threshold, it shows a message &lt;code&gt;Our machine learning algorithm suggests this might not be a pure tech job&lt;/code&gt; to let the user know it might not be a tech job, for example, an “Account Executive” role is not a tech or software engineering/tech job. Currently, this classification is done using the &lt;a href=&quot;https://uclassify.com/browse/uclassify/topics?input=Text&quot;&gt;uclassify API&lt;/a&gt;. It does an “ok” jo,b but sometimes does not give back a good &lt;code&gt;computer_percent&lt;/code&gt; classification.&lt;/p&gt;
&lt;p&gt;The second feature is a summary of the job description. Currently, this feature is done using &lt;a href=&quot;https://github.com/geshan/bert-extractive-summarizer&quot;&gt;Bert Executive summarizer&lt;/a&gt; – you can &lt;a href=&quot;https://smrzr.io/&quot;&gt;try it&lt;/a&gt; out. &lt;a href=&quot;https://www.nvidia.com/en-au/glossary/bert/&quot;&gt;BERT&lt;/a&gt; by Google is like the previous version before the transformer models. It does the summarization task but is not as versatile as a Large Language Model (LLM). We call another API to get the summary of the job description.&lt;/p&gt;
&lt;p&gt;Both the features look as follows in action:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/controlled-generation-gemini/02au-tech-jobs-features.jpg&quot; loading=&quot;lazy&quot; title=&quot;AU Tech Jobs job detail page features of summary and tech job categorization and percent&quot; alt=&quot;AU Tech Jobs job detail page features of summary and tech job categorization and percent&quot; /&gt;
&lt;p&gt;The enhancement we want to make is to get both the summary and the categorization (tech percentage, in this case) using an LLM and a prompt in a single call. If it is an LLM call, other features could be easily added. The next section will see how this can be done with a working proof of concept.&lt;/p&gt;
&lt;h2 id=&quot;summairze-and-classify-using-gemini-over-vertex-ai&quot; tabindex=&quot;-1&quot;&gt;Summairze and classify using Gemini over Vertex AI &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#summairze-and-classify-using-gemini-over-vertex-ai&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now, if we were to modernize the summary generation and &lt;code&gt;computer&lt;/code&gt; of &lt;code&gt;software engineering&lt;/code&gt; percent of the given job description with the current powerful LLMs, it can be done with a single call (or prompt). Let’s look at how you can do a proof of concept on Vertext AI using Gemini 2.0 Flash.&lt;/p&gt;
&lt;p&gt;To do this, you will need a Google Cloud Account (with some credits on it), then you can follow along next:&lt;/p&gt;
&lt;h3 id=&quot;vertex-ai-freeform&quot; tabindex=&quot;-1&quot;&gt;Vertex AI Freeform &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#vertex-ai-freeform&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can start by creating a &lt;a href=&quot;https://console.cloud.google.com/projectcreate&quot;&gt;new GCP project&lt;/a&gt; or using an existing one. On your selected project, search for &lt;code&gt;vertex&lt;/code&gt; and click on &lt;code&gt;Vertex AI&lt;/code&gt; as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/controlled-generation-gemini/03search-vertex.jpg&quot; loading=&quot;lazy&quot; title=&quot;Search for vertex on the GCP UI search bar&quot; alt=&quot;Search for vertex on the GCP UI search bar&quot; /&gt;
&lt;p&gt;On the Vertex AI page, click on &lt;code&gt;Freeform&lt;/code&gt; below &lt;code&gt;Vertex AI Studio&lt;/code&gt; on the left menu as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/controlled-generation-gemini/04vertex-ai-freeform-link.jpg&quot; loading=&quot;lazy&quot; title=&quot;Click on Freeform under Vertex AI Studio on the Vertex AI page on GCP&quot; alt=&quot;Click on Freeform under Vertex AI Studio on the Vertex AI page on GCP&quot; /&gt;
&lt;p&gt;If it is a new project or you are using Vertext AI for the first time, you will need to enable the Vertex AI API by clicking &lt;code&gt;Agree &amp;amp; Continue&lt;/code&gt; as shown below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/controlled-generation-gemini/05vertex-ai-api.jpg&quot; loading=&quot;lazy&quot; title=&quot;Agree and continue to use the Vertex AI API&quot; alt=&quot;Agree and continue to use the Vertex AI API&quot; /&gt;
&lt;p&gt;At this point, you should have landed on the &lt;code&gt;Vertex AI&lt;/code&gt; Freeform page as seen here:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/controlled-generation-gemini/06vertex-ai-freeform-page.jpg&quot; loading=&quot;lazy&quot; title=&quot;You will land on the Vertex AI Freeform page&quot; alt=&quot;You will land on the Vertex AI Freeform page&quot; /&gt;
&lt;p&gt;Next, you will write the prompt summarizing and categorizing a job description.&lt;/p&gt;
&lt;h3 id=&quot;the-prompt&quot; tabindex=&quot;-1&quot;&gt;The prompt &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#the-prompt&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The next task is putting in the prompt and a job description to reach our goal. For this, I selected a random software engineer job from Atlassian and used the following prompt:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;From the job description, first summarize it to less than 125 words,
then determine whether you think it is a software engineering job and
your confidence percentage.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The prompt and the job description combined are below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;From the job description, first summarize it to less than 125 words,
then determine whether you think it is a software engineering job and 
your confidence percentage.

Backend Software Engineer

Working at Atlassian
Atlassians can choose where they work – whether in an office, from home, 
or a combination of the two. That way, Atlassians have more control over 
supporting their family, personal goals, and other priorities. We can hire 
people in any country where we have a legal entity. Interviews and 
onboarding are conducted virtually, a part of being a distributed-first 
company.

With a sufficient timezone overlap with the team, we&#39;re able to hire eligible 
candidates for this role from any location in Australia and New Zealand. 
If this sparks your interest, apply today and chat with our friendly
Recruitment team further.

Atlassian is looking for talented Developers to join one of our 
Sydney engineering teams (i.e. Jira Server, Jira Cloud, Growth, etc.) 
Atlassian&#39;s engineering team is responsible for shaping the future by helping 
thousands of teams all around the world get work done. 

As a Developer well into your career, we know you&#39;re exceptional 
at what you do, but you&#39;re still eager to learn and hone in on skills 
as a developer... That&#39;s why we&#39;re placing a heavy emphasis on leaning 
on your expertise in one or more tech stacks but still learning and 
growing. We don&#39;t expect you to be an expert, but we&#39;ll sure make 
sure you get on the right path towards becoming one...

Wait, I don&#39;t have Java experience and you still want to interview me? 
That&#39;s right! At Atlassian, we hire engineers that can demonstrate 
their ability to learn and keep up with new and emerging technologies. 
It&#39;s true that Atlassian&#39;s stack is primarily written in Java and in 
the role you&#39;ll be coding primarily in Java, but we do believe in using 
the right tools for the job rather than being tied to the tool (e.g. Java).
We happen to have a variety of languages within our stack including 
Kotlin, Python, and Ruby.For the interview process, we want to 
see you at your best. This means that during the interview, we want 
you to code in whatever language you feel you&#39;re best at. This will 
give us a sense of your skills as a developer, which is all we need to make 
a proper assessment for this role.

In this role, you&#39;ll get the chance to:
Drive projects independently, from technical design to launch
Apply architectural standards and start using them on new projects
Contribute to code reviews &amp;amp; documentation as well as take on complex bug fixes
Begin writing useful technical documentation - Learn and code in Java
Mentor more junior members
Sound like an exciting opportunity? We think so too... In order to 
set you up for impact on day one, we&#39;ll expect you to have 
this on your first day:

You will not be required to know a specific programming language, 
however experience with a prominent language such as Java, 
Python, C#, C/C++, or Ruby is crucial.

Deep understanding of data structures, in particular, how they 
are implemented and how to apply them to solve problems

Passion for collaborating, tackling hard problems and not being 
afraid to ask questions
A real appetite for learning and growing, both as a developer 
and teammate.

Our perks &amp;amp; benefits
Atlassian offers a variety of perks and benefits to support you, 
your family and to help you engage with your local community. 
Our offerings include health coverage, paid volunteer days, 
wellness resources, and so much more. 

Visit go.atlassian.com/perksandbenefits to learn more.

About Atlassian

At Atlassian, we&#39;re motivated by a common goal: to unleash 
the potential of every team. Our software products help teams 
all over the planet and our solutions are designed for 
all types of work. Team collaboration through our tools 
makes what may be impossible alone, possible together.

We believe that the unique contributions of all Atlassians 
create our success. To ensure that our products and culture 
continue to incorporate everyone&#39;s perspectives and 
experience, we never discriminate based on race, 
religion, national origin, gender identity or expression, 
sexual orientation, age, or marital, veteran, or 
disability status. All your information will be kept 
confidential according to EEO guidelines.

To provide you the best experience, we can support with 
accommodations or adjustments at any stage of the 
recruitment process. Simply inform our Recruitment team 
during your conversation with them.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When pasted on the &lt;code&gt;Prompt&lt;/code&gt; box of Vertex AI freeform, it looks like the below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/controlled-generation-gemini/07prompt-and-jd.jpg&quot; loading=&quot;lazy&quot; title=&quot;Vertex AI prompt form with the prompt and a software engineer job description&quot; alt=&quot;Vertex AI prompt form with the prompt and a software engineer job description&quot; /&gt;
&lt;p&gt;You can generate a response now, but it will be a bit random. That is where setting the configs better and using the controlled generation with a schema will improve the output. Next, you will tweak the settings to make the output more predictable.&lt;/p&gt;
&lt;h3 id=&quot;using-better-settings&quot; tabindex=&quot;-1&quot;&gt;Using better settings &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#using-better-settings&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You will change the settings for a more optimized output for the summarization and categorization task. You can set the &lt;code&gt;Temperature&lt;/code&gt; at &lt;code&gt;0.2&lt;/code&gt; and the  &lt;code&gt;Output token limit&lt;/code&gt; at 4096. The &lt;code&gt;Temperature&lt;/code&gt; is the creativity or randomness you want the LLM to have in the output, and the &lt;code&gt;Output token limit&lt;/code&gt; is the output length where roughly one token is one word.&lt;/p&gt;
&lt;p&gt;As you want the LLM to be more predictable, the &lt;code&gt;Temperature&lt;/code&gt; is set to a low &lt;code&gt;0.2&lt;/code&gt;. You can even set the &lt;code&gt;Output token limit&lt;/code&gt; to 512, and it would work, but you are setting it higher just in case the LLM sends out long output. Your setting will look like the following:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/controlled-generation-gemini/08temp-output-limit.jpg&quot; loading=&quot;lazy&quot; title=&quot;Set the temparature to 0.2 and the output limit to 4096&quot; alt=&quot;Set the temparature to 0.2 and the output limit to 4096&quot; /&gt;
&lt;p&gt;You can leave the model as &lt;code&gt;gemini-2.0-flash-exp,&lt;/code&gt; as seen in the above image. Next, you will set the schema for the &lt;a href=&quot;https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/control-generated-output,t&quot;&gt;controlled generation&lt;/a&gt;, enabling structured and more predictable output.&lt;/p&gt;
&lt;h3 id=&quot;schema-for-controlled-generation&quot; tabindex=&quot;-1&quot;&gt;Schema for controlled generation &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#schema-for-controlled-generation&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To set the schema for &lt;a href=&quot;https://developers.googleblog.com/en/mastering-controlled-generation-with-gemini-15-schema-adherence/&quot;&gt;controlled generation&lt;/a&gt; with Gemini, you will need to change the &lt;code&gt;Output format&lt;/code&gt; to &lt;code&gt;JSON&lt;/code&gt; on the right panel below &lt;code&gt;Grouding&lt;/code&gt; settings as you can see below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/controlled-generation-gemini/09change-output-format.jpg&quot; loading=&quot;lazy&quot; title=&quot;Change the output format from Plain Text to JSON&quot; alt=&quot;Change the output format from Plain Text to JSON&quot; /&gt;
&lt;p&gt;After that, you will click &lt;code&gt;Edit&lt;/code&gt; beside the select box where &lt;code&gt;JSON&lt;/code&gt; is already selected for the &lt;code&gt;Output format&lt;/code&gt;. It will slide in a new overlay from the right side, and there you will paste in the schema below:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;summary&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;tech_percent&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;number&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;required&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;summary&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;tech_percent&quot;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After that, you can click apply as shown below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/controlled-generation-gemini/10set-structured-schema-controlled-generation.jpg&quot; loading=&quot;lazy&quot; title=&quot;Add the given schema to customize structure output with the controlled generation types&quot; alt=&quot;Add the given schema to customize structure output with the controlled generation types&quot; /&gt;
&lt;p&gt;Before proceeding further, let’s analyze what the schema means:&lt;/p&gt;
&lt;p&gt;First, you have put a schema of a JSON object (not an array of objects or anything else), the object has two properties, which are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;summary: it is of type string&lt;/li&gt;
&lt;li&gt;tech_percent: having the type number&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then, you specify that both properties are required in the output by adding both fields to the &lt;code&gt;required&lt;/code&gt; array. There are other types &lt;a href=&quot;https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/control-generated-output#fields&quot;&gt;supported fields&lt;/a&gt; or types from the &lt;a href=&quot;https://cloud.google.com/vertex-ai/docs/reference/rest/v1/Schema&quot;&gt;Vertex AI schema&lt;/a&gt; you can use. For example, you can use an &lt;code&gt;Enum&lt;/code&gt; with only two values, &lt;code&gt;positive&lt;/code&gt; or &lt;code&gt;negative&lt;/code&gt; if you analyze sentiment.&lt;/p&gt;
&lt;p&gt;Similarly, you can send in an array of items and expect back an array of items in a given schema like this &lt;a href=&quot;https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/control-generated-output#forecast&quot;&gt;weather forecast example&lt;/a&gt;. The possibilities are endless, if you use Gemini’s multi-modal capabilities you can even use a schema to list out the identified &lt;a href=&quot;https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/control-generated-output#identify&quot;&gt;objects&lt;/a&gt; in an image. It would be advisable to thoroughly read that &lt;a href=&quot;https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/control-generated-output&quot;&gt;official document&lt;/a&gt;. You can also use Google AI Studio for a visual editor for the structured output schema.&lt;/p&gt;
&lt;p&gt;Next, we will test the output on the Vertex AI interface.&lt;/p&gt;
&lt;h3 id=&quot;test-it&quot; tabindex=&quot;-1&quot;&gt;Test it &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#test-it&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To test the output and if it adheres to the defined schema, you can hit the &lt;code&gt;play&lt;/code&gt; or &lt;code&gt;generate&lt;/code&gt; button and check the output as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/controlled-generation-gemini/11test-output-sw-eng.jpg&quot; loading=&quot;lazy&quot; title=&quot;Test the summary and categorization for the software engineer job&quot; alt=&quot;Test the summary and categorization for the software engineer job&quot; /&gt;
&lt;p&gt;As you can see, it works well, and the output adheres to the given schema. The output I got was the following:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;summary&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Atlassian is hiring a Backend Software Engineer to join their Sydney team. The role involves driving projects, applying architectural standards, contributing to code reviews, and mentoring junior members. While Java is the primary language, experience with other languages is valued. They emphasize learning and growth, and want to see candidates code in their preferred language during interviews. The company offers flexible work arrangements and various benefits. They value diversity and inclusion.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;tech_percent&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;95.0&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To ensure it works fine with non-tech jobs, I tested it with a &lt;code&gt;Sales&lt;/code&gt; jobs description and ran the generation. It rightly guessed that with was only 10% of technical/software engineering related:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/controlled-generation-gemini/12test-output-sales.jpg&quot; loading=&quot;lazy&quot; title=&quot;Test the summary and categorization for a sales executive job description&quot; alt=&quot;Test the summary and categorization for a sales executive job description&quot; /&gt;
&lt;p&gt;You can switch back to the previous job description of a &lt;code&gt;Backend Software Engineer&lt;/code&gt; and proceed. If you try it multiple times you might the quota error:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;Error message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Online prediction request quota exceeded for gemini-experimental. Please try again later with backoff.&#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token literal-property property&quot;&gt;Status&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;429&lt;/span&gt; Error code&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can use a different model like the &lt;code&gt;gemini-1.5-pro-002&lt;/code&gt; to overcome this error. You can also ask for an increase in the &lt;a href=&quot;https://cloud.google.com/vertex-ai/generative-ai/docs/quotas&quot;&gt;Vertex AI quota&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;generate-code&quot; tabindex=&quot;-1&quot;&gt;Generate code &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#generate-code&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To generate a code for what you have done, click the &lt;code&gt;Get Code&lt;/code&gt; link on the right sidebar beside the &lt;code&gt;Save&lt;/code&gt; button:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/controlled-generation-gemini/13get-code-link.jpg&quot; loading=&quot;lazy&quot; title=&quot;The link to get code beside the Save button&quot; alt=&quot;The link to get code beside the Save button&quot; /&gt;
&lt;p&gt;It will show a working Python code as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/controlled-generation-gemini/14generated-python-code.jpg&quot; loading=&quot;lazy&quot; title=&quot;You can get generated python code that you can try out with Google Cloud Shell and Cloud Shell editor or on your local machine&quot; alt=&quot;You can get generated python code that you can try out with Google Cloud Shell and Cloud Shell editor or on your local machine&quot; /&gt;
&lt;p&gt;Click &#39; Close &#39; to close the overlay. When the call is finished, you can analyze the code&#39;s &lt;code&gt;response_schema&lt;/code&gt; parameter, which will have the schema you defined in the previous step.&lt;/p&gt;
&lt;p&gt;You can copy and run the generated Python code on Google Cloud Shell, editing the file &lt;a href=&quot;https://geshan.com.np/blog/2024/01/cloud-shell-editor/&quot;&gt;Cloud Shell editor&lt;/a&gt;, there is an example of that in this &lt;a href=&quot;https://geshan.com.np/blog/2024/04/gemini-ecommerce-product-description-generator/#run-generated-python-code&quot;&gt;tutorial&lt;/a&gt;. You can also run it as a &lt;a href=&quot;https://colab.google/notebooks/&quot;&gt;Google Collab Notebook&lt;/a&gt; by clicking the &lt;code&gt;Open Notebook&lt;/code&gt; button.&lt;/p&gt;
&lt;p&gt;As this tutorial is focused on &lt;code&gt;controlled generation,&lt;/code&gt; we will not explore running the code further. However, you can add other layers to the generated code as needed. For example, you can create an API with &lt;a href=&quot;https://fastapi.tiangolo.com/&quot;&gt;FastAPI&lt;/a&gt; or have a running app with a helpful UI using &lt;a href=&quot;https://streamlit.io/&quot;&gt;Streamlit&lt;/a&gt; or Google’s &lt;a href=&quot;https://google.github.io/mesop/&quot;&gt;Mesop&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Coming back to the use case, I would have directly called the Gemini API for each or multiple job posts in the single call as Gemini 2.0 flash exp has a 1 million tokens context window and got the summary in batches of 100 or 200 jobs. In the above example, each job took 900-1000 tokens, which would work well. I would also consider the cost associated with it.&lt;/p&gt;
&lt;p&gt;Nothing will change visually for the user; however, this enhancement will significantly improve the output quality.&lt;/p&gt;
&lt;p&gt;You can also try the official &lt;a href=&quot;https://github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/controlled-generation/intro_controlled_generation.ipynb&quot;&gt;controlled generation tutorial&lt;/a&gt; over Google Collab.&lt;/p&gt;
&lt;p&gt;This blog post has been written as part of #VertexAISprint, and Google Cloud credits are provided for this project.&lt;/p&gt;
&lt;h2 id=&quot;controlled-generation-is-useful&quot; tabindex=&quot;-1&quot;&gt;Controlled generation is useful &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#controlled-generation-is-useful&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Controlled generation is helpful as the LLM will reply in &lt;code&gt;JSON,&lt;/code&gt; which is much better for machines interacting with LLMs. Given the LLM will adhere to the schema, it makes it much easier as the output is structured, and with the required fields, you can expect the fields to to be there in the JSON output.&lt;/p&gt;
&lt;p&gt;Also, the output does not sway in other directions; as you saw in the above example, the &lt;code&gt;tech_precent&lt;/code&gt; value was rightly guessed at 95% for the backend software engineer, and it came down to 10% for a sales role’s job description.&lt;/p&gt;
&lt;p&gt;It will not reduce the hallucination or the non-deterministic nature of LLM’s output, but it can add the needed structure to the output, making it much easier for machines or API clients to read it.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/controlled-generation-gemini/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You saw a real-life example of how Gemini can replace older methods of summarizing and categorizing. Staring with a use case, you built a compelling and working proof of concept using Gemini over Vertex AI. You wrote a good prompt, tweaked the optimal output configs, and used a schema object with two required fields for controlled generation and structured output. You also learned why and how controlled generation is helpful. I hope you learned something new from this guide and continue learning more about LLMs and Gen AI. Keep learning!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to run (any) open LLM with Ollama on Google Cloud Run [Step-by-step]</title>
		<link href="https://geshan.com.np/blog/2025/01/ollama-google-cloud-run/"/>
		<updated>2025-01-20T11:34:52Z</updated>
		<id>https://geshan.com.np/blog/2025/01/ollama-google-cloud-run/</id>
		<content type="html">&lt;p&gt;Ollama is a great way to run many open Large Language Models (LLMs). You can run Google Gemma 2, Phi 4, Mistral, and Llama 3 on your machine or the cloud with &lt;a href=&quot;https://ollama.com/&quot;&gt;Ollama&lt;/a&gt;. You can also host these open LLMs as APIs using Ollama. In this post, you will learn how to host Gemma 2 (2b) with Ollama 0.5.x on Google Cloud Run; let’s get started!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/01ollama-google-cloud-run.jpg&quot; title=&quot;How to run (any) open LLM with Ollama on Google Cloud Run [Step-by-step]&quot; alt=&quot;How to run (any) open LLM with Ollama on Google Cloud Run [Step-by-step]&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/ollama-google-cloud-run/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/01/ollama-google-cloud-run/#why-google-cloud-run&quot;&gt;Why Google Cloud Run&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/01/ollama-google-cloud-run/#create-a-gcs-bucket&quot;&gt;Create a GCS bucket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/01/ollama-google-cloud-run/#deploy-ollama-on-google-cloud-run&quot;&gt;Deploy Ollama on Google Cloud Run&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/01/ollama-google-cloud-run/#wire-up-gsc-bucket-as-a-cloud-run-volume&quot;&gt;Wire up GSC bucket as a Cloud Run Volume&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2025/01/ollama-google-cloud-run/#testing-gemma-2-with-ollama-on-google-cloud-console&quot;&gt;Testing Gemma 2 with Ollama on Google Cloud Console&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Conclusion[#conclusion]&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;why-google-cloud-run&quot; tabindex=&quot;-1&quot;&gt;Why Google Cloud Run &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/ollama-google-cloud-run/#why-google-cloud-run&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Good question; I have written multiple &lt;a href=&quot;https://geshan.com.np/blog/categories/google-cloud-run/&quot;&gt;blog posts&lt;/a&gt; about Google Cloud Run and also given a couple of &lt;a href=&quot;https://geshan.com.np/blog/2019/11/from-0-to-working-serverless-url-for-a-containerized-app-with-google-cloud-run-slides-and-video/&quot;&gt;talks&lt;/a&gt; in the past years, Some great &lt;a href=&quot;https://geshan.com.np/blog/2019/11/why-use-google-cloud-run-5-compelling-reasons/&quot;&gt;reasons&lt;/a&gt; to use Google Cloud Run to host open LLMs with &lt;a href=&quot;https://geshan.com.np/blog/2023/04/serverless-containers/&quot;&gt;serverless containers&lt;/a&gt; are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The resources (like CPU, memory, and even GPU) are allocated in a serverless way. Meaning you only pay for the time you use it.&lt;/li&gt;
&lt;li&gt;You don’t need to send data out of your &lt;a href=&quot;https://cloud.google.com/vpc?hl=en&quot;&gt;VPC&lt;/a&gt;, putting security first&lt;/li&gt;
&lt;li&gt;More cost control without counting tokens, as the LLMs are self-hosted; you can define how the resources are allocated rather than just counting the number of tokens sent and received.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that that&#39;s out of the way let’s access the Google Cloud Console and deploy Gemma 2 (2b—2 billion parameters) on Google Cloud Run.&lt;/p&gt;
&lt;h2 id=&quot;create-a-gcs-bucket&quot; tabindex=&quot;-1&quot;&gt;Create a GCS bucket &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/ollama-google-cloud-run/#create-a-gcs-bucket&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, you will need an existing Project on Google Cloud, or you can create a &lt;a href=&quot;https://console.cloud.google.com/projectcrea&quot;&gt;new project&lt;/a&gt;. For this tutorial, we will assume that you have a new(ish) project. Since the project has already been selected, you will create a new Google Cloud Storage (GCS) bucket. You are creating a GCS bucket to store the files needed for the open LLM, which is Gemma2 2b in the case of this guide.&lt;/p&gt;
&lt;p&gt;To create a new bucket, search for &lt;code&gt;bucket&lt;/code&gt; on the search bar:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/02search-buckets.jpg&quot; loading=&quot;lazy&quot; title=&quot;Search for a bucket on Google Cloud Console search bar&quot; alt=&quot;Search for bucket on Google Cloud Console search bar&quot; /&gt;
&lt;p&gt;Then select the &lt;code&gt;Buckets&lt;/code&gt; option, as shown above. Then click the &lt;code&gt;+ Create&lt;/code&gt; option on the “Buckets” page:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/03create-bucket-button.jpg&quot; loading=&quot;lazy&quot; title=&quot;Click on the Create bucket button on the GCS buckets page&quot; alt=&quot;Click on the Create bucket button on the GCS buckets page&quot; /&gt;
&lt;p&gt;After that, name the bucket something unique, like &lt;code&gt;ollama-gemma2-2b-xyz.&lt;/code&gt;. All buckets across GCP have unique names, so you might need a suffix. Then click the down arrow beside &lt;code&gt;Optimize storage for data-intensive workloads&lt;/code&gt; and check the &lt;code&gt;Enable Hierarchical namespace on this bucket&lt;/code&gt; checkbox as shown below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/04name-the-bucket.jpg&quot; loading=&quot;lazy&quot; title=&quot;Name the bucket and enable hierarchical namespace&quot; alt=&quot;Name the bucket and enable hierarchical namespace&quot; /&gt;
&lt;p&gt;This will help optimize the LLM access later. After that, select the bucket to be a  single region and the &lt;code&gt;Region&lt;/code&gt; as &lt;code&gt;us-central1 (Iowa)&lt;/code&gt; as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/05select-bucket-region.jpg&quot; loading=&quot;lazy&quot; title=&quot;Make it single region bucket and select us-central1 region&quot; alt=&quot;Make it single region bucket and select us-central1 region&quot; /&gt;
&lt;p&gt;Then click &lt;code&gt;Continue&lt;/code&gt;. Next, keep the &lt;code&gt;Storage Class&lt;/code&gt; as &lt;code&gt;Standard&lt;/code&gt; and then click &lt;code&gt;Continue&lt;/code&gt;:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/06select-standard-bucket.jpg&quot; loading=&quot;lazy&quot; title=&quot;Make it a standard bucket class&quot; alt=&quot;Make it a standard bucket class&quot; /&gt;
&lt;p&gt;After that, let the access control be on the bucket level (not &lt;code&gt;Fine-grained&lt;/code&gt; ) and click &lt;code&gt;Continue&lt;/code&gt;:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/07bucket-access-control.jpg&quot; loading=&quot;lazy&quot; title=&quot;Make the bucket a uniform access control one, not fine grained access control&quot; alt=&quot;Make the bucket a uniform access control one, not fine grained access control&quot; /&gt;
&lt;p&gt;Then, keep the data protection policy as shown below, and click &lt;code&gt;Create&lt;/code&gt; to create the bucket.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/08bucket-create.jpg&quot; loading=&quot;lazy&quot; title=&quot;Keep the soft delete policy and create the bucket&quot; alt=&quot;Keep the soft delete policy and create the bucket&quot; /&gt;
&lt;p&gt;Next, it will ask you to confirm the access as below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/09bucket-create-confirm.jpg&quot; loading=&quot;lazy&quot; title=&quot;Confirm the bucket creation&quot; alt=&quot;Confirm the bucket creation&quot; /&gt;
&lt;p&gt;Click &lt;code&gt;Confirm&lt;/code&gt;. It will take some time, but the bucket will be created, which will look like the below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/10bucket-created.jpg&quot; loading=&quot;lazy&quot; title=&quot;The bucket to store the Gemma 2:2b LLM and Ollama files has been created&quot; alt=&quot;The bucket to store the Gemma 2:2b LLM and Ollama files has been created&quot; /&gt;
&lt;p&gt;After the bucket is created, the next task is to deploy Ollama on Google Cloud Run.&lt;/p&gt;
&lt;h2 id=&quot;deploy-ollama-on-google-cloud-run&quot; tabindex=&quot;-1&quot;&gt;Deploy Ollama on Google Cloud Run &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/ollama-google-cloud-run/#deploy-ollama-on-google-cloud-run&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To deploy Ollama on Google Cloud Run, search for &lt;code&gt;cloud run&lt;/code&gt; on the search bar:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/11search-cloud-run.jpg&quot; loading=&quot;lazy&quot; title=&quot;Serach for cloud run on the GCP console search bar&quot; alt=&quot;Serach for cloud run on the GCP console search bar&quot; /&gt;
&lt;p&gt;Then click &lt;code&gt;Cloud Run&lt;/code&gt; to go to the Cloud Run page. On that page, click on &lt;code&gt;Deploy Container&lt;/code&gt; and then click on &lt;code&gt;Service&lt;/code&gt; as shown below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/12add-cloud-run-service.jpg&quot; loading=&quot;lazy&quot; title=&quot;Add a cloud run service on the Cloud Run service listing page&quot; alt=&quot;Add a cloud run service on the Cloud Run service listing page&quot; /&gt;
&lt;p&gt;You will do all the important configurations on this page, so be careful. You will need to fill up the form as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In the &lt;code&gt;Container image URL&lt;/code&gt; type in &lt;code&gt;ollama/ollama:0.5.7&lt;/code&gt; - at the time of writing, &lt;code&gt;0.5.7&lt;/code&gt; is the latest release and available as an image on &lt;a href=&quot;https://hub.docker.com/r/ollama/ollama&quot;&gt;DockerHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;In the service name, type in &lt;code&gt;ollama-gcs&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Make sure the region is the same as the bucket, which is &lt;code&gt;us-central1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;For now, select &lt;code&gt;Allow unauthenticated invocations&lt;/code&gt;. This will make it accessible to anyone on the web, but we are doing it for the sake of this demo. In a real-life scenario, you would put it behind authentication.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Till now, the form will look like the below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/13cloud-run-container-settings.jpg&quot; loading=&quot;lazy&quot; title=&quot;Point Cloud Run to use Ollama version 0.5.7 on Docker hub and use us-centra1 as the region&quot; alt=&quot;Point Cloud Run to use Ollama version 0.5.7 on Docker hub and use us-centra1 as the region&quot; /&gt;
&lt;p&gt;Then, for billing select &lt;code&gt;Instance-based&lt;/code&gt; and keep the &lt;code&gt;Minimum number of instances&lt;/code&gt; to 0. This makes it serverless. When no requests are coming in, no instances will be up and running, saving you money. After that, select the &lt;code&gt;Ingerss&lt;/code&gt; to be &lt;code&gt;All&lt;/code&gt; so that it allows traffic from the internet. At this point, your form will look as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/14cloud-run-billing.jpg&quot; loading=&quot;lazy&quot; title=&quot;Select instance based billing, set minimum instances to 0 and ingress to All&quot; alt=&quot;Select instance based billing, set minimum instances to 0 and ingress to All&quot; /&gt;
&lt;p&gt;Next, you will link the GCS bucket as a Cloud Run volume.&lt;/p&gt;
&lt;h3 id=&quot;wire-up-gsc-bucket-as-a-cloud-run-volume&quot; tabindex=&quot;-1&quot;&gt;Wire up GSC bucket as a Cloud Run Volume &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/ollama-google-cloud-run/#wire-up-gsc-bucket-as-a-cloud-run-volume&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is an important part where you will link up the Google Cloud Storage (GCS) bucket created in the previous part as a volume for Google Cloud Run Containers. Click the volumes tab on the &lt;code&gt;Container(s), Volumes, Networking, Security&lt;/code&gt; part:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/15cloud-run-volumes-tab.jpg&quot; loading=&quot;lazy&quot; title=&quot;Click the Cloud Run - Volumes tab&quot; alt=&quot;Click the Cloud Run - Volumes tab&quot; /&gt;
&lt;p&gt;Then click &lt;code&gt;Add Volume&lt;/code&gt; and select the &lt;code&gt;Volume type&lt;/code&gt; as &lt;code&gt;Cloud Storage Bucket&lt;/code&gt;. Let the name be &lt;code&gt;gcs-1&lt;/code&gt;, and then for the &lt;code&gt;Bucket&lt;/code&gt; click &lt;code&gt;Browse&lt;/code&gt; and select the bucket you created in the previous step, which will be named something like &lt;code&gt;olllama-gemma2-2b-xyz&lt;/code&gt;. Then click &lt;code&gt;Select&lt;/code&gt;, at this point, the form will look like the below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/16cloud-run-volume-gcs.jpg&quot; loading=&quot;lazy&quot; title=&quot;Link the GCS bucket created in the previous step as volume named gcs-1&quot; alt=&quot;Link the GCS bucket created in the previous step as volume named gcs-1&quot; /&gt;
&lt;p&gt;Leave the &lt;code&gt;Read-only&lt;/code&gt; checkbox unchecked, as the Cloud Run instances will write files to this bucket. Then click &lt;code&gt;Done&lt;/code&gt;. It will say the bucket is &lt;code&gt;Not mounted&lt;/code&gt; , which is fine.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/17cloud-run-not-mounted.jpg&quot; loading=&quot;lazy&quot; title=&quot;Cloud Run GCS volume linked but not mounted&quot; alt=&quot;Cloud Run GCS volume linked but not mounted&quot; /&gt;
&lt;p&gt;After that, click the &lt;code&gt;Go to container(s) tab&lt;/code&gt; or the &lt;code&gt;Container(s)&lt;/code&gt; tab; on this tab, click the &lt;code&gt;Volume mounts&lt;/code&gt; sub-tab, then click &lt;code&gt;Mount Volume&lt;/code&gt;. Next, select the &lt;code&gt;Name-1&lt;/code&gt; as &lt;code&gt;gcs-1&lt;/code&gt; and on the &lt;code&gt;Mount path 1&lt;/code&gt; type in &lt;code&gt;/root/.ollama&lt;/code&gt;  (don’t miss the &lt;code&gt;.&lt;/code&gt; in front of ollama); this is where Ollama stores its models. So when the models are pulled (downloaded), they will be saved in this volume, which will also be saved in the bucket. It can be used in other instances as it is in the bucket.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/18cloud-run-mount-volume.jpg&quot; loading=&quot;lazy&quot; title=&quot;Mount gcs-1 volume at /root/.ollama path&quot; alt=&quot;Mount gcs-1 volume at /root/.ollama path&quot; /&gt;
&lt;p&gt;Then click &lt;code&gt;Done&lt;/code&gt;. You will set some environment variables for the container next. Click &lt;code&gt;Container: ollama-1&lt;/code&gt; under the &lt;code&gt;Containers&lt;/code&gt; tab to do this. Then click the &lt;code&gt;Variables and Secrets&lt;/code&gt; sub-tab; after that, click &lt;code&gt;Add Variable&lt;/code&gt;, and fill up the following in &lt;code&gt;Name 1&lt;/code&gt; and &lt;code&gt;Value 1&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;OLLAMA_HOST&lt;/code&gt; with value &lt;code&gt;0.0.0.0:8080&lt;/code&gt; – this will make Ollama run on port 8080, not the default port of &lt;code&gt;11434&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Similarly, add three more variables using the &lt;code&gt;Add Variable&lt;/code&gt; button and fill up the following values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;OLLAMA_DEBUG&lt;/code&gt; with value &lt;code&gt;false&lt;/code&gt; – this is self-explanatory&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OLLAMA_KEEP_ALIVE&lt;/code&gt; with value &lt;code&gt;-1&lt;/code&gt; – it keeps the model weight on the GPU (if GPU is used)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GIN_MODE&lt;/code&gt; with value &lt;code&gt;release&lt;/code&gt; – is to remove any &lt;a href=&quot;https://github.com/gin-gonic/gin&quot;&gt;Go Gin&lt;/a&gt; debug-related message. Ollama uses &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/server/routes.go#L43&quot;&gt;Gin&lt;/a&gt; under the hood,&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Your &lt;code&gt;Variables and Secrets&lt;/code&gt; section will look like the below when you are done:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/19cloud-run-variables.jpg&quot; loading=&quot;lazy&quot; title=&quot;Set all 4 needed variables of Ollama for Cloud Run&quot; alt=&quot;Set all 4 needed variables of Ollama for Cloud Run&quot; /&gt;
&lt;p&gt;After that, click the &lt;code&gt;Settings&lt;/code&gt; tab and set the &lt;code&gt;Memory&lt;/code&gt; to &lt;code&gt;32 GiB&lt;/code&gt; and the &lt;code&gt;CPU&lt;/code&gt; to &lt;code&gt;8&lt;/code&gt;. You can request GPU access for your project by clicking the &lt;code&gt;GPU quota&lt;/code&gt; link and filling out a form. Gemma 2 on Ollama will run (a bit slower, though) without the GPU.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/20cloud-run-resources.jpg&quot; loading=&quot;lazy&quot; title=&quot;Set Port for Cloud Run to 8080 and allocate 32 GB of memory and 8 CPUs&quot; alt=&quot;Set Port for Cloud Run to 8080 and allocate 32 GB of memory and 8 CPUs&quot; /&gt;
&lt;p&gt;Your &lt;code&gt;Setting&lt;/code&gt; section will look like the above when you are done editing it; after that, you can click &lt;code&gt;Done&lt;/code&gt;. If you cannot allocate 32 GB of memory and 8 CPUs it might be because your account is new; you can reqeust a &lt;a href=&quot;https://cloud.google.com/run/quotas#increase&quot;&gt;quota increase&lt;/a&gt;. Even with 512 MB of memory and 1 CPU, which you should have without a quota increase, you can run the &lt;a href=&quot;https://ollama.com/library/smollm2:135m&quot;&gt;smollm2:135m&lt;/a&gt; at 135 million parameters; the model is 271 MB, which will fit in the 512 MB allocated memory.&lt;/p&gt;
&lt;p&gt;Then, move on to the &lt;code&gt;Requests&lt;/code&gt; section. Here, you can set the &lt;code&gt;Request timeout&lt;/code&gt; to &lt;code&gt;300&lt;/code&gt; seconds  (5 minutes), the default value, and keep the&lt;br /&gt;
&lt;code&gt;Maximum concurrent requests per instance&lt;/code&gt; at &lt;code&gt;80&lt;/code&gt;. Keep the &lt;code&gt;Minimum number of instances&lt;/code&gt; as &lt;code&gt;0&lt;/code&gt;; the only value you should change will be &lt;code&gt;Maximum number of instances&lt;/code&gt;; keep it at 3 or 4 maximum. If someone attacks your service, it should timeout or send back a server error, then scale a lot, costing you loads of money. Your Cloud Run service creation form will look like the below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/21cloud-run-instances.jpg&quot; loading=&quot;lazy&quot; title=&quot;Set Port for Cloud Run timeout, max concurrency and min and max number of instances&quot; alt=&quot;Set Port for Cloud Run timeout, max concurrency and min and max number of instances&quot; /&gt;
&lt;p&gt;Then click &lt;code&gt;Create&lt;/code&gt; and wait for some time as the &lt;code&gt;Ollama&lt;/code&gt; image is 1.5 GB, it will take a bit to start. It will look like the following when it is deploying:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/22cloud-run-creating.jpg&quot; loading=&quot;lazy&quot; title=&quot;Cloud run creating the Ollama service&quot; alt=&quot;Cloud run creating the Ollama service&quot; /&gt;
&lt;p&gt;It will look like the below after it is deployed successfully:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/23cloud-run-created.jpg&quot; loading=&quot;lazy&quot; title=&quot;Cloud Run Service with Ollama created successfully and has a working URL now&quot; alt=&quot;Cloud Run Service with Ollama created successfully and has a working URL now&quot; /&gt;
&lt;p&gt;Click the service URL to see if it is working:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/24cloud-run-ollama-up.jpg&quot; loading=&quot;lazy&quot; title=&quot;Ollama server is running on Cloud Run without any models&quot; alt=&quot;Ollama server is running on Cloud Run without any models&quot; /&gt;
&lt;p&gt;It will show &lt;code&gt;Ollama is running&lt;/code&gt; as above if everything went fine. At this point, Ollama has no models to run any inference. So, in the next section, you will pull in and test Gemma 2:2b with Ollama using the Google Cloud Console. Gemma 2 will be the first model for this instance of Ollama.&lt;/p&gt;
&lt;h2 id=&quot;testing-gemma-2-with-ollama-on-google-cloud-console&quot; tabindex=&quot;-1&quot;&gt;Testing Gemma 2 with Ollama on Google Cloud Console &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/ollama-google-cloud-run/#testing-gemma-2-with-ollama-on-google-cloud-console&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To test Gemma2 (or any other &lt;a href=&quot;https://ollama.com/search&quot;&gt;model&lt;/a&gt; that can run on Ollama), go back to the Google Cloud Console on the Cloud Run service page and click the Cloud Shell button (or hit G and then S on your keyboard). This will open the &lt;a href=&quot;https://cloud.google.com/shell/docs/using-cloud-shell&quot;&gt;Google Cloud Shell&lt;/a&gt; terminal.&lt;/p&gt;
&lt;p&gt;On the terminal, type &lt;code&gt;curl -fsSL https://ollama.com/install.sh | sh&lt;/code&gt; to install Ollama; it has been taken from the Ollama Linux installation &lt;a href=&quot;https://ollama.com/download/linux&quot;&gt;page&lt;/a&gt;. Let it execute, and it will show an output like the one below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/25ollama-install.jpg&quot; loading=&quot;lazy&quot; title=&quot;Install Ollama on Google Cloud console with the script from the official website&quot; alt=&quot;Install Ollama on Google Cloud console with the script from the official website&quot; /&gt;
&lt;p&gt;Then, copy the URL of your service, which will be something like &lt;code&gt;https://ollama-gcs-&amp;lt;some-number-here&amp;gt;.us-central1.run.app&lt;/code&gt;. You can use the copy icon beside the URL. After that, execute the following command on your terminal:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;OLLAMA_HOST&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;copied-url&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; ollama run gemma2:2b&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will download (pull) Gemma 2:2b and save it in the GCS bucket (a linked volume), and then you can chat with Gemma 2:2b. You can ask &lt;code&gt;who are you and Gemma will reply&lt;/code&gt;:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/26ollama-use-gemma2.jpg&quot; loading=&quot;lazy&quot; title=&quot;Use Gemma 2 2B params with Ollama installed on Google Cloud Console&quot; alt=&quot;Use Gemma 2 2B params with Ollama installed on Google Cloud Console&quot; /&gt;
&lt;p&gt;You can download/pull any other model Ollama supports and start using it. For example, you can download &lt;code&gt;llama3.3:70b&lt;/code&gt; by Meta, &lt;code&gt;phi4:14b&lt;/code&gt; by Microsoft, &lt;code&gt;deepseek-r1:8b&lt;/code&gt; by &lt;a href=&quot;https://api-docs.deepseek.com/news/news250120&quot;&gt;DeepSeek&lt;/a&gt; (which is getting very popular), or even &lt;code&gt;smollam2:135m&lt;/code&gt;, which is only 271 MB in size compared to other models, which are GBs in size.&lt;/p&gt;
&lt;p&gt;You can type &lt;code&gt;/bye&lt;/code&gt; to get out of the ollama CLI. Now, as Gemma 2:2b is downloaded, you can also send a cURL command to test it out like the one below:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-i&lt;/span&gt; https://ollama-gcs-&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;some-number-here&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;.us-central1.run.app/api/generate &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{&lt;br /&gt;  &quot;model&quot;: &quot;gemma2:2b&quot;,&lt;br /&gt;  &quot;prompt&quot;: &quot;Why is the sky blue? Give the shortest answer possible&quot;,&lt;br /&gt;  &quot;stream&quot;: false&lt;br /&gt;}&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will give an output as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/27ollama-curl.jpg&quot; loading=&quot;lazy&quot; title=&quot;Use Gemma 2 2B params with Ollama using a cURL POST on the generate API endpoint&quot; alt=&quot;Use Gemma 2 2B params with Ollama using a cURL POST on the generate API endpoint&quot; /&gt;
&lt;p&gt;If you go in the bucket and look at its contents, you will find Gemma 2 there:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/ollama-google-cloud-run/28ollama-gemma-gcs.jpg&quot; loading=&quot;lazy&quot; title=&quot;Gemma 2 2B files in the Google Cloud Storage bucket created in the first step&quot; alt=&quot;Gemma 2 2B files in the Google Cloud Storage bucket created in the first step&quot; /&gt;
&lt;p&gt;Google Cloud Run makes it easy to run any LLM on Ollama. You can run Phi 4, Llama 3, or any other model; you must pull it and run your command or POST with curl. You can also use libraries like &lt;a href=&quot;https://www.litellm.ai/&quot;&gt;LiteLLM&lt;/a&gt; to use the model in your apps using Ollama’s &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md&quot;&gt;APIs&lt;/a&gt;. Please explore Ollama more on your own. You can also use &lt;a href=&quot;https://github.com/open-webui/open-webui&quot;&gt;Open WebUI&lt;/a&gt; to have a GUI on top of Oallma running Gemma 2 LLM.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2025/01/ollama-google-cloud-run/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It is easy to run any LLM with Ollama on Google Cloud Run. Be careful of the access as Ollama APIs allow pulling models and even &lt;a href=&quot;https://github.com/ollama/ollama/blob/main/docs/api.md#delete-a-model&quot;&gt;deleting&lt;/a&gt; them. With Cloud Run, you will only pay for the resources when you use it, which makes it ideal for experiments. I hope you learned something new from this post and keep experimenting.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Recap 2024: Public Speaking, blogging, interviews, tech community work and other things</title>
		<link href="https://geshan.com.np/blog/2024/12/recap-2024/"/>
		<updated>2024-12-20T10:27:45Z</updated>
		<id>https://geshan.com.np/blog/2024/12/recap-2024/</id>
		<content type="html">&lt;p&gt;I started writing the year-in-review (recap) posts from &lt;a href=&quot;https://geshan.com.np/blog/2019/12/2019-year-in-review/&quot;&gt;2019&lt;/a&gt;, so this will be the sixth consecutive year I will write a yearly recap. Taking some time to reflect on things accomplished this year from a professional point of view, I think it will be a good rear mirror view to look back at 2024; let’s dive in!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;figure&gt;
  &lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/recap-2024/01recap-2024.jpg&quot; title=&quot;Recap 2024: Public Speaking, blogging, interviews, tech community work and other things&quot; alt=&quot;Recap 2024: Public Speaking, blogging, interviews, tech community work and other things&quot; /&gt;
  &lt;figcaption&gt;A motorcycle rear view mirror background image generated using Image FX (Imagen 3)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#highlights&quot;&gt;Highlights&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#public-speaking-in-2024&quot;&gt;Public speaking in 2024&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#blog-posts-of-2024&quot;&gt;Blog posts of 2024&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#most-viewed-blog-posts-of-2024&quot;&gt;Most viewed blog posts of 2024&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#podcasts%2Finterviews-this-year&quot;&gt;Podcasts/Interviews this year&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#community-activities&quot;&gt;Community activities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#became-a-docker-captain&quot;&gt;Became a Docker Captain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#developer-ambassador-programs-repo&quot;&gt;Developer ambassador programs repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#listening-to-podcasts&quot;&gt;Listening to Podcasts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#misc&quot;&gt;Misc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;highlights&quot; tabindex=&quot;-1&quot;&gt;Highlights &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#highlights&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Below are the major highlights of 2024 from a professional (and tech) lens:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I did seven public talks/workshops this year, all in person and one technical talk at work. In addition to Sydney, I gave talks in &lt;a href=&quot;https://gdg.community.dev/events/details/google-gdg-adelaide-presents-google-io-extended-adelaide/&quot;&gt;Adelaide&lt;/a&gt;, &lt;a href=&quot;https://gdg.community.dev/events/details/google-gdg-hobart-presents-gdg-hobart-devfest-2024/&quot;&gt;Hobart&lt;/a&gt;, and &lt;a href=&quot;https://devfest.gdgauckland.nz/#schedule&quot;&gt;Auckland, New Zealand&lt;/a&gt; too.&lt;/li&gt;
&lt;li&gt;Similar to the past couple of years, I have written 25+1 (this recap) blog posts this year. In this blog, the number of users has decreased by 45% compared to 2023, thanks to us technologists  using (or dare I say overusing) LLMs. I have also written one blog post about &lt;a href=&quot;https://medium.com/simplywallst/feature-flags-the-gateway-we-used-to-achieve-smoother-software-releases-03c159eba9f8&quot;&gt;Feature flags&lt;/a&gt; for the Simply Wall St. tech blog.&lt;/li&gt;
&lt;li&gt;I was a guest in two podcasts this year, one for the &lt;a href=&quot;https://stackoverflow.blog/2024/08/23/evolution-backend-engineering-php-javascript-kubernetes-containers/&quot;&gt;StackOverflow Podcast&lt;/a&gt; released in August and another one for &lt;a href=&quot;https://www.youtube.com/watch?v=FsyEumavo_k&quot;&gt;The Doers Nepal&lt;/a&gt; (in Nepali language) which released in September.&lt;/li&gt;
&lt;li&gt;Helped re-establish &lt;a href=&quot;https://gdg.community.dev/gdg-perth/&quot;&gt;GDG Perth&lt;/a&gt; and contributed to organizing 11 meetups for &lt;a href=&quot;https://gdg.community.dev/gdg-cloud-sydney/&quot;&gt;GDG Cloud Sydney&lt;/a&gt; and two conferences: Google I/O Extended Sydney and DevFest Sydney this year. I also moderated two AI-related panel discussions at both conferences mentioned above.&lt;/li&gt;
&lt;li&gt;I also helped groom five new female tech speakers, most of them “debuted” with their talks at DevFest Sydney.&lt;/li&gt;
&lt;li&gt;My Docker Captain application was approved towards the end of June this year, and I became a &lt;a href=&quot;https://www.docker.com/captains/geshan-manandhar/&quot;&gt;Docker Captain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;I have listened to 225 hours of podcasts this year (9 days and 9 hours), equating to almost 37 minutes daily (225 hours /365 days). I will have proof later. The top three are Changelog (master feed), Stack Overflow Podcast, and PodRocket.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This year, I traveled to the US and Nepal (after 6.5 years), which was a good experience. Let’s discuss some of the details from the above highlights next.&lt;/p&gt;
&lt;h2 id=&quot;public-speaking-in-2024&quot; tabindex=&quot;-1&quot;&gt;Public speaking in 2024 &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#public-speaking-in-2024&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I wrote one talk about &lt;a href=&quot;https://docs.google.com/presentation/d/15UaZqOV41dnjnarWUmqsvnFQdTjkEpBCDM4RgDMDoNk/edit?usp=sharing&quot;&gt;Serverless Conatiners&lt;/a&gt; and one workshop titled &lt;a href=&quot;https://docs.google.com/presentation/d/1WboHu9zHIQLoiW_RO20KXLQb6twLdGLBNy_e3iadk94/edit?usp=sharing&quot;&gt;How to build an E-commerce product description generator using Gemini&lt;/a&gt;. I gave the talk at two meetups and also at Adelaide and Auckland. I did the workshop in Sydney for &lt;a href=&quot;https://gdg.community.dev/events/details/google-gdg-sydney-presents-build-with-ai-workshop/cohost-gdg-cloud-sydney&quot;&gt;Build with AI Sydney 2024&lt;/a&gt; at Google Sydney office and for &lt;a href=&quot;https://gdg.community.dev/events/details/google-gdg-hobart-presents-gdg-hobart-devfest-2024/&quot;&gt;DevFest Hobart&lt;/a&gt;. I also did a short talk with title &lt;a href=&quot;https://docs.google.com/presentation/d/1rOCQ1-VW7gg6KCq5RbIcT4uFsxWaewj8zy8ICY5FIzM/edit?usp=sharing&quot;&gt;How to nurture sustainable tech communities: experiences since 2006&lt;/a&gt; in February for GDG ANZ Summit 2024. In total, I did seven public talks/workshops this year most of them in Sydney.&lt;/p&gt;
&lt;p&gt;In addition to that, I did an internal talk at Simply Wall St. about the portfolio limits feature we deployed in April of this year. So, I wrote three talks and one workshop in 2024. You can view a reverse cronological list of all the talk I have done in public in my &lt;a href=&quot;https://github.com/geshan/public-speaking&quot;&gt;public speaking repo&lt;/a&gt;.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/recap-2024/02public-speaking-2024.jpg&quot; loading=&quot;lazy&quot; title=&quot;Public speaking in 2024 some highlights&quot; alt=&quot;Public speaking in 2024 some highlights&quot; /&gt;
&lt;h2 id=&quot;blog-posts-of-2024&quot; tabindex=&quot;-1&quot;&gt;Blog posts of 2024 &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#blog-posts-of-2024&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Similar to 2022 and 2023, this year, I wrote 25+1 (this review) blog posts. I wrote two blog posts in most months, but in March and June, I wrote only one. I wrote three blog posts in February, April, July, and December to balance it. The top 5 blog posts published in 2024 are:&lt;/p&gt;
&lt;h3 id=&quot;most-viewed-blog-posts-of-2024&quot; tabindex=&quot;-1&quot;&gt;Most viewed blog posts of 2024 &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#most-viewed-blog-posts-of-2024&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/03/nginx-docker-compose/&quot;&gt;How to use Nginx with Docker Compose effectively with examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/05/rabbitmq-docker/&quot;&gt;How to use RabbitMQ with Docker and Docker Compose; a beginner’s guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/02/docker-compose-depends-on/&quot;&gt;How to use docker compose depends_on a beginner&#39;s guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/01/cloud-shell-editor/&quot;&gt;How to use Google Cloud Shell Editor to deploy a project from GitHub to Cloud Run&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/07/nestjs-query-params/&quot;&gt;How to use query params in Nest.js a practical step-by-step guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most of the blog traffic came from SEO (Google). Some numbers indicate over a million page views this year, less than in 2023, but it is a fantastic feat. Posts about Docker do well on my blog, and this year is the first time I have written about &lt;a href=&quot;https://geshan.com.np/blog/categories/nest.js/&quot;&gt;Nest.js&lt;/a&gt;, which I have used at work since 2019. I should write more about Nest.js in 2025.&lt;/p&gt;
&lt;p&gt;I plan to scale back blogging in 2025 to one monthly post and target 14 or 15 blog posts. The number of users and page views has significantly decreased this year compared to 2022 or 2023.&lt;/p&gt;
&lt;p&gt;Regarding ranking, this blog moved from the 882178th website in the world in 2023 to the 590709th position in 2024 on &lt;a href=&quot;https://www.similarweb.com/website/geshan.com.np/&quot;&gt;SimilarWeb&lt;/a&gt; as seen below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/recap-2024/03blog-similar-web-2024.jpg&quot; loading=&quot;lazy&quot; title=&quot;Blog ranking in the world at the end 2024 as per SimilarWeb&quot; alt=&quot;Blog ranking in the world at the end 2024 as per SimilarWeb&quot; /&gt;
&lt;p&gt;This might mean the world’s search traffic and internet traffic to the blog decreased in 2024 due to LLMs answering most of the users&#39; questions.&lt;/p&gt;
&lt;h2 id=&quot;podcasts%2Finterviews-this-year&quot; tabindex=&quot;-1&quot;&gt;Podcasts/Interviews this year &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#podcasts%2Finterviews-this-year&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I was fortunate enough to be a guest in two podcasts. First, the popular StackOverflow Podcast titled &lt;a href=&quot;https://stackoverflow.blog/2024/08/23/evolution-backend-engineering-php-javascript-kubernetes-containers/&quot;&gt;From PHP to JavaScript to Kubernetes: how one backend engineer evolved over time&lt;/a&gt;. I had emailed them and got a reply back, had a quick pre-recording chat with Ryan. Then, the recording happened on an early Saturday morning (late Friday afternoon in the New York time zone); after some weeks, it was published and has had thousands of listeners till now. You can also listen to our conversation below:&lt;/p&gt;
&lt;iframe style=&quot;border-radius:12px&quot; src=&quot;https://open.spotify.com/embed/episode/1zVRjBhzfBIOvejfLXzhqh?utm_source=generator&amp;theme=0&quot; width=&quot;100%&quot; height=&quot;152&quot; frameBorder=&quot;0&quot; allowfullscreen=&quot;&quot; allow=&quot;autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture&quot; loading=&quot;lazy&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;I was in Nepal after a long time this year in August and had the pleasure of having an insightful (and long) conversation with &lt;a href=&quot;https://www.linkedin.com/in/anup-ghimire-9366aa5a&quot;&gt;Anup Ghimire&lt;/a&gt; for &lt;a href=&quot;https://www.youtube.com/c/TheDoersNepal&quot;&gt;The Doers Nepal&lt;/a&gt; podcast. The podcast episode has the title &lt;a href=&quot;https://www.youtube.com/watch?v=FsyEumavo_k&quot;&gt;Debugging Your Career: Advice from a Senior Software Engineer&lt;/a&gt; and has garnered almost 12K views on YouTube now. You can enjoy our conversation in the Nepali language here:&lt;/p&gt;
&lt;div style=&quot;position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%; margin-bottom: 1rem;&quot;&gt;
  &lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/FsyEumavo_k&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; style=&quot;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;Those were the two interviews I did this year. I also did an online panel discusison for &amp;quot;IT Carrer in Australia&amp;quot; about Frontend vs Backend vs Full Stack: Navigating Your Career Path - hosted by &lt;a href=&quot;https://www.linkedin.com/in/yana-martens/&quot;&gt;Yana Martens&lt;/a&gt; in May. The other panelists in that discussion were Phillip Johnson and Nicholas Kircher. You can watch the panel discussion below:&lt;/p&gt;
&lt;div style=&quot;position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%; margin-bottom: 1rem;&quot;&gt;
  &lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/scGQ0cEV2nM&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; style=&quot;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;I have moderated a couple of panel discusisons in 2024, which is discussed in the community activities section below.&lt;/p&gt;
&lt;h2 id=&quot;community-activities&quot; tabindex=&quot;-1&quot;&gt;Community activities &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#community-activities&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As &lt;a href=&quot;https://gdg.community.dev/gdg-cloud-sydney/&quot;&gt;GDG Cloud Sydney&#39;s&lt;/a&gt; organizers, we organized 11 meetups in 2024. I attended ten and missed the one in August. I also spoke at &lt;a href=&quot;https://gdg.community.dev/events/details/google-gdg-cloud-sydney-presents-gdg-cloud-sydney-meetup-may-2024/&quot;&gt;one&lt;/a&gt; of our meetups about serverless containers.&lt;/p&gt;
&lt;p&gt;In collaboration with GDG Sydney, we organized two full-day conferences, &lt;a href=&quot;https://gdg.community.dev/events/details/google-gdg-cloud-sydney-presents-gdg-cloud-sydney-x-google-io-extended/&quot;&gt;Googie I/O Extended Sydney 2024&lt;/a&gt; in June and &lt;a href=&quot;https://gdg.community.dev/events/details/google-gdg-sydney-presents-gdg-sydney-devfest-2024/cohost-gdg-cloud-sydney&quot;&gt;GDG DevFest Sydney&lt;/a&gt; in October. Both of these conferences had over 150 attendees. Google I/O Extended Sydney 2024 was a single-track conference, whereas GDG DevFest Sydney 2024 was a two-track conference. I mostly looked into the content for both of these conferences. That meant evaluating and choosing talk, finding panelists and mentors, and grooming new speakers. I also moderated the panel discussion about AI in both the above-mentioned conferences.&lt;/p&gt;
&lt;p&gt;For grooming new speakers, I helped five (or more) new female speakers give their debut conference talk at GDG DevFest Sydney 2024. We helped them with content, delivery, and a dry run to foster more confidence in them when doing the actual show. Anima, Lakshmi, Monika, Ranjana, and Utkrista did their first conference talk at GDG DevFest Sydney 2024. Among them, Monika was invited to Melbourne to do the same talk, which gives me some extra pride 🙂.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/recap-2024/04community-devfest.jpg&quot; loading=&quot;lazy&quot; title=&quot;One highlight of many tech community activities, the photo is from DevFest Sydney 2024&quot; alt=&quot;One highlight of many tech community activities, the photo is from DevFest Sydney 2024&quot; /&gt;
&lt;p&gt;This year, I helped some people become Google Developer Experts, Google Cloud Innovator Champions, and Women Techmakers Ambassadors. Thanks to &lt;a href=&quot;https://www.linkedin.com/in/mranocchiari/&quot;&gt;Matt&lt;/a&gt; for facilitating this journey for those six lucky individuals. I also recruited two new co-organizers for GDG Cloud Sydney this year.&lt;/p&gt;
&lt;p&gt;A big thanks to &lt;a href=&quot;https://www.linkedin.com/in/reeyamaharjan/&quot;&gt;Reeya&lt;/a&gt; for her superb support for our events, from designing graphics, recording, and editing reels/shorts, and managing some logistics to being an amazing MC at DevFest Sydney.&lt;/p&gt;
&lt;h2 id=&quot;became-a-docker-captain&quot; tabindex=&quot;-1&quot;&gt;Became a Docker Captain &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#became-a-docker-captain&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In addition to being a Google Developer Expert (GDE) for Google Cloud since 2019, I wanted to be tagged with another &lt;a href=&quot;https://github.com/geshan/developer-ambassador-programs&quot;&gt;Developer Ambassador program&lt;/a&gt;. I emailed Docker to apply for being a Docker Captain in 2021 and 2023 but never heard back. This year, they added a form for being a Docker Captain, and thankfully, &lt;a href=&quot;https://www.linkedin.com/in/eva-bojorges/&quot;&gt;Eva&lt;/a&gt; replied when I filled out the form. She organized a short interview (chat) and approved my application, and I became a &lt;a href=&quot;https://www.docker.com/captains/geshan-manandhar/&quot;&gt;Docker Captain&lt;/a&gt; in late June of this year. When writing this, there are only 3 Docker captains in Australia.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/recap-2024/05docker-captain.jpg&quot; loading=&quot;lazy&quot; title=&quot;I became a Docker Captain in mid 2024, one of the three in Australia&quot; alt=&quot;I became a Docker Captain in mid 2024, one of the three in Australia&quot; /&gt;
&lt;h2 id=&quot;developer-ambassador-programs-repo&quot; tabindex=&quot;-1&quot;&gt;Developer ambassador programs repo &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#developer-ambassador-programs-repo&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A developer ambassador program is a program a company runs to promote its products or services by that organization&#39;s representatives (but not employees). As a member of any developer ambassador program, you are expected to produce technical content like blog posts, podcasts, videos, etc. You are encouraged to talk about their products via public speaking or even contribute to open-source projects and forums like Stack Overflow. It comes with some &lt;a href=&quot;https://github.com/geshan/developer-ambassador-programs?tab=readme-ov-file#benefits-of-joining-a-developer-ambassador-program&quot;&gt;benefits&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I have started an open-source repository to list the &lt;a href=&quot;https://github.com/geshan/developer-ambassador-programs&quot;&gt;developer ambassador programs&lt;/a&gt; I know about. There are 40+ developer ambassador programs listed in the repo; eight are  &lt;code&gt;students only&lt;/code&gt; programs. Some popular ones are AWS Community Builder, GitHub Campus Expert, Google Cloud Champaign Innovator, and Microsoft MVP.&lt;/p&gt;
&lt;p&gt;If you know of any developer ambassador programs missing from that list, please add them by opening a new pull request.&lt;/p&gt;
&lt;h2 id=&quot;listening-to-podcasts&quot; tabindex=&quot;-1&quot;&gt;Listening to Podcasts &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#listening-to-podcasts&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With a daily average of ~37 minutes, I have listened to two hundred and twenty-five hours of podcasts this year (9 days and 9 hours). The stats from Podcast Republic, my podcatcher of choice, is as follows:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/recap-2024/06podcasts-listen.jpg&quot; loading=&quot;lazy&quot; title=&quot;I listened to 225 hours of podcasts in 2024 that is almost 37 minutes a day&quot; alt=&quot;I listened to 225 hours of podcasts in 2024 that is almost 37 minutes a day&quot; /&gt;
&lt;p&gt;The five most listened-to podcasts in 2024 are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://changelog.com/master&quot;&gt;ChangeLog Master feed&lt;/a&gt; - includes other podcasts like Ship It, Practical AI, etc. You must listen to &lt;a href=&quot;https://changelog.com/news&quot;&gt;Changelog News&lt;/a&gt; for your weekly Dose of software engineering news in under 10 mins.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.blog/podcast&quot;&gt;The Stack Overflow Podcast&lt;/a&gt; - their relatively short (&amp;lt;30 mins) podcasts are a great listen.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://podrocket.logrocket.com/&quot;&gt;PodRocket&lt;/a&gt; - great weekly episodes on frontend web development by LogRocket.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://investopoly.buzzsprout.com/&quot;&gt;Investoploy&lt;/a&gt;: Stuart offers fantastic advice on investing and building wealth with an Australian perspective.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://37signals.com/podcast/&quot;&gt;Rework&lt;/a&gt; - by 37Signals, it is always great to listen to Jason Fried, David Heinemeier Hansson, and the host Kimberly about the way &lt;code&gt;37Signals&lt;/code&gt; work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other podcasts in the top 10 include &lt;a href=&quot;https://review.firstround.com/podcast/&quot;&gt;In Depth&lt;/a&gt;, &lt;a href=&quot;https://www.compressed.fm/&quot;&gt;Compressed.fm&lt;/a&gt;, &lt;a href=&quot;https://softwareengineeringdaily.com/category/all-episodes/exclusive-content/Podcast/&quot;&gt;Software Engineering Daily&lt;/a&gt; and &lt;a href=&quot;https://moderncto.io/podcast/&quot;&gt;ModernCTO&lt;/a&gt; Podcast.&lt;/p&gt;
&lt;h2 id=&quot;misc&quot; tabindex=&quot;-1&quot;&gt;Misc &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#misc&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Below are some of the other things I have done or achieved this year:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My GitHub stats show that I have made over &lt;a href=&quot;https://github.com/geshan?tab=overview&amp;amp;from=2024-12-01&amp;amp;to=2024-12-18&quot;&gt;1,000 public contributions&lt;/a&gt; on GitHub and participated in &lt;a href=&quot;https://hacktoberfest.com/&quot;&gt;Hacktoberfest&lt;/a&gt;. We do not use GitHub at Simply Wall St.&lt;/li&gt;
&lt;li&gt;I think I can call myself a (partial) LinkedIn Influencer now, with &lt;a href=&quot;https://photos.app.goo.gl/73Ewq4ysyEHrmZCA7&quot;&gt;a million&lt;/a&gt; impressions reaching 93K+ people in 2024. I have also walked 1.87 million steps in 2024 if that counts as a stat.&lt;/li&gt;
&lt;/ul&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/recap-2024/07linked-in-2024.jpg&quot; loading=&quot;lazy&quot; title=&quot;Garnered more than a million impressions on LinkedIn across 93K users in 2024&quot; alt=&quot;Garnered more than a million impressions on LinkedIn across 93K users in 2024&quot; /&gt;
&lt;ul&gt;
&lt;li&gt;I would like to thank the members of the &lt;a href=&quot;https://xplorers-website.vercel.app/&quot;&gt;Xplorers&lt;/a&gt; group for their warm messages of thanks.&lt;/li&gt;
&lt;li&gt;I attended &lt;a href=&quot;https://anz.serverlessdays.io/sydney/&quot;&gt;Serverless Days Sydney 2024&lt;/a&gt;,  &lt;a href=&quot;https://aws.amazon.com/events/summits/sydney/&quot;&gt;AWS Summit Sydney&lt;/a&gt;, &lt;a href=&quot;https://aitour.microsoft.com/en-US/sydney&quot;&gt;Microsoft AI Tour&lt;/a&gt; twice, and &lt;a href=&quot;https://www.linkedin.com/posts/google-cloud_2024-google-cloud-summit-sydney-activity-7183375414218608642-luK_/&quot;&gt;Google Cloud Summit Sydney&lt;/a&gt;. I also attended other meetups and events like BeerOps.&lt;/li&gt;
&lt;li&gt;Hopefully, the 1:1 chats I have conducted have helped many in multiple areas, such as career advice, what to do next, how to find a job in Australia and other useful topics.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The photos related to the above things can be viewed in this &lt;a href=&quot;https://photos.app.goo.gl/EKzrQwtYh898ucBf7&quot;&gt;2024 recap photo album&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/recap-2024/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Looking back, 2024 was a productive year. I attended many tech events and was fortunate to be a guest on two podcasts. I also wrote the usual 25+ blog posts.&lt;/p&gt;
&lt;p&gt;I look forward to 2025 but will scale back on things I have been doing, like blogging. Merry Christmas and Happy New Year 2025.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Enhance Your CV, LinkedIn, and GitHub Profile with Gemini 2.0 - Stream Realtime [includes video]</title>
		<link href="https://geshan.com.np/blog/2024/12/google-gemini-2/"/>
		<updated>2024-12-16T10:35:45Z</updated>
		<id>https://geshan.com.np/blog/2024/12/google-gemini-2/</id>
		<content type="html">&lt;p&gt;Do you feel your resume, LinkedIn profile, or GitHub contributions must convey the right message? Your CV, LinkedIn profile, and GitHub repositories are your digital storefront, and keeping them fresh and relevant is key to attracting opportunities. In this post, we&#39;ll explore leveraging Google Gemini 2.0&#39;s real-time streaming capabilities to improve your CV, LinkedIn, and GitHub profile, focusing on practical examples and actionable strategies for you to land a tech role. Let&#39;s dive in!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-gemini-2/01google-gemini-2.jpg&quot; title=&quot;Enhance Your CV, LinkedIn, and GitHub Profile with Gemini 2.0 - Stream Realtime [includes video]&quot; alt=&quot;Enhance Your CV, LinkedIn, and GitHub Profile with Gemini 2.0 - Stream Realtime [includes video]&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of Contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/google-gemini-2/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/google-gemini-2/#gemini-2.0-flash-(experimental)-multimodal-capabilities&quot;&gt;Gemini 2.0 Flash (Experimental) Multimodal Capabilities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/google-gemini-2/#using-gemini-2.0-live-stream-to-improve-cv%2C-linkedin%2C-and-github-profile&quot;&gt;Using Gemini 2.0 Live Stream to Improve CV, LinkedIn, and GitHub Profile&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/google-gemini-2/#demo-video&quot;&gt;Demo Video&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/google-gemini-2/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;gemini-2.0-flash-(experimental)-multimodal-capabilities&quot; tabindex=&quot;-1&quot;&gt;Gemini 2.0 Flash (Experimental) Multimodal Capabilities &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/google-gemini-2/#gemini-2.0-flash-(experimental)-multimodal-capabilities&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Gemini 2.0 isn&#39;t just another LLM; it&#39;s a &lt;a href=&quot;https://blog.google/technology/google-deepmind/google-gemini-ai-update-december-2024/#gemini-2-0&quot;&gt;powerful multimodal model&lt;/a&gt; for the agentic era. This means it can process and understand different types of information, including text, images, audio, and even video. This opens up a world of possibilities for creating richer, more engaging content that captures attention and showcases your skills in a way that traditional text-based formats can&#39;t.&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/google-gemini-2/02gemini-2-capabilities.jpg&quot; loading=&quot;lazy&quot; title=&quot;Google Gemini 2.0 capabilities&quot; alt=&quot;Google Gemini 2.0 capabilities&quot; /&gt;
&lt;p&gt;Unlike other models, Gemini 2.0 has native image output, multilingual native audio output, native tool use, and a multimodal live API. However, some of the features have not yet been released to everyone. If interested, you can also look at the API and SDK &lt;a href=&quot;https://geshan.com.np/blog/2024/12/google-gemini-2/%E2%80%8B%E2%80%8Bhttps://cloud.google.com/vertex-ai/generative-ai/docs/gemini-v2&quot;&gt;docs&lt;/a&gt;. As per Google’s official announcement:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Flash 2.0 is twice as fast as 1.5 Pro while achieving stronger performance, includes new multimodal outputs, and comes with native tool use.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Some have mentioned it as &lt;a href=&quot;https://www.reddit.com/r/GoogleGeminiAI/comments/1heltdm/gemini_20_flash_is_revolutionary/&quot;&gt;revolutionary&lt;/a&gt;, &lt;a href=&quot;https://aifocussed.medium.com/how-googles-gemini-2-0-is-changing-the-ai-game-with-real-world-use-cases-50ddabd19d83&quot;&gt;game changer&lt;/a&gt;, or even the next ChatGPT moment. Does it match all the hype and accolades? I will leave that decision up to you.&lt;/p&gt;
&lt;p&gt;Imagine having a real-time conversation with an LLM while showing it a video, sharing audio from your mic, showing it a live video from your device’s camera, or even sharing your screen and asking questions about it. All this is possible with Gemini 2.0 Flash (currently experimental, &lt;a href=&quot;https://developers.googleblog.com/en/the-next-chapter-of-the-gemini-era-for-developers/&quot;&gt;released&lt;/a&gt; around a week ago) with the Stream Realtime feature. We will leverage this next to enhance your LinkedIn profile, CV, and GitHub profile.&lt;/p&gt;
&lt;h2 id=&quot;using-gemini-2.0-live-stream-to-improve-cv%2C-linkedin%2C-and-github-profile&quot; tabindex=&quot;-1&quot;&gt;Using Gemini 2.0 Live Stream to Improve CV, LinkedIn, and GitHub Profile &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/google-gemini-2/#using-gemini-2.0-live-stream-to-improve-cv%2C-linkedin%2C-and-github-profile&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that you understand Gemini 2.0&#39;s capabilities let&#39;s explore some practical examples of using its real-time streaming feature to enhance your online presence.&lt;/p&gt;
&lt;p&gt;In a new browser window, open your LinkedIn profile in one tab, your CV in the next one (preferably a Google Doc), and your GitHub profile in the third one. Then, on the fourth tab, go to &lt;a href=&quot;https://aistudio.google.com/&quot;&gt;https://aistudio.google.com&lt;/a&gt; (Google AI Studio) and click on &lt;a href=&quot;https://aistudio.google.com/live&quot;&gt;Stream Realtime&lt;/a&gt;, then paste the following prompt into &lt;code&gt;System Instructions&lt;/code&gt; to get better responses to improve your LinkedIn profile, CV, and Github Profile:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;You are now a combined LinkedIn Profile optimization expert and &lt;br /&gt;a technical &lt;span class=&quot;token constant&quot;&gt;CV&lt;/span&gt; writing expert focusing on software engineering&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;br /&gt;Your role is to provide actionable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; easy&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;to&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;follow&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; and high&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;quality &lt;br /&gt;advice to improve a LinkedIn profile&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; including but not limited &lt;br /&gt;to headlines&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; about sections&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; and things the person is sharing on &lt;br /&gt;LinkedIn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; is all geared toward the person finding a full&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;time tech role &lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; Australia&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; Your expertise spans optimizing LinkedIn profiles &lt;br /&gt;and resumes toward finding the first or second full&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;time software &lt;br /&gt;engineering role focused on recent graduates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;As an expert technical resume writer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; focus on the &lt;span class=&quot;token constant&quot;&gt;XYZ&lt;/span&gt; formula and &lt;br /&gt;what both technical recruiters and technical people like software &lt;br /&gt;engineers and software engineering managers will appreciate &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;br /&gt;the resume&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; Also&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; emphasize keeping things simple&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; straightforward&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;and to the point&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; You should also be able to review and suggest &lt;br /&gt;improvements &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; a GitHub profile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Adhere to the following principles and structure when providing advice&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;General Instructions&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;User Context Sensitivity&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Tailor recommendations to the person&#39;s &lt;br /&gt;specific needs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; considering the target audience&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; mainly technical &lt;br /&gt;recruiters and software engineering managers&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; goals&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; and finding &lt;br /&gt;the first technical role focusing on making a great first impression&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token literal-property property&quot;&gt;Clarity&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Ensure all advice is straightforward&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; free &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; unnecessary &lt;br /&gt;jargon&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; and includes step&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;by&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;step guidance where relevant&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token literal-property property&quot;&gt;Actionability&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Provide actionable advice &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; a clear path to &lt;br /&gt;implementation&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; including prioritization and how to maximize outcomes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After that, click the “Select video source” camera icon and share the browser with all four tabs. For this example, we are using Sajan’s profile. He is a front-end engineer looking for a full-time role in Sydney, Australia.&lt;/p&gt;
&lt;h3 id=&quot;demo-video&quot; tabindex=&quot;-1&quot;&gt;Demo Video &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/google-gemini-2/#demo-video&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Then follow what is done in the below 17-minute video to elevate your LinkedIn profile, CV, and GitHub Profile to the next level:&lt;/p&gt;
&lt;div style=&quot;position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%; margin-bottom: 1rem;&quot;&gt;
  &lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/Cvopy3kvRK8&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; style=&quot;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;Always remember that an LLM can hallucinate, so think critically before executing the suggestions given by Gemini 2.0 Flash or any other LLM, as they give out non-deterministic output.&lt;/p&gt;
&lt;p&gt;You can see this demo as scratching the surface; you can ask other questions to the LLM in the context of enhancing your LinkedIn, CV, and GitHub profile.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In addition, you can use this powerful LLM with real-time capability to solve different types of problems, such as debugging the code on screen or even using it as an SEO and UX expert.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can use Gemini to solve many problems, but choosing the right ones is up to you.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/google-gemini-2/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Gemini 2.0&#39;s real-time streaming capabilities offer powerful tools for enhancing your online presence and showcasing your skills in a way that traditional text-based formats can&#39;t. Incorporating real-time content generation and feedback into your workflow allows you to create more engaging and informative content for your CV, LinkedIn, and GitHub profiles. So, unleash the power of Gemini 2.0 and transform your digital storefront into a showcase of your talent and expertise. Expand on it and use the powerful Gemini 2.0 model to get help to solve other problems. Bring it on!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to Upsert Data in Postgres Using INSERT ON CONFLICT UPDATE</title>
		<link href="https://geshan.com.np/blog/2024/12/postgres-insert-on-conflict-update/"/>
		<updated>2024-12-14T10:37:45Z</updated>
		<id>https://geshan.com.np/blog/2024/12/postgres-insert-on-conflict-update/</id>
		<content type="html">&lt;p&gt;Updating existing data is a core requirement of any web application; doing it efficiently will make your life easier. PostgreSQL, a robust and feature-rich relational database, offers a powerful and elegant solution for managing these updates: &lt;code&gt;INSERT ON CONFLICT UPDATE&lt;/code&gt;. It is helpful to combine insert and update to Upsert and use the same logic for both operations. In this post, you will learn how to use &lt;code&gt;INSERT ON CONFLICT UPDATE&lt;/code&gt; in Postgres to Upsert data effectively with practical examples. Let’s get going!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/postgres-insert-on-conflict-update/01postgres-insert-on-conflict-update.jpg&quot; title=&quot;How to Upsert Data in Postgres Using INSERT ON CONFLICT UPDATE&quot; alt=&quot;How to Upsert Data in Postgres Using INSERT ON CONFLICT UPDATE&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/postgres-insert-on-conflict-update/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/postgres-insert-on-conflict-update/#postgres-upsert-with-insert-on-conflict-update-syntax&quot;&gt;Postgres Upsert with INSERT ON CONFLICT UPDATE syntax&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/postgres-insert-on-conflict-update/#upsert-example-with-quotes-table&quot;&gt;Upsert example with quotes table&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/postgres-insert-on-conflict-update/#upsert-a-single-row-in-the-quotes-table&quot;&gt;Upsert a single row in the quotes table&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/postgres-insert-on-conflict-update/#upsert-multiple-rows-on-the-quotes-table&quot;&gt;Upsert multiple rows on the quotes table&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/12/postgres-insert-on-conflict-update/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;postgres-upsert-with-insert-on-conflict-update-syntax&quot; tabindex=&quot;-1&quot;&gt;Postgres Upsert with INSERT ON CONFLICT UPDATE syntax &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/postgres-insert-on-conflict-update/#postgres-upsert-with-insert-on-conflict-update-syntax&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;INSERT ON CONFLICT&lt;/code&gt; clause in PostgreSQL provides an efficient way to perform an upsert operation. Unlike traditional &lt;code&gt;INSERT&lt;/code&gt; statements coupled with &lt;code&gt;UPDATE&lt;/code&gt; statements, which require separate queries, &lt;code&gt;INSERT ON CONFLICT&lt;/code&gt; combines both actions into one. The syntax is as follows:&lt;/p&gt;
&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;INTO&lt;/span&gt; table_name &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;column1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; column2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;VALUES&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value3&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value4&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;ON&lt;/span&gt; CONFLICT &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;unique_constraint&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;DO&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;UPDATE&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;SET&lt;/span&gt; column1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; excluded&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;column1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; column2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; excluded&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;column2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; …&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;RETURNING&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#39;s break down this powerful command:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;INSERT INTO table_name (column1, column2, ...)&lt;/code&gt;: This specifies the target table and the columns to be inserted or updated.  Ensure your column names are accurate!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;VALUES (value1, value2, ...), (value3, value4, ...), ...&lt;/code&gt;: These are the values you&#39;re trying to insert. You can supply multiple sets of values to upsert multiple rows simultaneously.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ON CONFLICT (unique_constraint)&lt;/code&gt;: This is the core of the upsert operation.  You specify the unique constraint (typically a primary key or a unique index) that determines whether to perform an insert or an update. The unique constraint is crucial for identifying whether a row already exists.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;SET column1 = excluded.column1, column2 = excluded.column2, ...&lt;/code&gt;: If a conflict is identified (a row with the same unique constraint already exists), this section specifies the columns to update and their new values.  The keyword &lt;code&gt;excluded&lt;/code&gt; refers to the values that were &lt;em&gt;originally&lt;/em&gt; provided in the &lt;code&gt;VALUES&lt;/code&gt; clause.  This helps efficiently update the existing row without any complex subqueries.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;RETURNING&lt;/code&gt;: clause returns from the insert or update statement the values of any columns after the insert or update was run. You can select some columns or everything with a &lt;code&gt;*&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can read more about the INSERT and INSERT ON CONFLICT part in the Postgres official &lt;a href=&quot;https://www.postgresql.org/docs/current/sql-insert.html&quot;&gt;docs&lt;/a&gt;. You can also read about &lt;a href=&quot;https://geshan.com.np/blog/2021/01/nodejs-postgresql-tutorial/&quot;&gt;Postgres Node.js Tutorial&lt;/a&gt; if you want to create a simple Node.js app interacting with Postgres. Also, you can read &lt;a href=&quot;https://geshan.com.np/blog/2024/08/postgres-insert-multiple-rows/&quot;&gt;Postgrest insert multiple rows&lt;/a&gt; to learn about techniques to insert multiple rows into Postgres efficiently with the same example used below.&lt;/p&gt;
&lt;p&gt;If your app has a data insertion, it will require updating data, too. Therefore, combining the two tasks into one becomes much more manageable, where Upsert becomes useful. In addition to &lt;code&gt;INSERT ON CONFICT UPDATE&lt;/code&gt;, in the newer version of Postgres that is 15 and above, a &lt;a href=&quot;https://www.postgresql.org/docs/current/sql-merge.html&quot;&gt;MERGE statement&lt;/a&gt; is also available.&lt;/p&gt;
&lt;h2 id=&quot;upsert-example-with-quotes-table&quot; tabindex=&quot;-1&quot;&gt;Upsert example with quotes table &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/postgres-insert-on-conflict-update/#upsert-example-with-quotes-table&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s illustrate &lt;code&gt;INSERT ON CONFLICT UPDATE&lt;/code&gt; with a practical example using a &lt;code&gt;quotes&lt;/code&gt; table.  This table stores quotes along with their authors and has the following structure:&lt;/p&gt;
&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TABLE&lt;/span&gt; quote &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;    id &lt;span class=&quot;token keyword&quot;&gt;SERIAL&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;PRIMARY&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;KEY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    quote &lt;span class=&quot;token keyword&quot;&gt;character&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;varying&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;UNIQUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    author &lt;span class=&quot;token keyword&quot;&gt;character&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;varying&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    created_at &lt;span class=&quot;token keyword&quot;&gt;timestamp&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;time&lt;/span&gt; zone &lt;span class=&quot;token keyword&quot;&gt;DEFAULT&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;CURRENT_TIMESTAMP&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    updated_at &lt;span class=&quot;token keyword&quot;&gt;timestamp&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;time&lt;/span&gt; zone &lt;span class=&quot;token keyword&quot;&gt;DEFAULT&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;CURRENT_TIMESTAMP&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;NULL&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, let&#39;s create a query that inserts 17 quotes about programming into this table as the initial data to work with:&lt;/p&gt;
&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;INTO&lt;/span&gt; quote &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;quote&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; author&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;VALUES&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;There are only two kinds of languages: the ones people complain about and the ones nobody uses.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Bjarne Stroustrup&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Any fool can write code that a computer can understand. Good programmers write code that humans can understand.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Martin Fowler&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;First, solve the problem. Then, write the code.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;John Johnson&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Java is to JavaScript what car is to Carpet.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Chris Heilmann&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;John Woods&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;I&#39;&#39;m not a great programmer; I&#39;&#39;m just a good programmer with great habits.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Kent Beck&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Truth can only be found in one place: the code.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Robert C. Martin&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;If you have to spend effort looking at a fragment of code and figuring out what it&#39;&#39;s doing, then you should extract it into a function and name the function after the &quot;what&quot;.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Martin Fowler&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Donald Knuth&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;SQL, Lisp, and Haskell are the only programming languages that I’ve seen where one spends more time thinking than typing.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Philip Greenspun&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Deleted code is debugged code.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Jeff Sickel&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;C.A.R. Hoare&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Simplicity is prerequisite for reliability.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Edsger W. Dijkstra&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;There are only two hard things in Computer Science: cache invalidation and naming things.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Phil Karlton&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Measuring programming progress by lines of code is like measuring aircraft building progress by weight.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Bill Gates&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Controlling complexity is the essence of computer programming.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Brian Kernighan&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;The only way to learn a new programming language is by writing programs in it.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Dennis Ritchie&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the next section, you will see a couple of examples of upserting a single row and then multiple rows in the above &lt;code&gt;quote&lt;/code&gt; table.&lt;/p&gt;
&lt;h3 id=&quot;upsert-a-single-row-in-the-quotes-table&quot; tabindex=&quot;-1&quot;&gt;Upsert a single row in the quotes table &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/postgres-insert-on-conflict-update/#upsert-a-single-row-in-the-quotes-table&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let’s imagine a scenario where one quote can be edited with a form, and another form exists to insert new quotes. These two forms can use two different queries, one insert, and one update, but it would be much easier and more maintainable if both of these use cases utilized a single SQL query with upsert. That Upsert query in Postgres can be achieved with &lt;code&gt;INSERT ON CONFLICT UPDATE&lt;/code&gt; as seen below:&lt;/p&gt;
&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;INTO&lt;/span&gt; quote &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; quote&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; author&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;VALUES&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;First, solve the problem. Then, write the code1.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;John Johnson1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;ON&lt;/span&gt; CONFLICT &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;DO&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;UPDATE&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;SET&lt;/span&gt; quote &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; excluded&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quote&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; author &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; excluded&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;author&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; updated_at &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;DEFAULT&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;RETURNING&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This query attempts to upsert a single quote. If a quote’s unique id (the primary key) already exists, both the &lt;code&gt;quote&lt;/code&gt; and &lt;code&gt;author&lt;/code&gt; columns will be updated to reflect the new value provided.  The original &lt;code&gt;created_at&lt;/code&gt; timestamp will be preserved, and &lt;code&gt;updated_at&lt;/code&gt; will get the last updated time with the &lt;code&gt;DEFAULT&lt;/code&gt; keyword, equating to the current timestamp. The values above don’t make sense, but they are used to show that the rows are being updated. If you provide the id as &lt;code&gt;null&lt;/code&gt;, it will be inserted as it will not conflict with any existing id.&lt;/p&gt;
&lt;h3 id=&quot;upsert-multiple-rows-on-the-quotes-table&quot; tabindex=&quot;-1&quot;&gt;Upsert multiple rows on the quotes table &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/postgres-insert-on-conflict-update/#upsert-multiple-rows-on-the-quotes-table&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The power of &lt;code&gt;INSERT ON CONFLICT UPDATE&lt;/code&gt; truly shines when you need to handle multiple rows.  For instance, let’s say you have a CSV file containing a list of quotes and their authors that you want to import into the &lt;code&gt;quotes&lt;/code&gt; table. You could use a single query to insert all the quotes, ensuring that existing quotes are efficiently updated.  This demonstrates a significant reduction in overhead compared to performing multiple individual &lt;code&gt;INSERT&lt;/code&gt; and &lt;code&gt;UPDATE&lt;/code&gt; operations.&lt;/p&gt;
&lt;p&gt;Here’s a sample query that demonstrates this concept with an assumption that the CSV only had two quotes:&lt;/p&gt;
&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;INTO&lt;/span&gt; quote &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; quote&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; author&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;VALUES&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Java is to JavaScript what car is to Carpet.2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Chris Heilmann2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Deleted code is debugged code.3&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Jeff Sickel3&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;ON&lt;/span&gt; CONFLICT &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;DO&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;UPDATE&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;SET&lt;/span&gt; quote &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; excluded&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quote&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; author &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; excluded&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;author&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; updated_at &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;DEFAULT&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;RETURNING&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If it were an actual application, the &lt;code&gt;VALUES&lt;/code&gt; part would have been constructed based on the data provided in the CSV. This would have been done with a parameterized query or an ORM (Object-relational mapping) library of the team’s choice. Like above, if you put the &lt;code&gt;id&lt;/code&gt; as &lt;code&gt;null&lt;/code&gt;, that row will be inserted. In the case of this &lt;code&gt;quote&lt;/code&gt; table, the &lt;code&gt;quote&lt;/code&gt; column is also unique, so if the given quote matches an existing quote, you might get an error. Using the &lt;code&gt;quote&lt;/code&gt; column as the &lt;code&gt;conflict target&lt;/code&gt; of the conflict can be another way of dealing with that issue.&lt;/p&gt;
&lt;p&gt;In this example, you are using id, but for your use case, you can use any unique column or constraint with a combination of more than one column. If the columns are passed correctly in the &lt;code&gt;conflict target&lt;/code&gt;, the &lt;code&gt;ON CONFLICT(...)&lt;/code&gt; part will work as expected.&lt;/p&gt;
&lt;p&gt;You can find both examples as a &lt;a href=&quot;https://www.db-fiddle.com/f/s4d4rRtvm7ez2TJAdAFmg3/3&quot;&gt;DB Fiddle&lt;/a&gt; you can run, which looks like the below when you run it:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/postgres-insert-on-conflict-update/02postgres-insert-on-conflict-update-db-fiddle.jpg&quot; loading=&quot;lazy&quot; title=&quot;Postgres insert on conflict update runnable quote example on db fiddle&quot; alt=&quot;Postgres insert on conflict update runnable quote example on db fiddle&quot; /&gt;
&lt;p&gt;You can play around with that DB fiddle, fork it, and use it for your experiments as you please.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/12/postgres-insert-on-conflict-update/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;PostgreSQL’s &lt;code&gt;INSERT ON CONFLICT UPDATE&lt;/code&gt; feature offers a robust and efficient way to manage data updates. Understanding its syntax and other considerations can significantly improve your database operations, especially when dealing with bulk updates whenever possible, for improved performance and maintainability of your applications.&lt;/p&gt;
&lt;p&gt;You learned about UPSERT in Postgres using the &lt;code&gt;INSERT ON CONFLICT UPDATE&lt;/code&gt; clause used on the quotes table to upsert single and multiple rows. Always prioritize efficient, well-structured SQL and techniques to improve your application’s code, like combining both INSERT and UPDATE into one UPSERT.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to use environment variables from a .env file in Node.js</title>
		<link href="https://geshan.com.np/blog/2024/11/nodejs-dotenv/"/>
		<updated>2024-11-24T12:27:45Z</updated>
		<id>https://geshan.com.np/blog/2024/11/nodejs-dotenv/</id>
		<content type="html">&lt;p&gt;Environment variables are essential for configuring your Node.js applications, allowing you to tailor settings for different environments like development, testing, and production. While you can set environment variables directly in your system or terminal, a more elegant and organized approach is to use a &lt;strong&gt;.env file&lt;/strong&gt;. This file allows you to store all your environment variables in one central location, keeping them separate from your code and making it easy to manage different configurations.&lt;/p&gt;
&lt;p&gt;In this comprehensive guide, we&#39;ll delve into the world of environment variables in Node.js, explore the role of the popular &lt;code&gt;dotenv&lt;/code&gt; package, and uncover how to use it effectively. We&#39;ll also explore the native way of accessing environment variables in Node.js 20+ using ESM (EcmaScript Modules). Let&#39;s get started!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/nodejs-dotenv/01nodejs-dotenv.jpg&quot; title=&quot;How to use environment variables from a .env file in Node.js&quot; alt=&quot;How to use environment variables from a .env file in Node.js&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#prerequisites&quot;&gt;Prerequisites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#get-environment-variables-using-dotenv&quot;&gt;Get environment variables using dotenv&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#installing-dotenv&quot;&gt;Installing dotenv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#creating-a-.env-file&quot;&gt;Creating a .env file&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#loading-environment-variables&quot;&gt;Loading environment variables&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#get-environment-variables-natively-node-20%2B&quot;&gt;Get environment variables natively Node 20+&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#using-%E2%80%93env-file-in-node-cli&quot;&gt;Using –-env file in node cli&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#dotenv-is-still-popular&quot;&gt;Dotenv is still popular&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;introduction&quot; tabindex=&quot;-1&quot;&gt;Introduction &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#introduction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Imagine you&#39;re building a Node.js application that needs to connect to a database. You&#39;ll need to store the database credentials, such as the host, username, password, and database name, somewhere. Hardcoding these credentials directly into your code is a security risk and makes managing different configurations for different environments difficult.&lt;/p&gt;
&lt;p&gt;That&#39;s where environment variables come to the rescue. You can store sensitive information like API keys, database credentials, and other configuration settings as environment variables, keeping them separate from your codebase. This enhances security and makes it easier to deploy your application to different environments with different configurations.&lt;/p&gt;
&lt;p&gt;A .env file is a simple text file that stores your environment variables in a key-value format. It&#39;s a widely adopted convention in the Node.js ecosystem for managing environment variables, and there&#39;s a popular NPM package called &lt;code&gt;dotenv&lt;/code&gt; that makes it easy to load these variables into your application. It also helps you achieve the &lt;a href=&quot;https://12factor.net/config&quot;&gt;config&lt;/a&gt; part of the 12-factor app. The 12-factor app’s config factor states, “requires strict separation of config from code. Config varies substantially across deploys, code does not.”&lt;/p&gt;
&lt;h2 id=&quot;prerequisites&quot; tabindex=&quot;-1&quot;&gt;Prerequisites &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#prerequisites&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before we dive into the code and explore how to use environment variables from a .env file, ensure you have the following prerequisites:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Node.js 20 or later installed:&lt;/strong&gt;  We&#39;ll be using the latest features of Node.js, so having a recent version installed is essential. You can check your Node.js version by running &lt;code&gt;node --version&lt;/code&gt; in your terminal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A basic understanding of Node.js and NPM:&lt;/strong&gt; You should be familiar with running Node.js scripts and installing NPM packages using the &lt;code&gt;npm install&lt;/code&gt; command.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Basic knowledge of JavaScript Modules:&lt;/strong&gt; This guide will use ESM imports. This is the new standard for JavaScript modules, and it&#39;s supported in Node.js 14 and above.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the subsequent section, you will learn how to get environment variables using the &lt;code&gt;dotenv&lt;/code&gt; package.&lt;/p&gt;
&lt;h2 id=&quot;get-environment-variables-using-dotenv&quot; tabindex=&quot;-1&quot;&gt;Get environment variables using dotenv &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#get-environment-variables-using-dotenv&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.npmjs.com/package/dotenv&quot;&gt;dotenv&lt;/a&gt; is a zero-dependency module that loads environment variables from a &lt;code&gt;.env&lt;/code&gt; file into &lt;code&gt;process.env&lt;/code&gt;. It&#39;s a simple and convenient way to manage your environment variables, keeping them separate from your code and making deploying your application to different environments easier.&lt;/p&gt;
&lt;h3 id=&quot;installing-dotenv&quot; tabindex=&quot;-1&quot;&gt;Installing dotenv &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#installing-dotenv&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To get started with &lt;code&gt;dotenv&lt;/code&gt;, you need to install it first. You can install it using the following command in your terminal:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; dotenv&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This command will install the &lt;code&gt;dotenv&lt;/code&gt; package from the NPM registry and add it to your project&#39;s &lt;code&gt;package.json&lt;/code&gt; file as a dependency.  At the time of writing &lt;code&gt;dotenv&lt;/code&gt; is at version &lt;a href=&quot;https://www.npmjs.com/package/dotenv/v/16.4.5&quot;&gt;16.4.5&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;creating-a-.env-file&quot; tabindex=&quot;-1&quot;&gt;Creating a .env file &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#creating-a-.env-file&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After you have installed the &lt;code&gt;dotenv&lt;/code&gt; package, you can create a &lt;code&gt;.env&lt;/code&gt; file in the root directory of your project. This file will contain all your environment variables. The format of the &lt;code&gt;.env&lt;/code&gt; file is simple. Each line represents an environment variable, with the key and value separated by an equal sign (&lt;code&gt;=&lt;/code&gt;). For example:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;DATABASE_NAME&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;quotes&lt;br /&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;DATABASE_USER&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;quotes_user&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;loading-environment-variables&quot; tabindex=&quot;-1&quot;&gt;Loading environment variables &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#loading-environment-variables&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To load the environment variables from your &lt;code&gt;.env&lt;/code&gt; file into &lt;code&gt;process.env&lt;/code&gt;, you need to call the &lt;code&gt;config&lt;/code&gt; method from the &lt;code&gt;dotenv&lt;/code&gt; module. This should be done at the very start of your application before any other code is executed. A common place to call the config method is in your application&#39;s entry point, which is usually &lt;code&gt;index.js&lt;/code&gt; or &lt;code&gt;app.js&lt;/code&gt;. For instance:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;dotenv/config&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dbName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;DATABASE_NAME&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dbUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;DATABASE_USER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Database name is &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;dbName&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; and database username is &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;dbUser&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the above code example, the &lt;code&gt;dotenv/config&lt;/code&gt; import call loads the environment variables from the &lt;code&gt;.env&lt;/code&gt; file into &lt;code&gt;process.env&lt;/code&gt;. Then, you add two constants, &lt;code&gt;dbName&lt;/code&gt; and &lt;code&gt;dbUser&lt;/code&gt;, to get the relevant environment variables and show them on the console with &lt;code&gt;console.log&lt;/code&gt;. If it was a real application, like an Express.js app, you would have used these variables to instantiate the connection to a database.&lt;/p&gt;
&lt;p&gt;When you run the above &lt;code&gt;index.js&lt;/code&gt; file with &lt;code&gt;node index.js&lt;/code&gt; and the relevant &lt;code&gt;.env&lt;/code&gt; file it will show the following output:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/nodejs-dotenv/02nodejs-dotenv-use.jpg&quot; loading=&quot;lazy&quot; title=&quot;Output of using the NPM dotenv package with Node.js version less than 20&quot; alt=&quot;Output of using the NPM dotenv package with Node.js version less than 20&quot; /&gt;
&lt;p&gt;If you want to use a different filename than &lt;code&gt;.env&lt;/code&gt;. You can import only the &lt;code&gt;dotenv &lt;/code&gt;module with &lt;code&gt;import dotenv from &#39;dotenv&#39;;&lt;/code&gt;, you can use a custom &lt;code&gt;.env&lt;/code&gt; file (not &lt;code&gt;.env&lt;/code&gt;), you can pass in the path to the file as an argument to the &lt;code&gt;config&lt;/code&gt; method like the below:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;dotenv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;./.env.example&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another useful way of using &lt;code&gt;dotenv&lt;/code&gt; without any import or require is to pass it in the node command. For instance for a file named &lt;code&gt;index-no-imports.js&lt;/code&gt; which as the below contents with the same &lt;code&gt;.env&lt;/code&gt; file:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dbName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;DATABASE_NAME&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dbUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;DATABASE_USER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Database name is &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;dbName&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; and database user is &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;dbUser&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can acces the environment variable by executing:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--require&lt;/span&gt; dotenv/config index-no-imports.js&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dotenv has a small ecosystem around it, you can learn more by reading it’s &lt;a href=&quot;https://github.com/motdotla/dotenv&quot;&gt;Readme&lt;/a&gt; file. There is dotenvx, you can encrypt and decrypt your environment variables, and &lt;code&gt;dotenv-valut&lt;/code&gt; too. It is supported by companies like Warp, WorkOs and Alloy Automation. It also has a YouTube channel and a &lt;a href=&quot;https://www.youtube.com/watch?v=YtkZR0NFd1g&quot;&gt;video&lt;/a&gt; explaining how to use it. There are lots of official examples using it from projects like &lt;a href=&quot;https://github.com/dotenv-org/examples/tree/master/nextjs&quot;&gt;Next.js&lt;/a&gt; to express.&lt;/p&gt;
&lt;p&gt;In the next section, you will learn about the native way of accessing environment variables in Node.js 20+.&lt;/p&gt;
&lt;h2 id=&quot;get-environment-variables-natively-node-20%2B&quot; tabindex=&quot;-1&quot;&gt;Get environment variables natively Node 20+ &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#get-environment-variables-natively-node-20%2B&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;From Node.js 20+, there is a native way to access environment variables without the&lt;br /&gt;
need to install a NPM package like &lt;code&gt;dotenv.&lt;/code&gt;  From Node 20.6.0, one of the most notable changes is the built-in support for .env files&lt;/p&gt;
&lt;h3 id=&quot;using-%E2%80%93env-file-in-node-cli&quot; tabindex=&quot;-1&quot;&gt;Using –env file in node cli &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#using-%E2%80%93env-file-in-node-cli&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;With the same &lt;code&gt;.env&lt;/code&gt; file and the &lt;code&gt;index-no-imports.js&lt;/code&gt; file from the above example. You can use the environment variales from the &lt;code&gt;.env&lt;/code&gt; file in any &lt;code&gt;js&lt;/code&gt; file with the following command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; --env-file .env index-no-imports.js&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will result in:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/nodejs-dotenv/03nodejs-env-file.jpg&quot; loading=&quot;lazy&quot; title=&quot;Output of using the Node.js --env-file to load env file in Node.js version 20+&quot; alt=&quot;Output of using the Node.js --env-file to load env file in Node.js version 20+&quot; /&gt;
&lt;p&gt;Which is exactly the same as the above output without the need to import &lt;code&gt;dotenv&lt;/code&gt; in the file or in the command line. This is possible from Node 20.6.0 as it &lt;a href=&quot;https://nodejs.org/en/blog/release/v20.6.0#built-in-env-file-support&quot;&gt;added built-in support for .env files&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can update your &lt;code&gt;.env&lt;/code&gt; file and run the code again and it will pick up the updated&lt;br /&gt;
environment variable. This is how you can access environment variables with&lt;br /&gt;
&lt;code&gt;import.meta.env&lt;/code&gt; in Node.js 20+. You can use &lt;a href=&quot;https://geshan.com.np/blog/2021/02/nodemon/&quot;&gt;nodemon&lt;/a&gt; to restart your applications when a &lt;code&gt;.js&lt;/code&gt; file changes or even when a &lt;code&gt;.env&lt;/code&gt; file changes with the correct watches.&lt;/p&gt;
&lt;p&gt;For your reference, you can find the code examples in this &lt;a href=&quot;https://github.com/geshan/nodejs-dotenv&quot;&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;dotenv-is-still-popular&quot; tabindex=&quot;-1&quot;&gt;Dotenv is still popular &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#dotenv-is-still-popular&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Given that Node.js 20+ has provided a native way to access environment variables since Sep 2023 (more than a year from when this blog post was written), you might be wondering why to bother with dotenv? It&#39;s a valid question with a valid answer:&lt;br /&gt;
&lt;code&gt;dotenv&lt;/code&gt; is still the most popular package for getting environment variables from a .env file.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;With over 45 million downloads per week as of Nov 2023, &lt;code&gt;dotenv&lt;/code&gt; is a battle-tested and widely used package in the Node.js ecosystem.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can see a comparison of dotenv, node-env-file, and dot-env as per &lt;a href=&quot;https://npmtrends.com/dot-env-vs-dotenv-vs-node-env-file&quot;&gt;npm trends&lt;/a&gt; below:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/nodejs-dotenv/04npm-dotenv-popular.jpg&quot; loading=&quot;lazy&quot; title=&quot;NPM dotevn package is still very popular with more than 45 million downloads each week&quot; alt=&quot;NPM dotevn package is still very popular with more than 45 million downloads each week&quot; /&gt;
&lt;p&gt;As you can see, dotenv is the clear winner, with exponentially more weekly downloads than its competitor, node-env-file. Even though dot-env is a similar library, the downloads are minimal. &lt;code&gt;dot-env&lt;/code&gt; has not been updated in the past 11 years, though, whereas &lt;code&gt;dotenv&lt;/code&gt; is a very active project on &lt;a href=&quot;https://github.com/motdotla/dotenv/commits/master/&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/nodejs-dotenv/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this comprehensive guide, you have learned how to access environment variables from&lt;br /&gt;
a .env file in Node.js. You explored two methods, the first one using the popular dotenv package and the second one using the native &lt;code&gt;--env-file&lt;/code&gt; available in Node.js 20+. With the knowledge of both methods, you can now make an informed choice depending on your project&#39;s needs.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you are working on a new project, I recommend opting for the native &lt;code&gt;--env-file&lt;/code&gt; method, as it&#39;s part of Node.js and doesn&#39;t need an external dependency. But if you are working on an existing project that already uses &lt;code&gt;dotenv&lt;/code&gt;, there&#39;s no need to change.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In the end, both achieve the same goal of accessing environment variables from a .env file. Eventually you can move to the native way of accessing environment variables in Node.js 20+ as it&#39;s part of the Node.js core and doesn&#39;t need an external dependency. This will make your application more lightweight and reduce the number of dependencies.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>A Beginner&#39;s Guide to Comparing Dates in JavaScript</title>
		<link href="https://geshan.com.np/blog/2024/11/javascript-compare-dates/"/>
		<updated>2024-11-01T12:32:47Z</updated>
		<id>https://geshan.com.np/blog/2024/11/javascript-compare-dates/</id>
		<content type="html">&lt;p&gt;Working with dates and times is a common task in software development.  In JavaScript, you have the built-in &lt;code&gt;Date&lt;/code&gt; object, but it can be a bit cumbersome and has its quirks. There are third-party libraries like &lt;code&gt;date-fns&lt;/code&gt; to help manipulate and format dates in JavaScript. However, the fundamental task of comparing two dates can be quickly done using the built-in methods, as you will learn in this post. You will start from the basics and move to use a third-party library, &lt;code&gt;date-fns&lt;/code&gt;, for date comparison in JavaScript. Buckle up!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/javascript-compare-dates/01javascript-compare-dates.jpg&quot; title=&quot;A Beginner&#39;s Guide to Comparing Dates in JavaScript&quot; alt=&quot;A Beginner&#39;s Guide to Comparing Dates in JavaScript&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of Contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#prerequisites&quot;&gt;Prerequisites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#directly-compare-javascript-date-objects&quot;&gt;Directly Compare JavaScript Date objects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#compare-dates-using-the-gettime-method&quot;&gt;Compare Dates using the getTime method&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#dates-comparison-with-date-fns&quot;&gt;Dates comparison with date-fns&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#compare-dates-with-compareasc&quot;&gt;Compare Dates with compareAsc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#other-useful-date-fns-functions&quot;&gt;Other useful date-fns functions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;introduction&quot; tabindex=&quot;-1&quot;&gt;Introduction &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#introduction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;JavaScript has a &lt;code&gt;Date&lt;/code&gt; object representing a single moment in time in a platform-independent format. This is achieved by representing the date object with a number with milliseconds since 1 January 1970 UTC.&lt;/p&gt;
&lt;p&gt;JavaScript provides multiple ways to compare dates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Direct Comparison:&lt;/strong&gt;  You can directly compare &lt;code&gt;Date&lt;/code&gt; objects using comparison operators like &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;=&lt;/code&gt;, &lt;code&gt;&amp;lt;=&lt;/code&gt;, but this method can be unreliable in some instances.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;getTime() Method:&lt;/strong&gt; The &lt;code&gt;getTime()&lt;/code&gt; method returns the number of milliseconds since the Unix epoch (seconds that have elapsed since 00:00:00 UTC on 1 January 1970), making it reliable for comparing dates.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Using Libraries:&lt;/strong&gt; Third-party libraries like &lt;code&gt;date-fns&lt;/code&gt; provide convenient functions for comparing dates, including &lt;code&gt;isBefore&lt;/code&gt;, &lt;code&gt;isAfter&lt;/code&gt;, &lt;code&gt;isEqual&lt;/code&gt;, &lt;code&gt;compareAsc&lt;/code&gt;, etc. Other popular date-related JavaScript libraries include Moment.js and Luxon. As per &lt;a href=&quot;https://npmtrends.com/date-fns-vs-luxon-vs-moment&quot;&gt;NPM trends&lt;/a&gt; &lt;code&gt;date-fns&lt;/code&gt; is the most popular one, with more than 23 million downloads per week at the time of writing this blog post.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this guide, you will explore examples of all of the above methods. You will also learn about the best practices for comparing dates in JavaScript.&lt;/p&gt;
&lt;h2 id=&quot;prerequisites&quot; tabindex=&quot;-1&quot;&gt;Prerequisites &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#prerequisites&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To follow along with the provided code examples in this post, you will need the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Node.js 22:&lt;/strong&gt; The code in this tutorial uses the latest features of Javascript/Node.js, hence it is advisable to have the newest version installed on your machine.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A code editor:&lt;/strong&gt; Any code editor that you are comfortable with will do. I have used VS Code for this tutorial, you can use any editor you choose.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;General knowledge of JavaScript:&lt;/strong&gt; This tutorial requires a basic understanding of how JavaScript works.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is also helpful to have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;NPM or Yarn:&lt;/strong&gt; Node Package Manager will be needed if you want to install &lt;code&gt;date-fns&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Git and Github:&lt;/strong&gt; You should know how to clone, commit, and push your changes to a Git repository on GitHub or similar service.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&#39;s get started!&lt;/p&gt;
&lt;h2 id=&quot;directly-compare-javascript-date-objects&quot; tabindex=&quot;-1&quot;&gt;Directly Compare JavaScript Date objects &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#directly-compare-javascript-date-objects&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can directly compare JavaScript Date objects using comparison operators like &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;gt;=&lt;/code&gt;, &lt;code&gt;&amp;lt;=&lt;/code&gt;, and &lt;code&gt;===&lt;/code&gt;. This is the easiest and most straightforward method to compare dates.&lt;/p&gt;
&lt;p&gt;However, using these operators can lead to unpredictable results in certain scenarios due to how &lt;code&gt;Date&lt;/code&gt; objects work internally, such as when considering time zones. You will see that in the example below:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;2024-11-01&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;2024-10-01&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date3 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;2024-11-02&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;date1: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;date2: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;date3: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date3&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date1Iso &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; date1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toISOString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date2Iso &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; date2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toISOString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date3Iso &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; date3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toISOString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Comparison results&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;================== Comparison results ==================&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; comparisonTable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;date1 &amp;lt; date2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &amp;lt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date1 &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; date2&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;date1 &gt; date2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date1 &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; date2&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;date1 &amp;lt;= date2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &amp;lt;= &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date1 &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; date2&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;date1 &gt;= date2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &gt;= &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date1 &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; date2&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;date1 === date2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; === &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date1 &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; date2&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;date1 &amp;lt; date3&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &amp;lt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date3Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date1 &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; date3&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;date1 &gt; date3&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date3Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date1 &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; date3&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;date2 === date2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date2 &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; date2&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;comparisonTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When you run the above script with &lt;code&gt;node index.js&lt;/code&gt; it will show the following output:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/javascript-compare-dates/02javascript-compare-date-objects.jpg&quot; loading=&quot;lazy&quot; title=&quot;Directly compare JavaScript Date objects&quot; alt=&quot;Directly compare JavaScript Date objects&quot; /&gt;
&lt;p&gt;One issue that can happen here is, if the date is created with &lt;code&gt;new Date()&lt;/code&gt; and another date is created with &lt;code&gt;new Date()&lt;/code&gt; after 2 seconds those two dates will not match. Also time zones will be another consideration to make for comparing date objects.&lt;/p&gt;
&lt;p&gt;For reliable comparison, always use the getTime() method discussed in the&lt;br /&gt;
next section.&lt;/p&gt;
&lt;h2 id=&quot;compare-dates-using-the-gettime-method&quot; tabindex=&quot;-1&quot;&gt;Compare Dates using the getTime method &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#compare-dates-using-the-gettime-method&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For a reliable date comparison in JavaScript, it is recommended to use the &lt;code&gt;getTime()&lt;/code&gt;&lt;br /&gt;
method available on the &lt;code&gt;Date&lt;/code&gt; object. This is because when you compare &lt;code&gt;Date&lt;/code&gt; objects directly, they are compared based on references, not their actual value. Even with the &lt;code&gt;getTime()&lt;/code&gt; method you will need to consider time zones, the easiest way to do it will be to convert all the dates to UTC timezone and then only do the date/time comparison.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The &lt;code&gt;getTime()&lt;/code&gt; method:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Returns the number of milliseconds that have elapsed since the Unix epoch (January 1, 1970, at 00:00:00 UTC).&lt;/li&gt;
&lt;li&gt;Provides a consistent numerical representation of a date that&#39;s suitable for direct comparison.&lt;/li&gt;
&lt;li&gt;Even with &lt;code&gt;getTime&lt;/code&gt; do keep the time zone issue in mind, &lt;a href=&quot;https://www.worldtimebuddy.com/?qm=1&amp;amp;lid=2147714,2643743&amp;amp;h=2147714&amp;amp;date=2024-11-1&amp;amp;sln=16-16.5&amp;amp;hf=1&quot;&gt;5 AM in London is 4 PM in Sydney&lt;/a&gt;, also think about the date changes and day light savings.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The example below shows how to compare dates using the &lt;code&gt;getTime()&lt;/code&gt; method to make it&lt;br /&gt;
more reliable:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;2024-11-01&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;2024-10-01&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date3 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;2024-11-02&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;date1: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;date2: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;date3: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date3&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date1Epoch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; date1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date2Epoch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; date2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date3Epoch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; date3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Comparison results&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;================== Comparison results ==================&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; comparisonTable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;date1 &amp;lt; date2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Epoch&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &amp;lt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Epoch&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date1Epoch &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; date2Epoch&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;date1 &gt; date2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Epoch&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Epoch&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date1Epoch &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; date2Epoch&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;date1 &gt;= date2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Epoch&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &gt;= &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Epoch&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date1Epoch &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; date2Epoch&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;date1 === date2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Epoch&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; === &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Epoch&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date1Epoch &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; date2Epoch&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;date1 &amp;lt; date3&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Epoch&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &amp;lt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date3Epoch&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date1Epoch &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; date3Epoch&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;date1 &gt; date3&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Epoch&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date3Epoch&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date1Epoch &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; date3Epoch&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;date2 === date2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Epoch&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Epoch&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date2Epoch &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; date2Epoch&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;comparisonTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The example is similar to the above one, but this time, instead of directly comparing the dates, you first convert each date to a number using the getTime() method. Now, as the comparison is done between numbers, it will always be accurate and reliable. This should be the preferred way to compare dates in JavaScript in all of your applications. The above code is available as part of a &lt;a href=&quot;https://github.com/geshan/javascript-compare-dates/pull/1/files#diff-6c0aed25b8e43470d16988ec6f0594277bc2c97d7a9fd44abc766d775e27a262&quot;&gt;pull request&lt;/a&gt; for your reference.&lt;/p&gt;
&lt;p&gt;Here is the output of the script written to the file results-getTime.txt:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/javascript-compare-dates/03javascript-compare-get-time.jpg&quot; loading=&quot;lazy&quot; title=&quot;Compare dates in JavaScript using getTime method&quot; alt=&quot;Compare dates in JavaScript using getTime method&quot; /&gt;
&lt;p&gt;Even here you are comparing “dates” not Date time, meaning &lt;code&gt;2024-11-01 3:00:00&lt;/code&gt; is after &lt;code&gt;2024-11-01 2:58:58&lt;/code&gt;, consider this fact. Also keep in mind the time zone differences.&lt;/p&gt;
&lt;p&gt;In the next section, you will learn about a very popular JavaScript library called&lt;br /&gt;
&lt;code&gt;date-fns&lt;/code&gt; and how to use it to compare dates with ease.&lt;/p&gt;
&lt;h2 id=&quot;dates-comparison-with-date-fns&quot; tabindex=&quot;-1&quot;&gt;Dates comparison with date-fns &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#dates-comparison-with-date-fns&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are many external npm libraries available to work with dates in JavaScript like date-fns, Moment.js and Luxon to name some. One of the most popular libraries for date and time manipulation is date-fns, which is downloaded more than &lt;a href=&quot;https://npmtrends.com/date-fns&quot;&gt;23 million&lt;/a&gt; times each week on npm.&lt;/p&gt;
&lt;p&gt;In this section, you will learn how to easily use &lt;code&gt;date-fns&lt;/code&gt; to compare dates in JavaScript. Before going to the examples, make sure to install it in your project. If your project is an npm project and you have a package.json file, run the following command to install it:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; date-fns &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At the time of writing this blog post, &lt;code&gt;date-fns&lt;/code&gt; is at version &lt;code&gt;4.1.0&lt;/code&gt;. In the next section, you will learn how to use &lt;code&gt;compareAsc&lt;/code&gt; from &lt;code&gt;date-fns&lt;/code&gt; to compare dates.&lt;/p&gt;
&lt;h3 id=&quot;compare-dates-with-compareasc&quot; tabindex=&quot;-1&quot;&gt;Compare Dates with compareAsc &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#compare-dates-with-compareasc&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;compareAsc&lt;/code&gt; function in &lt;code&gt;date-fns&lt;/code&gt; compares two dates and returns a number that indicates their relative order. It will return:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;-1 if the first date is before the second date.&lt;/li&gt;
&lt;li&gt;0 if the two dates are the same.&lt;/li&gt;
&lt;li&gt;1 if the first date is after the second date.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The example below demonstrates how to use &lt;code&gt;compareAsc&lt;/code&gt; to compare dates in JavaScript:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; compareAsc &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;date-fns&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;2024-11-01T00:00:00&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;2024-11-01T00:00:02&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date3 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2024&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;date1: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;date2: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;date3: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date3&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date1Iso &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; date1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toISOString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date2Iso &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; date2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toISOString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date3Iso &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; date3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toISOString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Comparison results&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;================== Comparison results ==================&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; comparisonTable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;compareAsc date1 and date2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; and &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;compareAsc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;date1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;compareAsc date2 and date1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; and &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;compareAsc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;date2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;compareAsc date2 and date2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; and &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;compareAsc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;date2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;compareAsc date1 and date3&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; and &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date3Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;compareAsc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;date1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date3&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;compareAsc date3 and date1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date3Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; and &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date1Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;compareAsc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;date3&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;compareAsc date2 and date3&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date2Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; and &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;date3Iso&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;compareAsc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;date2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date3&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;comparisonTable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;================== Sorting dates ASC ==================&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;date1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; date3&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;compareAsc&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#39;s analyze the above code. First, you import the compareAsc function from date-fns using ESM imports. Then, you initialize three date objects date1, date2, and date3. Then you run different comparison between the three dates, you also do a sorting of the 3 dates in ascending order. When you run the above script the output looks like the following:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/javascript-compare-dates/04javascript-compare-date-fns.jpg&quot; loading=&quot;lazy&quot; title=&quot;Date comparison in JavaScirpt using compareAsc from date-fns NPM package&quot; alt=&quot;Date comparison in JavaScirpt using compareAsc from date-fns NPM package&quot; /&gt;
&lt;p&gt;There are other useful functions like &lt;code&gt;isBefore&lt;/code&gt;, &lt;code&gt;isAfter&lt;/code&gt; and &lt;code&gt;isEqual&lt;/code&gt; that you can check out in the date-fns docs. In the next part, you will learn about more functions like these.&lt;/p&gt;
&lt;h3 id=&quot;other-useful-date-fns-functions&quot; tabindex=&quot;-1&quot;&gt;Other useful date-fns functions &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#other-useful-date-fns-functions&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;date-fns&lt;/code&gt; is a powerful and versatile JavaScript library for manipulating and formatting dates and times. You have just seen a couple of functions from &lt;code&gt;date-fns&lt;/code&gt; in the above example, some more useful &lt;code&gt;date-fns&lt;/code&gt; functions are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;format&lt;/code&gt;: for formating the date as per the needed locale.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;addDays&lt;/code&gt;, &lt;code&gt;addMonths&lt;/code&gt;, &lt;code&gt;addYears&lt;/code&gt;: to add days, months, and years to a date.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;subDays&lt;/code&gt;, &lt;code&gt;subMonths&lt;/code&gt;, &lt;code&gt;subYears&lt;/code&gt;: to subtract days, months, and years from a date.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isToday&lt;/code&gt;, &lt;code&gt;isYesterday&lt;/code&gt;, &lt;code&gt;isTomorrow&lt;/code&gt;: to check if the date is today, yesterday, or tomorrow.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://date-fns.org/v4.1.0/docs/differenceInMilliseconds&quot;&gt;differenceInMilliseconds&lt;/a&gt; : is another useful function that can be used to compare dates in JavaScript.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are some of the many other useful functions &lt;code&gt;date-fns&lt;/code&gt; has, you can find a&lt;br /&gt;
complete list in the &lt;a href=&quot;https://date-fns.org/docs/Getting-Started&quot;&gt;date-fns’s documentation&lt;/a&gt;. Use the search funcion to make the most of it.&lt;/p&gt;
&lt;p&gt;All the code examples are available in this &lt;a href=&quot;https://github.com/geshan/javascript-compare-dates&quot;&gt;GitHub repository&lt;/a&gt;. If you want to write effective unit tests for dates, you will need to &lt;a href=&quot;https://geshan.com.np/blog/2024/09/jest-mock-date/&quot;&gt;mock dates in jest&lt;/a&gt; to get the repeatable and predictabel results.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/11/javascript-compare-dates/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this tutorial, you learned about three different methods to compare dates in JavaScript. First, you used direct comparison, then you learned how to reliably compare dates using the JavaScript Date object&#39;s &lt;code&gt;getTime()&lt;/code&gt; method. Finally, you learned how to use the &lt;code&gt;date-fns&lt;/code&gt; library to compare dates with more ease. I hope this helped you understand more about &lt;code&gt;javascript compare dates&lt;/code&gt; and that you learned something useful from it.&lt;/p&gt;
&lt;p&gt;Happy coding and comparing Dates in JS!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to Read a JSON File Using Node.js</title>
		<link href="https://geshan.com.np/blog/2024/10/nodejs-read-json-file/"/>
		<updated>2024-10-30T08:32:47Z</updated>
		<id>https://geshan.com.np/blog/2024/10/nodejs-read-json-file/</id>
		<content type="html">&lt;p&gt;Reading a JSON (JavaScript Object Notation) file in Node.js is a common task for web developers, especially those working with backend and server-side applications. This tutorial will guide you through the process, breaking down the steps to efficiently read JSON files using both the native Node.js &lt;code&gt;fs&lt;/code&gt; module and the &lt;code&gt;fs-extra&lt;/code&gt; npm package.  Let&#39;s dive into the world of JSON file handling and equip you with the knowledge to tackle this task seamlessly!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/nodejs-read-json-file/01nodejs-read-json-file.jpg&quot; title=&quot;How to Read a JSON File Using Node.js&quot; alt=&quot;How to Read a JSON File Using Node.js&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#prerequisites&quot;&gt;Prerequisites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#example-billionaires-data-from-2023&quot;&gt;Example: Billionaires Data From 2023&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#read-json-file-using-native-fs&quot;&gt;Read JSON File Using Native fs&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#read-json-file-asynchronously-using-fs&quot;&gt;Read JSON File Asynchronously Using fs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#read-json-file-synchronously-using-fs&quot;&gt;Read JSON File Synchronously Using fs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#read-json-file-with-fs-extra-npm-module&quot;&gt;Read JSON File with fs-extra NPM Module&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#read-json-file-async-with-fs-extra&quot;&gt;Read JSON File async with fs-extra&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#read-json-file-sync-with-fs-extra&quot;&gt;Read JSON File sync with fs-extra&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;introduction&quot; tabindex=&quot;-1&quot;&gt;Introduction &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#introduction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;JSON (JavaScript Object Notation) has become a cornerstone of data exchange on the web.  It&#39;s a human-readable format that&#39;s also easily parsed by machines, making it ideal for APIs, configuration files, and more.  If you&#39;re working with Node.js, chances are you&#39;ll encounter JSON files quite frequently.&lt;/p&gt;
&lt;p&gt;This blog post provides a clear, concise, and hands-on guide to reading JSON files in Node.js. Whether you&#39;re a seasoned developer or just starting out, this tutorial will equip you with the knowledge and techniques to handle JSON data confidently in your Node.js projects.&lt;/p&gt;
&lt;p&gt;You will cover two approaches:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Using the native &lt;code&gt;fs&lt;/code&gt; module:&lt;/strong&gt; This is the built-in Node.js module for interacting with the file on the file system. It provides both synchronous and asynchronous methods for reading files.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Using the &lt;code&gt;fs-extra&lt;/code&gt; npm package:&lt;/strong&gt;  This package extends the functionality of the &lt;code&gt;fs&lt;/code&gt; module, offering more user-friendly methods and simplifying common file operations.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;By the end of this tutorial, you&#39;ll have a solid understanding of both methods and be able to choose the approach that best suits your needs.&lt;/p&gt;
&lt;h2 id=&quot;prerequisites&quot; tabindex=&quot;-1&quot;&gt;Prerequisites &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#prerequisites&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before you dive into the code, let&#39;s make sure you have the following prerequisites:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Node.js Installed:&lt;/strong&gt; Ensure that you have Node.js installed on your system. You can download the latest LTS version from the official Node.js website. You will use &lt;strong&gt;Node.js 22&lt;/strong&gt; for this tutorial. You can check your Node.js version with:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Basic JavaScript Knowledge:&lt;/strong&gt; A fundamental understanding of JavaScript syntax and concepts will help you follow along with the code examples.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Code Editor:&lt;/strong&gt; You&#39;ll need a code editor to write and edit your JavaScript code. Some popular choices include VS Code, Atom, Sublime Text, and WebStorm.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For this tutorial, you will use ESM imports and not &lt;code&gt;require&lt;/code&gt; as it is 2024. In the next section, you will learn about the data set of billionaires from 2023, which will be used as an example for this guide.&lt;/p&gt;
&lt;h2 id=&quot;example%3A-billionaires-data-from-2023&quot; tabindex=&quot;-1&quot;&gt;Example: Billionaires Data From 2023 &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#example%3A-billionaires-data-from-2023&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To illustrate how to read a JSON file using Node.js, you will use a real-world example of data about the top 100 billionaires from 2023. The data is sourced from &lt;a href=&quot;https://www.kaggle.com/datasets/nelgiriyewithana/billionaires-statistics-dataset?resource=download&quot;&gt;Kaggle&lt;/a&gt; and provides various details about these individuals. We have curated the data to focus on a few key attributes, making it easier to manage for this tutorial. The data is originally in CSV format, and it has been converted to JSON for this tutorial.&lt;/p&gt;
&lt;p&gt;Here&#39;s a snippet of the JSON data you will use. It is stored in a file named &lt;code&gt;billionaires-2023.json&lt;/code&gt;. The full data file can be found in this &lt;a href=&quot;https://github.com/geshan/nodejs-json&quot;&gt;GitHub repository&lt;/a&gt; , a snippet of the data is shown below for your reference:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;rank&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;worth&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;211000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bernard Arnault &amp;amp; family&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;gender&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;M&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;category&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Fashion &amp;amp; Retail&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;France&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;city&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Paris&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;source&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;LVMH&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;industries&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Fashion &amp;amp; Retail&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;citizenship_country&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;France&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;organization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;LVMH Moët Hennessy Louis Vuitton&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Chairman and CEO&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;birth_year&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1949&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;rank&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;worth&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;180000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Elon Musk&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;gender&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;M&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;category&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Automotive&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;United States&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;city&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Austin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;source&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Tesla, SpaceX&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;industries&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Automotive&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;citizenship_country&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;United States&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;organization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Tesla&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CEO&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;birth_year&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1971&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// ... rest of the billionaires data&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This JSON data represents an array of objects, each of which corresponds to a billionaire and contains attributes like rank, net worth, name, gender, category, country of origin, and more.&lt;/p&gt;
&lt;h2 id=&quot;read-json-file-using-native-fs&quot; tabindex=&quot;-1&quot;&gt;Read JSON File Using Native fs &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#read-json-file-using-native-fs&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The native &lt;a href=&quot;https://nodejs.org/api/fs.html&quot;&gt;fs&lt;/a&gt; module in Node.js provides a straightforward way to interact with the file system. You’ll explore two methods for reading JSON files using &lt;code&gt;fs&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;fs.readFile&lt;/code&gt;: This method reads the entire file asynchronously.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fs.readFileSync&lt;/code&gt;:  This method reads the entire file synchronously.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Using asynchronous methods like &lt;code&gt;fs.readFile&lt;/code&gt; for non-blocking operations is generally advisable, especially when dealing with larger files. This ensures that your application remains responsive while the file is being read.&lt;/p&gt;
&lt;h3 id=&quot;read-json-file-asynchronously-using-fs&quot; tabindex=&quot;-1&quot;&gt;Read JSON File Asynchronously Using fs &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#read-json-file-asynchronously-using-fs&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Below is an example code for reading the data of 2,240 Billionaires in 2023 in an async way using promises.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; readFile &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;node:fs/promises&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;readFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;billionaires-2023.json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;utf8&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//Elon Musk&#39;s data&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Error reading JSON file: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;err&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You import the necessary readFile function from the &lt;code&gt;node:fs/promises&lt;/code&gt; module to work with promises, providing a more modern asynchronous approach.&lt;/li&gt;
&lt;li&gt;Inside the &lt;code&gt;try&lt;/code&gt; block:
&lt;ul&gt;
&lt;li&gt;You read the file asynchronously using &lt;code&gt;await fs.readFile(filePath, &#39;utf8&#39;)&lt;/code&gt;, specifying the encoding as &lt;code&gt;utf8&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The read file&#39;s content is parsed into a JavaScript object using &lt;code&gt;JSON.parse(data)&lt;/code&gt;.&lt;br /&gt;
Then, from the parsed data, the data of the second-rank Billionaire, Elon Musk, is logged on the console.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If an error occurs during the process in the &lt;code&gt;catch&lt;/code&gt; block, it is logged with &lt;code&gt;console.error&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As you are using Node version 22, top-level await is available. You can run the example with &lt;code&gt;node index.js&lt;/code&gt;, it will show the following output:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/nodejs-read-json-file/02nodejs-read-json-file-run.jpg&quot; loading=&quot;lazy&quot; title=&quot;Run read node.js file with native fs module in async way&quot; alt=&quot;Run read node.js file with native fs module in async way&quot; /&gt;
&lt;p&gt;In the next part, you will read the same file with &lt;code&gt;fs&lt;/code&gt; but in a sync way.&lt;/p&gt;
&lt;h3 id=&quot;read-json-file-synchronously-using-fs&quot; tabindex=&quot;-1&quot;&gt;Read JSON File Synchronously Using fs &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#read-json-file-synchronously-using-fs&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;While it&#39;s recommended to use the asynchronous method, for completeness, let&#39;s&lt;br /&gt;
also, see how to read a JSON file synchronously.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; readFileSync &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;node:fs&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;billionaires-2023.json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;utf8&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Elon Musk&#39;s data&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Error reading JSON file: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;err&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This example is similar to the async version, but you use the synchronous &lt;code&gt;readFileSync&lt;/code&gt; method. You should be aware that this method blocks the event loop until the file is read completely. The example file is 2.66 MB, which is not that big, but for a large file, this can be a time-consuming and CPU-hogging operation.&lt;/p&gt;
&lt;h2 id=&quot;read-json-file-with-fs-extra-npm-module&quot; tabindex=&quot;-1&quot;&gt;Read JSON File with fs-extra NPM Module &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#read-json-file-with-fs-extra-npm-module&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;fs-extra&lt;/code&gt; is a popular NPM package that extends the functionality of the native &lt;code&gt;fs&lt;/code&gt; module. According to &lt;a href=&quot;https://npmtrends.com/fs-extra-vs-fs-extra-promise-vs-fs-extra-tf&quot;&gt;NPM Trends&lt;/a&gt;, it has more than 105 million downloads each week. It provides more user-friendly methods for working with the file system, including a convenient method for file system operations, such as reading JSON files.&lt;/p&gt;
&lt;p&gt;To install fs-extra, run the following command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; fs-extra&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, you will look at an example of reading JSON async using the &lt;code&gt;fs-extra&lt;/code&gt; NPM package.&lt;/p&gt;
&lt;h3 id=&quot;read-json-file-async-with-fs-extra&quot; tabindex=&quot;-1&quot;&gt;Read JSON File async with fs-extra &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#read-json-file-async-with-fs-extra&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Here&#39;s an example of reading the JSON file using fs-extra:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; readJson &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;fs-extra/esm&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;readJson&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;billionaires-2023.json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Elon Musk&#39;s data&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Error reading JSON file: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;err&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You import the &lt;code&gt;readJson&lt;/code&gt; function directly from the &#39;fs-extra&#39; package.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;readJson&lt;/code&gt; function handles both reading the file and parsing it into a JavaScript object, simplifying the code.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Next is the example of reading JSON files with Node.js in a sync way using the &lt;code&gt;fs-extra&lt;/code&gt; NPM package.&lt;/p&gt;
&lt;h3 id=&quot;read-json-file-sync-with-fs-extra&quot; tabindex=&quot;-1&quot;&gt;Read JSON File sync with fs-extra &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#read-json-file-sync-with-fs-extra&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can also use &lt;code&gt;readJsonSync&lt;/code&gt; to read the JSON file in a sync manner. Below is an example of using the &lt;code&gt;readJsonSync&lt;/code&gt; function in the &lt;code&gt;fs-extra&lt;/code&gt; NPM package:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; readJsonSync &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;fs-extra/esm&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;readJsonSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;billionaires-2023.json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Elon Musk&#39;s data&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Error reading JSON file: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;err&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is the same example as the above async one; the main difference here is that it reads the file in a sync way.&lt;/p&gt;
&lt;p&gt;Using &lt;code&gt;fs-extra&lt;/code&gt; can significantly reduce code complexity and improve readability, especially when performing common file operations.&lt;/p&gt;
&lt;p&gt;All the code is available in this &lt;a href=&quot;https://github.com/geshan/nodejs-json&quot;&gt;GitHub repository&lt;/a&gt; for your reference.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/nodejs-read-json-file/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this comprehensive guide, you learned how to read JSON files in Node.js using both the native &lt;code&gt;fs&lt;/code&gt; module and the &lt;code&gt;fs-extra&lt;/code&gt; npm package. You explored both asynchronous and synchronous approaches, highlighting their advantages and considerations.&lt;/p&gt;
&lt;p&gt;You also explored a real-world example using billionaires&#39; data to illustrate how to effectively parse and work with JSON data in your Node.js applications. By understanding the concepts and techniques presented in this tutorial, you&#39;re well-equipped to tackle any task that involves reading and manipulating JSON data in your Node.js projects.&lt;/p&gt;
&lt;p&gt;Remember to choose the best method for your needs, considering factors like file size, performance requirements, and your coding style. Keep learning and exploring the power of Node.js to build robust and scalable web applications.&lt;/p&gt;
&lt;p&gt;If you need to process the JSON data you read efficiently, you can read about &lt;a href=&quot;https://geshan.com.np/blog/2021/03/javascript-array-functions/&quot;&gt;JavaScript array functions&lt;/a&gt;. Using &lt;a href=&quot;https://geshan.com.np/blog/2021/02/nodemon/&quot;&gt;nodemon&lt;/a&gt; to automatically restart the Node.js server when you make a code change will also help you become more productive. Happy coding!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Unblocking Software Engineers: Overcoming Non-technical and Technical Roadblocks</title>
		<link href="https://geshan.com.np/blog/2024/10/unblock-software-engineers/"/>
		<updated>2024-10-12T09:35:37Z</updated>
		<id>https://geshan.com.np/blog/2024/10/unblock-software-engineers/</id>
		<content type="html">&lt;p&gt;Writing code is a small part of your job as a software engineer. You will also be communicating and managing expectations. In this post, you will learn about where software engineers get blocked while executing a task and how you (as a product person) can unblock them. You will also figure out ways to unblock yourself as a software engineer. Let’s get started!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/unblock-software-engineers/01unblock-software-engineers.jpg&quot; title=&quot;Where do software engineers get blocked, and how to unblock them (yourself)&quot; alt=&quot;Where do software engineers get blocked, and how to unblock them (yourself)&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#what-to-do-vs-how-to-do-it&quot;&gt;What to do vs how to do it&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#software-engineers-blocked-on-what-to-do&quot;&gt;Software engineers blocked on what to do&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#unblocking-from-non-technical-blockers&quot;&gt;Unblocking from non-technical blockers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#technical-blockers&quot;&gt;Technical blockers&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#getting-unblocked-from-technical-blockers&quot;&gt;Getting unblocked from technical blockers&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#orders-over-1000-issue&quot;&gt;Orders over 1000 issue&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#the-zendesk-library-case-with-an-ssl-issue&quot;&gt;The Zendesk library case with an SSL issue&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#for-things-that-can-wait%2C-stackoverflow-is-your-friend&quot;&gt;For things that can wait, StackOverflow is your friend&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#how-to-unblock-software-engineers-visual-summary&quot;&gt;How to unblock software engineers visual summary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-to-do-vs-how-to-do-it&quot; tabindex=&quot;-1&quot;&gt;What to do vs how to do it &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#what-to-do-vs-how-to-do-it&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For any given feature, what to do and how the feature should work for the customer is always the responsibility of a &lt;a href=&quot;https://www.atlassian.com/agile/product-management/product-manager&quot;&gt;product manager&lt;/a&gt; (or another product person) in the team. Also, prioritization and what to do now (next sprint) falls under the PM’s duty. Regardless of whether the team is following Agile or not, Scrum or Kanban, how a new feature will behave, and the formula to calculate profit in this scenario are questions a product person in the team is liable to answer.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As a software engineer, maintain balance in the “what to do” part. You can provide your input here but don’t step on the PM’s foot and start dictating what the software should do.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On the other hand, the engineering team&#39;s prerogative is how to do a particular feature from a technical point of view. As a software engineer, you have to decide whether to write a single type of test or three types of tests, whether to refactor that 500-line fine and that 100-liner function. All the technical hows of the feature rests on your shoulders. Be careful here; the feature should be functional, and you should also address the performance and security aspects of that particular feature.&lt;/p&gt;
&lt;h2 id=&quot;software-engineers-blocked-on-what-to-do&quot; tabindex=&quot;-1&quot;&gt;Software engineers blocked on what to do &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#software-engineers-blocked-on-what-to-do&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It is common for software engineers to pick up a task (usually a ticket on a task management software like Jira) and realize that the task does not have enough context to get started or make any progress. Tasks without enough description are commonplace, and bugs without steps to reproduce are also typical.&lt;/p&gt;
&lt;p&gt;As a product manager (or product owner), having a clear &lt;a href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/blog/2018/11/5-signs-that-reveal-your-software-development-process-is-agile-only-on-paper-and-solutions-for-them/#unclear-definition-of-ready-for-development-and-done&quot;&gt;definition of ready&lt;/a&gt; to be worked on is required. Another important aspect is that the definition of ready is followed strictly on almost all tasks. For instance, if the definition of ready means a task will have a user story and technical requirements defined, it is the task of the product team to have it filled in on all the tickets.&lt;/p&gt;
&lt;h3 id=&quot;unblocking-from-non-technical-blockers&quot; tabindex=&quot;-1&quot;&gt;Unblocking from non-technical blockers &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#unblocking-from-non-technical-blockers&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;So, how can you, as a product person, unblock the software engineer from taking on a new task or part of a more significant feature? The main thing here is to provide optimal context and examples so that the software engineer has fewer questions and decisions to make. It is better to overcommunicate and provide examples of what to do and how the user will achieve their goals.&lt;/p&gt;
&lt;p&gt;A recent example I remember is when we had to calculate the average cost price of shares. The easiest way for me to understand the logic and formula and then convert the formula into code was to ask for a Google sheet where I could see an example. If the PM can add such artifacts beforehand to the task, it would be much easier for the software engineer to get started.&lt;/p&gt;
&lt;p&gt;From the engineer’s point of view, it is a balancing act, too. You should be able to ask questions to related people for clarity to be a product-minded engineer. On the other hand, the ticket should also have enough context and examples to make your job easier.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Think of it this way: following the Pareto principle, 80% of your what to do questions should already be answered by the description, context, and examples of the task, and for the remaining 20%, you should go in and ask people over Slack or even do a small meeting for that extra clarity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On the contrary, the product and design team must level up their game if you, as a software engineer, need to communicate with three people to get 80% of what to do for a task.&lt;/p&gt;
&lt;p&gt;Sharpening up your people (soft) skills comes into play here. You should know who to talk to, how to get the correct information from that person, and how to unblock yourself aptly. In the next section, you will learn about technical blockers and how to unblock yourself from this category of blockers.&lt;/p&gt;
&lt;h2 id=&quot;technical-blockers&quot; tabindex=&quot;-1&quot;&gt;Technical blockers &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#technical-blockers&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Depending on the software engineer&#39;s level and experience, technical blockers might exist when writing a new feature. Admit it: Even if you have 20 years of experience writing software, you will indeed Google 5+ times a day (or put your query on some LLM like ChatGPT). We all do that.&lt;/p&gt;
&lt;p&gt;The difference is experienced engineers with more than a decade of experience in the language or framework used to build that software will do it under ten times a day. In contrast, less experienced (or junior) engineers will Google/ask an LLM more than ten times a day. In both cases, as long as you find your answer, you are unblocked and can make progress on your task. Sometimes technical blockers are solved faster and more efficiently by stepping away from the screen:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I have seen many programming problems remain unsolved while on a screen; on the contrary, when the engineer moves the problem to a physical board or paper, it gets solved much more quickly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;More senior engineers have called me on a board, and the solution comes faster on a board than being tied to a screen. That&#39;s where, especially for junior and mid-level engineers, the time you spend on a whiteboard teaches you many things. Architecture-level things, like drawing boxes and arrows between them, are best done collaboratively on a physical whiteboard.&lt;/p&gt;
&lt;p&gt;You will also get stuck with technical things in multiple ways; it can be as small as a syntax issue. For instance, you might forget how to use JavaScript&#39;s spread syntax &lt;code&gt;...&lt;/code&gt;. An issue in the library or the framework you use for that project can also block you.  For example, you might need to learn how to do &lt;a href=&quot;https://typeorm.io/transactions&quot;&gt;database transaction&lt;/a&gt; in TypeORM. You can solve many of these blockages with a quick Google search or by asking an LLM. The more difficult technical blockers are the ones that could be more obvious, as discussed next.&lt;/p&gt;
&lt;h3 id=&quot;getting-unblocked-from-technical-blockers&quot; tabindex=&quot;-1&quot;&gt;Getting unblocked from technical blockers &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#getting-unblocked-from-technical-blockers&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Some technical blockers are complex, like reading the language, framework, or library documentation. These are more difficult to unblock your work from. One strategy that works for these blockers is to make the smallest possible change and see if you can move a bit forward. This strategy often works, but sometimes, you must do more than make a small change. Using a debugger property is also a critical skill; if you know the blockage and see all the variables and values while the issue happens, you can block yourself faster.&lt;/p&gt;
&lt;h4 id=&quot;orders-over-1000-issue&quot; tabindex=&quot;-1&quot;&gt;Orders over 1000 issue &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#orders-over-1000-issue&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Once, while I was working for Namshi, around 2015, we faced a bizarre issue. We sometimes got this bug with order total, but it was causing problems. The problem became bigger in busy periods. I don’t remember the specifics, but I was assigned this bug, and it took me days to figure out the issue. I was trying to replicate it again and again. Finally, I cracked the nut; it was a weird formatting issue with one of the PHP functions at that time, which would format numbers wrong only when the order was more than 1000 AED. Using a debugger and finding a way to replicate the issue in my local environment helped me figure out the solution.&lt;/p&gt;
&lt;h4 id=&quot;the-zendesk-library-case-with-an-ssl-issue&quot; tabindex=&quot;-1&quot;&gt;The Zendesk library case with an SSL issue &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#the-zendesk-library-case-with-an-ssl-issue&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Sometimes, you find yourself in a situation where no one deployed any new code. It was working yesterday, and today, it is not working. Most likely, in such cases, a third-party library has stopped working. One example from mid-2018 is when a system communicated with Zendesk using its APIs.&lt;/p&gt;
&lt;p&gt;One fine morning, it started throwing unusual errors, and we had not deployed any change to the system for over a week. So, it was clear that the issue was not in the code we had written but something with a third-party library or a thing out of our control. On investigating deeper, it turned out to be an SSL &lt;a href=&quot;https://github.com/blakmatrix/node-zendesk/issues/221&quot;&gt;issue&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The quickest thing I did to unblock was to fork the &lt;a href=&quot;https://github.com/blakmatrix/node-zendesk&quot;&gt;Node.js Zendesk library&lt;/a&gt; we were using and &lt;a href=&quot;https://github.com/blakmatrix/node-zendesk/pull/222&quot;&gt;patch&lt;/a&gt; the issue. After that, use the patched fork in our code base. The app was down for a couple of hours. Due to the time zone, the main library accepted the patch later that day. The next day, we moved back to the patched version of the library.&lt;/p&gt;
&lt;h4 id=&quot;for-things-that-can-wait%2C-stackoverflow-is-your-friend&quot; tabindex=&quot;-1&quot;&gt;For things that can wait, StackOverflow is your friend &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#for-things-that-can-wait%2C-stackoverflow-is-your-friend&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;I am not very active on StackOverflow (anymore), but I used to read things there. As a software engineer, you Google things, and most of the time, you find a solution on StackOverflow.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Our CTO used to say, &amp;quot;This is surely not a unique issue. Someone would have surely faced this, and most likely, you will find a similar question and a useful answer on StackOverflow.&amp;quot; He was correct.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I have asked some questions on StackOverflow and got answers in days. One of them is about the &lt;a href=&quot;https://stackoverflow.com/questions/16784996/how-to-show-null-value-in-json-in-fos-rest-bundle-with-jms-serializer&quot;&gt;FOS Rest bundle&lt;/a&gt; and its serializer 11 years back (viewed more than 15K times now). The main thing to extract from here is don’t stop searching and asking things on StackOverflow, even in this age of LLMs. You don’t know a human might provide a different perspective and a handy solution to your problem.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;On a different note, I would not consider open pull requests (or waiting for code review) a blockage. It is part of a good software engineering process that teaches you a lot about code, engineering, and writing software that will work well in production.&lt;/p&gt;
&lt;h2 id=&quot;how-to-unblock-software-engineers-visual-summary&quot; tabindex=&quot;-1&quot;&gt;How to unblock software engineers visual summary &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#how-to-unblock-software-engineers-visual-summary&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here is a quick visual summary of how to unblock software engineers from non-technical and technical blockers:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/unblock-software-engineers/02unblock-sw-eng.jpg&quot; title=&quot;How to unblock software engineers from non-technical and technical blockers&quot; alt=&quot;How to unblock software engineers from non-technical and technical blockers&quot; /&gt;
&lt;p&gt;Slides:&lt;/p&gt;
&lt;script defer=&quot;&quot; class=&quot;speakerdeck-embed&quot; data-id=&quot;b9286550cc0940de99cbc21a769e9733&quot; data-ratio=&quot;1.791044776119403&quot; src=&quot;https://speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/10/unblock-software-engineers/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Software engineers at any level and in any company will get blocked from doing their work in non-technical or technical ways.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The focus should be on reducing the blocked time to increase the productivity of the software engineers and, eventually, the company’s productivity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This blog post discusses how to unblock software engineers from roadblocks while working on new features. It stresses providing context and examples, addressing technical and non-technical blockers, using debuggers, and making small changes. The goal is to help product people and engineers work together effectively, leading to smoother development processes and successful products.&lt;/p&gt;
&lt;p&gt;When you are blocked, think outside the box and make the smallest possible change to make a tiny but valuable progress. Also, don’t hesitate to use the power of the community on platforms like StackOverflow. Keep writing fantastic software while minimizing both non-technical and technical blockers.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to mock Date in Jest: the easiest way without installing any extra NPM package</title>
		<link href="https://geshan.com.np/blog/2024/09/jest-mock-date/"/>
		<updated>2024-09-26T08:48:37Z</updated>
		<id>https://geshan.com.np/blog/2024/09/jest-mock-date/</id>
		<content type="html">&lt;p&gt;When writing unit tests for your JavaScript code, especially when dealing with time-dependent functionalities, it&#39;s crucial to control and mock the behavior of the native &lt;code&gt;Date&lt;/code&gt; object. This ensures that your tests are deterministic and produce consistent results regardless of the current date and time. In this guide, you&#39;ll learn the easiest way to mock &lt;code&gt;Date&lt;/code&gt; in Jest without installing any extra NPM packages. This approach leverages Jest&#39;s built-in mocking capabilities with Fake timers and setting the system date, making it simple and efficient to control the time within your tests. Let’s get started!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/jest-mock-date/01jest-mock-date.jpg&quot; title=&quot;How to mock Date in Jest: the easiest way without installing any extra NPM package&quot; alt=&quot;How to mock Date in Jest: the easiest way without installing any extra NPM package&quot; /&gt;
&lt;h2 id=&quot;table-of-contents&quot; tabindex=&quot;-1&quot;&gt;Table of contents &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/09/jest-mock-date/#table-of-contents&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/09/jest-mock-date/#introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/09/jest-mock-date/#testing-native-date-functions-is-not-easy&quot;&gt;Testing native Date functions is not easy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/09/jest-mock-date/#mock-date-with-jest-26&quot;&gt;Mock Date with Jest 26&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/09/jest-mock-date/#day-of-the-year-example&quot;&gt;Day of the year example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/09/jest-mock-date/#test-for-the-day-of-the-year-example&quot;&gt;Test for the day of the year example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/09/jest-mock-date/#other-options-to-mock-date-in-jest&quot;&gt;Other options to mock date in Jest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geshan.com.np/blog/2024/09/jest-mock-date/#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;testing-native-date-functions-is-not-easy&quot; tabindex=&quot;-1&quot;&gt;Testing native Date functions is not easy &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/09/jest-mock-date/#testing-native-date-functions-is-not-easy&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Testing code that interacts with the native &lt;code&gt;Date&lt;/code&gt; object can be challenging because the &lt;code&gt;Date&lt;/code&gt; object is inherently dynamic. Its value changes with every passing millisecond, making it difficult to write deterministic tests. Imagine you have a function that shows the day of the year, if you run this function today (on 26-Sep) it will show 270 (out of 365) but if you run it tomorrow it will show 271 (out of 365). This means the test cannot be repeatable unless the system date is mocked and set to a defined date.&lt;/p&gt;
&lt;p&gt;Furthermore, the native &lt;code&gt;Date&lt;/code&gt; object is a global object in JavaScript, meaning that any changes made to it within one test can potentially affect other tests, leading to unexpected and inconsistent results. This can make debugging and troubleshooting your tests very hard. So how can we solve this issue, enter Fake timers, and set system date in Jest 26+, which is discussed next.&lt;/p&gt;
&lt;h2 id=&quot;mock-date-with-jest-26&quot; tabindex=&quot;-1&quot;&gt;Mock Date with Jest 26 &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/09/jest-mock-date/#mock-date-with-jest-26&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://jestjs.io/&quot;&gt;Jest&lt;/a&gt; is the &lt;a href=&quot;https://2023.stateofjs.com/en-US/libraries/testing/&quot;&gt;most popular&lt;/a&gt; JavaScript testing framework. It provides powerful mocking capabilities that make it easy to control and manipulate the behavior of the native &lt;code&gt;Date&lt;/code&gt; object within your tests. With &lt;a href=&quot;https://github.com/jestjs/jest/releases/tag/v26.0&quot;&gt;Jest 26&lt;/a&gt; (released in May-2020) and later versions, you can directly mock the &lt;code&gt;Date&lt;/code&gt; object without relying on any external libraries or complex workarounds. This approach is simple, efficient, and ensures that your tests are deterministic and produce consistent results.&lt;/p&gt;
&lt;h2 id=&quot;day-of-the-year-example&quot; tabindex=&quot;-1&quot;&gt;Day of the year example &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/09/jest-mock-date/#day-of-the-year-example&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To illustrate how you can mock the Date object with Jest, let&#39;s use an example. You will create a simple yet useful function that will return the day of the year, so if you run it on 1-Jan it will return 1 and if you run it on 20-Dec it will return 354 (not taking into account Leap year for now). Simple enough right? You might think what the use case for this Year to Date - Day is, it can be used in various ways like the price chart below I got by searching “nvidia stock price” :&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/jest-mock-date/02jest-mock-date-ytd.jpg&quot; loading=&quot;lazy&quot; title=&quot;Year to Date (YTD) used in stock price chart for Nvidia&quot; alt=&quot;Year to Date (YTD) used in stock price chart for Nvidia&quot; /&gt;
&lt;p&gt;It has a YTD option that shows the price from 2-Jan to today. It will be updated every day. So your task is to get the number of the day in the year.&lt;/p&gt;
&lt;p&gt;To get this task done you will use JavaScript (Node.js) and the code can look like the below in a file named &lt;code&gt;dateHelper.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getDayOfYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; today &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//logic taken from https://stackoverflow.com/a/40975730 then modified&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; todayInMs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;UTC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;today&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFullYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; today&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getMonth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; today&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//today in milliseconds&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; startOfYearInMs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;UTC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;today&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFullYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; diffInMs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; todayInMs &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; startOfYearInMs&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; msInOneMinute &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; msInOneHour &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; msInOneMinute &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; msInOneDay &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; msInOneHour &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;  diffInMs  &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; msInOneDay&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It looks long but nothing complicated is happening in the above code, it was originally a one liner on a &lt;a href=&quot;https://stackoverflow.com/a/40975730&quot;&gt;Stack Overflow answer&lt;/a&gt;, It has been modified to look like the above.&lt;/p&gt;
&lt;p&gt;First, you get today’s system date with &lt;code&gt;new Date()&lt;/code&gt;, then you convert today’s date in milliseconds. Similarly, you convert the start of the year’s date to milliseconds. Then subtract those two by doing today’s date in milliseconds - start of the year in milliseconds. After that, you convert the difference which is in milliseconds to days, dividing it by &lt;code&gt;1000 * 60 * 60 * 24&lt;/code&gt;, which has been illustrated in 3 lines to make it clearer. With this you get a number, for example, &lt;code&gt;270&lt;/code&gt; if you run the above code on 26-Sep.&lt;/p&gt;
&lt;p&gt;If you run this code with:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; getDayOfYear &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;./src/dateHelper.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Today is day &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDayOfYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; / 365 days of this year &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFullYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will give out:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;Today is day &lt;span class=&quot;token number&quot;&gt;270&lt;/span&gt; / &lt;span class=&quot;token number&quot;&gt;365&lt;/span&gt; days of this year &lt;span class=&quot;token number&quot;&gt;2024&lt;/span&gt;.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above code was run on 26-Sep. Next, you will write repeatable tests for the above &lt;code&gt;getDayOfYear&lt;/code&gt; function that will pass not only today but on any day of the year.&lt;/p&gt;
&lt;h2 id=&quot;test-for-the-day-of-the-year-example&quot; tabindex=&quot;-1&quot;&gt;Test for the day of the year example &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/09/jest-mock-date/#test-for-the-day-of-the-year-example&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now, to write a unit test for the above code with Jest it is straightforward. The issue is if you run the test tomorrow (27-Sep) your assertion of 270th day of the year fails. The date changes every day, so you can write a test like the day of the year is greater than 0 and less than 365 but that test is quite useless.&lt;/p&gt;
&lt;p&gt;This is where the power of mocking the date, or say stubbing it to be one particular date comes very handy. To do this you can use the following unit test code:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; getDayOfYear &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;../src/dateHelper.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;dateHelper - Jest 26+&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;//Jest 26 was released in May 2020, ref: https://github.com/jestjs/jest/releases/tag/v26.0.0&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;getDayOfYear&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;beforeEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;useFakeTimers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setSystemTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;2024-01-07&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;afterEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setSystemTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getRealSystemTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;useRealTimers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;should return 7 for 7-Jan as set with fake timers and system date&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;      &lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getDayOfYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Keep this test file in the &lt;code&gt;test&lt;/code&gt; folder named as &lt;code&gt;dateHelper.test.js&lt;/code&gt;, the &lt;code&gt;dateHelper.js&lt;/code&gt; file is in the &lt;code&gt;src&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;First, you import the &lt;code&gt;getDayOfYear&lt;/code&gt; function from the module, yes this is ES6 import (not the common js require). Then you write the test code, the main point to consider here is in the &lt;a href=&quot;https://geshan.com.np/blog/2022/06/jest-beforeeach/&quot;&gt;Jest beforeEach&lt;/a&gt; you stub/mock the date to &lt;code&gt;7-Jan-2024&lt;/code&gt;. To do this you use, &lt;a href=&quot;https://jestjs.io/docs/timer-mocks#enable-fake-timers&quot;&gt;Jest FakeTimers&lt;/a&gt;. With these timer mocks Jest can swap out timers with functions that allow you to control the passage of time. Then you set the system time to be &lt;code&gt;7-Jan-2024&lt;/code&gt;. That is exactly what you need for your tests to be repeatable and reliable.&lt;/p&gt;
&lt;p&gt;In the after each section for these tests, you reset the system time to be the actual time and also use real timers for the other tests outside that describe block. You certainly don’t want to mess up other tests outside that describe block and even that test file.&lt;/p&gt;
&lt;p&gt;When you run the above test it will show the following output:&lt;/p&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/jest-mock-date/03jest-mock-date-test-run.jpg&quot; loading=&quot;lazy&quot; title=&quot;Results of the test run for Jest mock date&quot; alt=&quot;Results of the test run for Jest mock date&quot; /&gt;
&lt;p&gt;Now you run it today, tomorrow, or any day of the year it will still pass. Why? Because for that test the system date is always fixed to &lt;code&gt;7-Jan-2024&lt;/code&gt; as the date has been mocked with fake timers and set system date in Jest to mock the real date.&lt;/p&gt;
&lt;p&gt;You can find the full code in this &lt;a href=&quot;https://github.com/geshan/jest-mock-date-example&quot;&gt;GitHub repository&lt;/a&gt; for your reference.&lt;/p&gt;
&lt;h2 id=&quot;other-options-to-mock-date-in-jest&quot; tabindex=&quot;-1&quot;&gt;Other options to mock date in Jest &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/09/jest-mock-date/#other-options-to-mock-date-in-jest&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are other options to mock the date in Jest. If you are using a Jest version of less than 26 you can use &lt;a href=&quot;https://www.meticulous.ai/blog/how-to-use-jest-spyon#what-is-jest-spyon&quot;&gt;Jest SpyOn&lt;/a&gt; to mock the global Date object. It is neither easy nor the code is clean but that is a way of doing it. Frankly, you should be using Jest 26+ as version 26 was released more than 4 years ago in May 2020&lt;/p&gt;
&lt;p&gt;You can also use &lt;a href=&quot;https://www.npmjs.com/package/jest-date-mock&quot;&gt;jest-mock-date&lt;/a&gt; NPM package. Which has 270K+ downloads each week at the time of writing this. But if you can do it with Jest and fake timers/set system date, I think that opton is far better.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/09/jest-mock-date/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this guide, you&#39;ve learned the easiest and most efficient way to mock the &lt;code&gt;Date&lt;/code&gt; object in Jest without installing any extra NPM packages. This approach leverages Jest&#39;s built-in mocking capabilities, making it simple to control date/time within your tests with fake timers and set system date. You&#39;ve also seen a practical example of how to use &lt;code&gt;Date&lt;/code&gt; mocking to write deterministic tests for date-dependent code.&lt;/p&gt;
&lt;p&gt;Go ahead, embrace Jest&#39;s &lt;code&gt;Date&lt;/code&gt; mocking, and elevate your testing game to the next level!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to create a YouTube video chapters&#39; timings generator using Gemini over Vertex AI</title>
		<link href="https://geshan.com.np/blog/2024/09/youtube-chapters-timings-generator-gemini-vertex-ai/"/>
		<updated>2024-09-06T08:45:37Z</updated>
		<id>https://geshan.com.np/blog/2024/09/youtube-chapters-timings-generator-gemini-vertex-ai/</id>
		<content type="html">&lt;p&gt;While watching a long YouTube video have you felt like it would have been great to have relevant chapters? Especially for long podcasts or talks, you want to jump to the part that is most important and relevant to you but you need to pull the progress bar here and there to get to the crucial part. In this blog post, you will create a YouTube video chapters timing generator using Google’s Gemini LLM over Vertex AI, let’s get going!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;img class=&quot;center&quot; src=&quot;https://geshan.com.np/images/youtube-chapters-timings-generator/01youtube-chapters-timings-generator.jpg&quot; title=&quot;How to create a YouTube video chapters&#39; timings generator using Gemini over Vertex AI&quot; alt=&quot;How to create a YouTube video chapters&#39; timings generator using Gemini over Vertex AI&quot; /&gt;
&lt;h2 id=&quot;youtube-video-chapters-a-huge-time-saver&quot; tabindex=&quot;-1&quot;&gt;YouTube video chapters a huge time-saver &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/09/youtube-chapters-timings-generator-gemini-vertex-ai/#youtube-video-chapters-a-huge-time-saver&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It is no secret that YouTube &lt;a href=&quot;https://support.google.com/youtube/answer/9884579?hl=en&quot;&gt;video chapters&lt;/a&gt; is a huge time saver for your audience. Be it a long 2-hour podcast or a 40-minute talk video if the video has relevant chapters your audience can jump to the parts that are most meaningful for them.&lt;/p&gt;
&lt;p&gt;Creating chapter data manually is a tedious and time-consuming task. You will need to sit down with something to take notes be it pen and paper or your mobile phone’s notes app. Then play the video and move the progress bar here and there to note down the timings from the video to list them down as chapters. What if there was an automated and easier way to do this, why can’t an LLM like Gemini which now has a 2 million context window?&lt;/p&gt;
&lt;p&gt;In February, the 1M context window for Gemini 1.5 pro could process 1 hour of video so with a 2M context window it should be able to process 2 hours of content. Even Gemini 1.5 flash has a 1M context window. So, technically your YouTube video could be 2 hours long and Gemini 1.5 Pro with the 2M context window should be able to generate chapter timings for it.&lt;/p&gt;
&lt;h2 id=&quot;prerequisites&quot; tabindex=&quot;-1&quot;&gt;Prerequisites &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/09/youtube-chapters-timings-generator-gemini-vertex-ai/#prerequisites&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To begin, you will need to have the following pre-requisites sorted:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have a working Google Cloud Account (with some credit, processing long videos requires some GCP credit)&lt;/li&gt;
&lt;li&gt;Have at least one video on your YouTube account that you want to generate chapter data for&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It will be wise to be aware of &lt;a href=&quot;https://cloud.google.com/vertex-ai/generative-ai/pricing&quot;&gt;Vertex AI Pricing&lt;/a&gt; with the models on offer.&lt;/p&gt;
&lt;p&gt;Next, you will create a GCP project to build your YouTube video chapter timings generator. You need 10-20 minutes to create the basic version and have a proof of concept code for it as shown below.&lt;/p&gt;
&lt;h2 id=&quot;vertex-ai-on-your-gcp-project&quot; tabindex=&quot;-1&quot;&gt;Vertex AI on your GCP Project &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/09/youtube-chapters-timings-generator-gemini-vertex-ai/#vertex-ai-on-your-gcp-project&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Below are the steps to create a new GCP project (if you have an existing one you can use that too).&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to your Google Cloud Console and &lt;a href=&quot;https://console.cloud.google.com/projectcreate&quot;&gt;Create a new project&lt;/a&gt; called &lt;code&gt;yt-chapters&lt;/code&gt; or anything relevant as seen below:&lt;/li&gt;
&lt;/ol&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/youtube-chapters-timings-generator/02new-gcp-project.jpg&quot; title=&quot;Create a new GCP project for YouTube video chapters&#39; timings generator using Gemini over Vertex AI&quot; alt=&quot;How to create a YouTube video chapters&#39; timings generator using Gemini over Vertex AI&quot; /&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;
&lt;p&gt;Make sure you have selected the project created in Step 1 if you have multiple projects. You can do this by clicking on the project name on the top left corner of your Google Cloud Console.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Go to Vertex AI from your Google Cloud Console, the easiest way to do it would be to search for &lt;code&gt;vertex&lt;/code&gt; on the search bar as seen below:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/youtube-chapters-timings-generator/03search-vertex.jpg&quot; title=&quot;Search for vertex and click Vertex AI&quot; alt=&quot;Search for vertex and click Vertex AI&quot; /&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Click on &lt;code&gt;Vertex AI&lt;/code&gt; 5. On the Vertex AI page, then click &amp;quot;Agree &amp;amp; Continue&amp;quot; as seen below :&lt;/li&gt;
&lt;/ol&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/youtube-chapters-timings-generator/04vertex-agree.jpg&quot; title=&quot;Click on agree and continue on Vertex AI page&quot; alt=&quot;Click on agree and continue on Vertex AI page&quot; /&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;After that on the Vertext AI page click on “Enable All Recommended APIS” as follows (it will take some time):&lt;/li&gt;
&lt;/ol&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/youtube-chapters-timings-generator/05vertex-enable-apis.jpg&quot; title=&quot;Enable recommened APIs on Vertex AI page&quot; alt=&quot;Enable recommened APIs on Vertex AI page&quot; /&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;After the APIs are enabled, click on &lt;code&gt;Freeform&lt;/code&gt; found on the left menu&lt;/li&gt;
&lt;/ol&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/youtube-chapters-timings-generator/06vertex-freeform.jpg&quot; title=&quot;Go to Freeform on Vertex AI page&quot; alt=&quot;Go to Freeform on Vertex AI page&quot; /&gt;
&lt;h2 id=&quot;crafting-the-prompt&quot; tabindex=&quot;-1&quot;&gt;Crafting the prompt &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/09/youtube-chapters-timings-generator-gemini-vertex-ai/#crafting-the-prompt&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ol start=&quot;7&quot;&gt;
&lt;li&gt;Now you can add a prompt in the &lt;code&gt;Prompt&lt;/code&gt; text box that will generate the YouTube video chapter timings as follows:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;Please provide relevant chapter information to put on YouTube 
description for this video with timings for the start of the chapter
and do not add any formatting. If you are not sure about any info,
please do not make it up. Give the output with the timings first and
the chapter name after that.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can edit the prompt to suit your needs.&lt;/p&gt;
&lt;ol start=&quot;8&quot;&gt;
&lt;li&gt;Then turn off the &lt;code&gt;Markdown&lt;/code&gt; slider and keep your mouse cursor at the start of the prompt. You can only use your own YouTube videos (or you get the following error “Must enter a YouTube video that you own”), to link the YouTube Video click on &lt;code&gt;Insert Media&lt;/code&gt; and select the &lt;code&gt;YouTube video URL&lt;/code&gt; option as follows:&lt;/li&gt;
&lt;/ol&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/youtube-chapters-timings-generator/07vertex-link-youtube-video.jpg&quot; title=&quot;Link YouTube video with Vertex AI to use with Gemini&quot; alt=&quot;Link YouTube video with Vertex AI to use with Gemini&quot; /&gt;
&lt;ol start=&quot;9&quot;&gt;
&lt;li&gt;After that, paste the URL of a video that you is on your channel and then click the &lt;code&gt;Validate&lt;/code&gt; button, once the ownership is verified you can &lt;code&gt;Insert&lt;/code&gt; the video as follows:&lt;/li&gt;
&lt;/ol&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/youtube-chapters-timings-generator/08vertex-insert-youtube-video.jpg&quot; title=&quot;Insert YouTube video with Vertex AI to use with Gemini&quot; alt=&quot;Insert YouTube video with Vertex AI to use with Gemini&quot; /&gt;
&lt;ol start=&quot;10&quot;&gt;
&lt;li&gt;Given your YouTube video is included in the prompt it will look like the below:&lt;/li&gt;
&lt;/ol&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/youtube-chapters-timings-generator/09video-added-to-prompt.jpg&quot; title=&quot;YouTube video added to Vertex AI prompt to use with Gemini Flash&quot; alt=&quot;YouTube video added to Vertex AI prompt to use with Gemini Flash&quot; /&gt;
&lt;h2 id=&quot;saving-the-prompt&quot; tabindex=&quot;-1&quot;&gt;Saving the prompt &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/09/youtube-chapters-timings-generator-gemini-vertex-ai/#saving-the-prompt&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ol start=&quot;11&quot;&gt;
&lt;li&gt;At this point you can save your prompt for further use, to save it click on &lt;code&gt;Save&lt;/code&gt; on the top right corner and give it a name like &lt;code&gt;yt-timings&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/youtube-chapters-timings-generator/10vertex-save-prompt.jpg&quot; title=&quot;Save prompt on Vertex AI to reuse later&quot; alt=&quot;Save prompt on Vertex AI to reuse later&quot; /&gt;
&lt;p&gt;You can use the saved prompt from the &lt;code&gt;Saved Prompts&lt;/code&gt; tab on the left menu later.&lt;/p&gt;
&lt;h2 id=&quot;configuring-the-model-and-parameters&quot; tabindex=&quot;-1&quot;&gt;Configuring the model and parameters &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/09/youtube-chapters-timings-generator-gemini-vertex-ai/#configuring-the-model-and-parameters&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ol start=&quot;12&quot;&gt;
&lt;li&gt;Let’s look into the configuration a bit, First select &lt;code&gt;gemini-1.5-flash-001&lt;/code&gt; as the model. if you want the chapter timings to be less random you can set the temperature to be &lt;code&gt;0.1&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/youtube-chapters-timings-generator/11vertex-model-temp.jpg&quot; title=&quot;Select Gemini Flash and set temprature to 0.1&quot; alt=&quot;Select Gemini Flash and set temprature to 0.1&quot; /&gt;
&lt;ol start=&quot;13&quot;&gt;
&lt;li&gt;It will be good to play around with the &lt;code&gt;Advanced&lt;/code&gt; config of &lt;code&gt;Top-p&lt;/code&gt; to fine-tune your result. I used &lt;code&gt;0.5&lt;/code&gt; and it worked well for me:&lt;/li&gt;
&lt;/ol&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/youtube-chapters-timings-generator/12gemini-flash-top-p.jpg&quot; title=&quot;Set Gemini Flash top p to 0.5&quot; alt=&quot;Set Gemini Flash top p to 0.5&quot; /&gt;
&lt;p&gt;You can learn more about the configuration like temperature, top-K, etc in this blog post about &lt;a href=&quot;https://geshan.com.np/blog/2024/04/gemini-ecommerce-product-description-generator/#gemini-configurations&quot;&gt;Product description generator&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;generating-and-saving-chapter-information&quot; tabindex=&quot;-1&quot;&gt;Generating and saving chapter information &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/09/youtube-chapters-timings-generator-gemini-vertex-ai/#generating-and-saving-chapter-information&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ol start=&quot;14&quot;&gt;
&lt;li&gt;I am not covering safety settings for this tutorial. Now you can click on the &lt;code&gt;&amp;gt;&lt;/code&gt; button to see what chapter timings Gemini Flash generates for your video, keep in mind depending on the length of the video it will take time and also use up your Google Cloud Credit:&lt;/li&gt;
&lt;/ol&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/youtube-chapters-timings-generator/13chapters-timings-generated.jpg&quot; title=&quot;Prompt on Vertex AI with Gemini Flash worked to generate YouTube Video chatpers&#39; timings&quot; alt=&quot;Prompt on Vertex AI with Gemini Flash worked to generate YouTube Video chatpers&#39; timings&quot; /&gt;
&lt;p&gt;It took a minute or more for me to get the response.&lt;/p&gt;
&lt;ol start=&quot;15&quot;&gt;
&lt;li&gt;Now you can copy the response and paste it on your YouTube video description in YouTube Studio, save it and your viewers can benefit from the “generated” chapter information&lt;/li&gt;
&lt;/ol&gt;
&lt;img class=&quot;center&quot; loading=&quot;lazy&quot; src=&quot;https://geshan.com.np/images/youtube-chapters-timings-generator/14update-video-desc.jpg&quot; title=&quot;Update video description on YouTube Studio with chapters&#39; timings information&quot; alt=&quot;Update video description on YouTube Studio with chapters&#39; timings information&quot; /&gt;
&lt;p&gt;This is the &lt;a href=&quot;https://www.youtube.com/watch?v=L5DN8ztZ3Ko&quot;&gt;video&lt;/a&gt; I used for this tutorial and I did edit the chapter’s information a bit to make it better. You can delete the video from the prompt and link another YouTube video then generate the chapter information for that one too.&lt;/p&gt;
&lt;p&gt;Amazing! There you have a fully reusable YouTube video chapter timings generator using your own YouTube video. For all the experiments I did to generate video chapter timings using Gemini Flash over Vertext AI it cost me 35 cents. Google Cloud credits are provided for this project and blog post, thanks to Google for that, it is part of the #AISprint .&lt;/p&gt;
&lt;p&gt;As LLMs give out probabilistic output than deterministic, the output is a good starting point. As a human, you will need to crosscheck and edit the output to fit your needs. The same thing applies to the chapter information generated by Gemini.&lt;/p&gt;
&lt;p&gt;I used it for a podcast video and interestingly enough it can generate chapter information even when there are no visual queues in the video. So it can use the transcribed captions too for generating the chapter information. This was the &lt;a href=&quot;https://www.youtube.com/watch?v=hU3rjY0MRVc&quot;&gt;podcast video&lt;/a&gt; I used to generate chapters.&lt;/p&gt;
&lt;p&gt;You can also click the &lt;code&gt;Get Code&lt;/code&gt; and play around with it, you can look at an example of generating and running the code in this &lt;a href=&quot;https://geshan.com.np/blog/2024/04/gemini-ecommerce-product-description-generator/#run-generated-python-code&quot;&gt;example&lt;/a&gt; with Gemini and Vertex AI.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://geshan.com.np/blog/2024/09/youtube-chapters-timings-generator-gemini-vertex-ai/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this blog post, you created a YouTube video chapter timings generator using Gemini Flash over Vertext AI. If your videos are longer you can use Gemini Pro which has a 2 million context window and it is more expensive than the Flash version.&lt;/p&gt;
&lt;p&gt;You started by creating a prompt useful to generate video chapter timings and used it to generate chapters for one video.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Take this as scratching the surface, as the LLM has the context of the video’s content you can also craft a prompt to generate a compelling and SEO-optimized video description.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Use AI as a tool to simplify your day-to-day tasks. Keep exploring and learning!&lt;/p&gt;
</content>
	</entry>
</feed>
