<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Firat</title>
    <description>The latest articles on DEV Community by Firat (@firatkiral).</description>
    <link>https://dev.to/firatkiral</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F664013%2F19485e6b-b243-4d37-8c2f-767a93680656.jpeg</url>
      <title>DEV Community: Firat</title>
      <link>https://dev.to/firatkiral</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/firatkiral"/>
    <language>en</language>
    <item>
      <title>What are Glue Records?</title>
      <dc:creator>Firat</dc:creator>
      <pubDate>Sat, 20 Sep 2025 09:10:35 +0000</pubDate>
      <link>https://dev.to/firatkiral/what-are-glue-records-9jf</link>
      <guid>https://dev.to/firatkiral/what-are-glue-records-9jf</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Understanding Glue Records in DNS&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Glue records are special DNS records that resolve a "chicken and egg" problem in the Domain Name System (DNS). They are essentially IP addresses for name servers that are part of the same domain, published in the parent zone or by the domain registrar.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Domain Name System (DNS) Works
&lt;/h3&gt;

&lt;p&gt;When you type a domain name into your web browser, the DNS system translates that domain name into an IP address that computers use to identify each other on the network. This translation is done by querying a series of DNS servers, starting from the root servers down to the authoritative name servers for the domain.&lt;/p&gt;

&lt;p&gt;All domain names must have at least two name servers for redundancy and reliability. These name servers are typically specified in the domain's DNS records. But if you want to use name servers that are part of your own domain (e.g., &lt;code&gt;ns1.yourdomain.com&lt;/code&gt; and &lt;code&gt;ns2.yourdomain.com&lt;/code&gt;), you need glue records to ensure that the DNS resolution process can find these name servers. Otherwise, the DNS resolver would try to resolve the name server's domain name, looking for the name server itself, leading to a circular dependency.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DNS resolver looks up &lt;code&gt;yourdomain.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;It query the parent zone (e.g., &lt;code&gt;.com&lt;/code&gt;) for the name servers of &lt;code&gt;yourdomain.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The parent zone responds with &lt;code&gt;ns1.yourdomain.com&lt;/code&gt; and &lt;code&gt;ns2.yourdomain.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Along with the name servers, the parent zone also provides glue records (IP addresses) for &lt;code&gt;ns1.yourdomain.com&lt;/code&gt; and &lt;code&gt;ns2.yourdomain.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The DNS resolver can now directly contact &lt;code&gt;ns1.yourdomain.com&lt;/code&gt; and &lt;code&gt;ns2.yourdomain.com&lt;/code&gt; using the provided IP addresses to get the DNS records for yourdomain.com&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use Cases for Glue Records
&lt;/h3&gt;

&lt;p&gt;Glue records are typically used in the following scenarios:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hosting Your Own Name Servers:&lt;/strong&gt; If you want to run your own DNS servers for your domain, you will need glue records to ensure that other DNS resolvers can find your name servers.&lt;br&gt;
&lt;strong&gt;Subdomains as Name Servers:&lt;/strong&gt; If you want to use subdomains of your main domain as name servers (e.g., &lt;code&gt;ns1.subdomain.yourdomain.com&lt;/code&gt;), glue records are necessary to avoid circular dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Glue records are essential for the proper functioning of DNS when using name servers that are part of the same domain. They help resolve circular dependencies and ensure that DNS resolvers can find the necessary name servers to translate domain names into IP addresses. If you plan to host your own name servers or use subdomains as name servers, make sure to set up glue records with your domain registrar.&lt;/p&gt;

</description>
      <category>dns</category>
      <category>server</category>
      <category>domain</category>
      <category>nameserver</category>
    </item>
    <item>
      <title>How to Setup Secure Email Server</title>
      <dc:creator>Firat</dc:creator>
      <pubDate>Sat, 20 Sep 2025 09:04:54 +0000</pubDate>
      <link>https://dev.to/firatkiral/how-to-setup-secure-email-server-2i1p</link>
      <guid>https://dev.to/firatkiral/how-to-setup-secure-email-server-2i1p</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Learn how to set up your own email server using Mail-in-a-Box on a fresh Ubuntu server.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You are already aware of all challenges and responsibilities of running a secure email server and you still want to have your own email server. That's great! This guide will help you set up a secure email server.&lt;/p&gt;

&lt;p&gt;In this tutorial, we'll use open-source email server software called Mail-in-a-Box. It's a batteries-included solution for setting up a mail server on a fresh Ubuntu server. It provides all basic features like webmail, calender, contacts, spam filtering, etc. out of the box. You can start using emails with your own domain right away after the setup.&lt;/p&gt;

&lt;h4&gt;
  
  
  Prerequisites
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;A fresh Ubuntu 22.04 server (a VPS from any provider will do).&lt;/li&gt;
&lt;li&gt;A domain name (you can buy one from any domain registrar).&lt;/li&gt;
&lt;li&gt;Basic knowledge of using the terminal and SSH.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Step 1: Prepare Your Server
&lt;/h4&gt;

&lt;p&gt;I'll use &lt;a href="https://www.digitalocean.com/?refcode=8ceab51000e3&amp;amp;utm_campaign=Referral_Invite&amp;amp;utm_medium=Referral_Program&amp;amp;utm_source=badge" rel="noopener noreferrer"&gt;DigitalOcean&lt;/a&gt; droplets for this tutorial, but you can use any VPS provider with port 25 unblocked. Most of them block port 25 to prevent spam, so make sure to check that first. DigitalOcean is a good choice as they don't block port 25 as default. Port 25 is essential for sending emails so it's important that your VPS provider allows it.&lt;/p&gt;

&lt;p&gt;To be able to connect your VPS server you'll need to add your SSH public key to the server. SSH keys are a secure way to connect to your server in terminal. And you'll be able to do run some installation commands later on. You can follow this guide to create SSH keys if you don't have one already.&lt;/p&gt;

&lt;p&gt;When you have your SSH key ready, create a new droplet with the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new droplet with Ubuntu 22.04, it's important to use this version as Mail-in-a-Box doesn't support newer versions yet.&lt;/li&gt;
&lt;li&gt;Choose a plan (the cheapest one is usually sufficient for personal use).&lt;/li&gt;
&lt;li&gt;Choose a data center region close to you.&lt;/li&gt;
&lt;li&gt;Add your SSH key for secure access.&lt;/li&gt;
&lt;li&gt;Create the droplet and note down its IP address.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is a detailed tutorial on how to create a droplet on DigitalOcean: &lt;a href="https://docs.digitalocean.com/products/droplets/how-to/create/" rel="noopener noreferrer"&gt;How to Create a Droplet on DigitalOcean&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once your droplet is created, you also need to set a &lt;strong&gt;reverse DNS (PTR)&lt;/strong&gt; record for your server's IP address. This is important for email deliverability as many email providers check for a valid PTR record to prevent spam. When you change your droplet's name in DigitalOcean, the PTR record is automatically updated to match the new name. So, you can set your droplet's name to your domain name to have a matching PTR record. We'll you use &lt;code&gt;box.yourdomain.com&lt;/code&gt; as the hostname for the rest of this tutorial.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: Point Your Domain to Your Server
&lt;/h4&gt;

&lt;p&gt;Before setting up the email server, you need to do some DNS configuration for your domain. Mail-in-a-Box requires you to create glue records for your domain. Your domain registrar should have a glue record management section in their dashboard. I'd recommend using &lt;a href="https://porkbun.com/" rel="noopener noreferrer"&gt;porkbun.com&lt;/a&gt; as your domain registrar, their pricing is reasonable and provide a good DNS management options.&lt;/p&gt;

&lt;p&gt;Assuming you have purchased a domain from Porkbun, follow these steps to create glue records:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log in to your Porkbun account and go to the "Domain Management" section.&lt;/li&gt;
&lt;li&gt;Click details button at the right side of your domain name.&lt;/li&gt;
&lt;li&gt;Scroll down to the "Glue Records" section and click "Manage".&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create two glue records:&lt;br&gt;
&lt;code&gt;ns1.yourdomain.com&lt;/code&gt; pointing to your server's IP address.&lt;br&gt;
&lt;code&gt;ns2.yourdomain.com&lt;/code&gt; pointing to your server's IP address.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save the changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next, you need to set your domain's nameservers to the glue records you just created. In the same domain settings page, find the "Nameservers" section and set the nameservers to:&lt;br&gt;
&lt;code&gt;ns1.yourdomain.com&lt;/code&gt;&lt;br&gt;
&lt;code&gt;ns2.yourdomain.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Save the changes. It may take some time for the DNS changes to propagate, usually within a few hours but sometimes up to 48 hours. Here is more detailed guide on how to set up glue records on porkbun: &lt;a href="https://kb.porkbun.com/article/112-how-to-host-your-own-nameservers-with-glue-records" rel="noopener noreferrer"&gt;How to Set Up Glue Records on Porkbun&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to learn more about glue records and why they are important, you can read this article: &lt;a href="https://dumpbox.net/article/what-are-glue-records" rel="noopener noreferrer"&gt;What are Glue Records?&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Step 3: Connect to Your Server
&lt;/h4&gt;

&lt;p&gt;Once your droplet is created, you can connect to it using SSH. Open your terminal and run the following command (replace your_droplet_ip with the actual IP address of your droplet):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh root@your_droplet_ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should now be logged into your server as the root user. Before proceeding, it's a good practite to create a new user with sudo privileges for better security. Using root user grants full access to the system, which can lead to accidental system damage or the server a prime target for malicious attacks if compromised. Creating a new user with limited privileges helps mitigate these risks.&lt;/p&gt;

&lt;p&gt;Creating a new user can be done with the following command (replace &lt;code&gt;your_username&lt;/code&gt; with your desired username):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adduser your_username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, add the new user to the sudo group to grant administrative privileges:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;usermod -aG sudo your_username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You logged in to your root account using SSH keys. You will need to add a copy of your local public key to the new user’s &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt; file to log in successfully as the new user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rsync --archive --chown=your_username:your_username ~/.ssh /home/your_username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's done! Now you can log out from the root account by typing exit and log in again using the new user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh your_username@your_droplet_ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 4: Install Mail-in-a-Box
&lt;/h4&gt;

&lt;p&gt;Now, let's do some initial setup on the server. First, update the package list and upgrade all packages to their latest versions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, install mail-in-a-box. The installation process is straightforward. Run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -s https://mailinabox.email/setup.sh | sudo -E bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script will guide you through the installation process. When it asks domain name, enter your hostname (&lt;code&gt;box.yourdomain.com&lt;/code&gt;) as same as the PTR record you set earlier. The installation process may take some time as it installs and configures all necessary components.&lt;/p&gt;

&lt;p&gt;Once the installation is complete, because your SSL certificate is not yet signed, you need to log in using &lt;code&gt;https://your_droplet_ip/admin&lt;/code&gt; for the first time. You login using the email account you created during the installation process. After logging in, navigate to the "System" tab and click on "TLS (SSL) Certificates" section. If you already have a domain name pointed to your server, the instructions to obtain a free SSL certificate from Let's Encrypt will show up automatically. Follow the instructions to get your SSL certificate.&lt;/p&gt;

&lt;p&gt;Now you can access the mail-in-a-box admin interface by navigating to &lt;code&gt;https://box.yourdomain.com/admin&lt;/code&gt; in your web browser. Now you can go to the "Mail &amp;amp; Users" tab to create new email accounts with your domain name like &lt;code&gt;username@yourdomain.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can visit Mail in a box &lt;a href="https://mailinabox.email/" rel="noopener noreferrer"&gt;official website&lt;/a&gt; for more detailed instructions on how to create email accounts and manage your server.&lt;/p&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;That's it! You have successfully set up your own secure email server using Mail-in-a-Box. You can now create email accounts, manage your server, and start sending and receiving emails with your own domain.&lt;/p&gt;

</description>
      <category>email</category>
      <category>server</category>
      <category>droplet</category>
      <category>dns</category>
    </item>
    <item>
      <title>Is It Worth Running Your Own Email Server?</title>
      <dc:creator>Firat</dc:creator>
      <pubDate>Sat, 20 Sep 2025 08:53:31 +0000</pubDate>
      <link>https://dev.to/firatkiral/is-it-worth-running-your-own-email-server-5g7a</link>
      <guid>https://dev.to/firatkiral/is-it-worth-running-your-own-email-server-5g7a</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Running your own email server can be a rewarding experience, but it also requires a lot of effort and dedication.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Gmail is waiting to reject you as soon as you send something from port 25. If you want to end up someone's inbox, you need to follow some rules and standards. On the other side, security is a big concern. Internet is a wild west, as soon as you put something online, your server will start getting attacked, they are waiting to pull you apart, steal everything they can find, take over your server to run for their bad purposes.&lt;/p&gt;

&lt;p&gt;You may think how they can even find you, right? It would take minutes for bots to find your server to start attacking it as soon as you put it online.&lt;/p&gt;

&lt;h4&gt;
  
  
  Are you ready to fight?
&lt;/h4&gt;

&lt;p&gt;If so, why would you want to run your own email server? You may want to use your own domain for your email address? But there are many services that can do that for you, like Google Workspace, Zoho Mail, Proton Mail, etc. They let you use your own domain for your email address. So you don't have to worry about the security, spam filtering, backups, etc.&lt;/p&gt;

&lt;p&gt;But if it might be expensive if you need many email addresses for you company. So having your own email server can be a good and cheaper alternative. You may also need privacy, you don't want your emails to be read by third parties. You may want to have full control over your emails, you don't want to be dependent on any service provider. Ok, it is convincing, lets look at the steps.&lt;/p&gt;

&lt;h4&gt;
  
  
  Get your hands wet
&lt;/h4&gt;

&lt;p&gt;Fist you need to find a good Virtual Private Server (VPS) provider with port 25 open. You may also try to run your email server from your home or company network, but most probably your Internet Service Provider (ISP) will block port 25. Port 25 is the default port for Simple Mail Transfer Protocol (SMTP), which is used for sending emails. Most ISPs and VPS providers block this port as default to prevent spam and abuse.&lt;/p&gt;

&lt;p&gt;Then need good IP reputation. Most of the VPS providers have bad IP reputation or already blacklisted, because they are used by many people, some of them may be spammers. You can check the IP reputation of your server using tools like MXToolbox, etc.So you need to find a clean IP address so you relay your emails from third party SMTP relay service like SendGrid, Mailgun, Amazon SES, etc.&lt;/p&gt;

&lt;p&gt;Next, you need to install and configure an email server software. There are many options available, like Postfix, Exim, Dovecot, etc. You need to choose one that suits your needs and preferences. Or you can find some all-in-one opensource solutions like Mail-in-a-Box, etc.&lt;/p&gt;

&lt;p&gt;And you need to set up DNS records for your domain. You need to set up MX records, SPF, DKIM and DMARC records. MX records are used to specify the mail servers for your domain. SPF is used to specify which servers are allowed to send emails on behalf of your domain. DKIM is used to sign your emails to prove that they are not tampered with. DMARC is used to specify how to handle emails that fail SPF or DKIM checks.&lt;/p&gt;

&lt;h4&gt;
  
  
  Are those enough?
&lt;/h4&gt;

&lt;p&gt;These are the basic steps to run your own email server. But still you may end up in spam. If your domain is new, it might be recognized as unsafe and sent to spam. You build your domain reputation over time. If you are sending bulk emails, or newsletters, you also need to add unsubscribe link, and List-Unsubscribe header to your emails. So people wont mark your emails as spam.&lt;/p&gt;

&lt;h4&gt;
  
  
  Summary
&lt;/h4&gt;

&lt;p&gt;Running your own email server can be a rewarding experience, but it also requires a lot of effort and dedication. You need to be prepared to deal with the challenges and issues that may arise. If you are not ready to fight, it is better to use a third party service provider.&lt;/p&gt;

&lt;p&gt;If you are ready, good luck and have fun!&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>email</category>
      <category>server</category>
      <category>cloud</category>
    </item>
    <item>
      <title>How Does Public Key Cryptography Work?</title>
      <dc:creator>Firat</dc:creator>
      <pubDate>Sat, 20 Sep 2025 08:48:57 +0000</pubDate>
      <link>https://dev.to/firatkiral/how-does-public-key-cryptography-work-eho</link>
      <guid>https://dev.to/firatkiral/how-does-public-key-cryptography-work-eho</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Fascinating technology behind public and private key pairs cryptography&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The internet has opened up new ways of communication. But those come with their own security challenges. When we send on email or chat with someone, we assume that only the intended recipient can read our message. But how can we be sure of that? When we send data over the internet, we first need to lock that data up so that only the people with the right key can unlock it. Assuming that we can't deliver the key in person, we need to find a secure way to share it over the internet. Securing that key with another key will create a never-ending loop. So how can we securely share a key over an insecure channel like the internet?&lt;/p&gt;

&lt;p&gt;Luckily some people instead of looking ways to securing key, they invented new way of locking and unlocking data. This is called public key cryptography. It uses two keys, a public key and a private key. Public key is used to lock (encrypt) the data, and private key is used to unlock (decrypt) the data. So, if you want to send a secure message to someone, you need to use their public key to encrypt the message and send it to them. Public key can't be used to decrypt the message, only the private key can do that. So no one else can read the message except the recepient who has the private key. So its same if receipient wants to send a secure message to you, they will use your public key to encrypt the message and send it to you. Only you can decrypt the message using your private key.&lt;/p&gt;

&lt;p&gt;So each person has 2 keys, a public key and a private key. You share your public key with everyone, but you keep your private key secret for yourself. Of course you don't need to do this manually. Almost all apps you use today use public key cryptography behind the scenes to secure your data. For example, when you visit a website that uses HTTPS, your browser uses public key cryptography to securely share a key with the website so that all the data you send and receive is encrypted vice versa.&lt;/p&gt;

&lt;p&gt;I won't go into the mathematical details of how public key cryptography works, but I will give you a high level overview. Public key cryptography is based on the idea of one-way functions. A one-way function is a function that is easy to compute in one direction, but hard to compute in the other direction. For example, multiplying two large prime numbers together is easy, but factoring the resulting number back into its prime factors is hard. That's the basis of RSA, one of the most widely used public key cryptography algorithms.&lt;/p&gt;

&lt;h4&gt;
  
  
  Summary
&lt;/h4&gt;

&lt;p&gt;Public key cryptography is a powerful tool that allows us to securely communicate over insecure channels like the internet. It uses two keys, a public key and a private key, to lock and unlock data. Public key cryptography is based on the idea of one-way functions, which are easy to compute in one direction but hard to compute in the other direction. This technology is used in almost all apps you use today to secure your data.&lt;/p&gt;

</description>
      <category>cryptography</category>
      <category>publickey</category>
      <category>encryption</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>How Independent is OpenAI from Microsoft?</title>
      <dc:creator>Firat</dc:creator>
      <pubDate>Thu, 11 Apr 2024 16:34:51 +0000</pubDate>
      <link>https://dev.to/firatkiral/how-independent-is-openai-from-microsoft-2fah</link>
      <guid>https://dev.to/firatkiral/how-independent-is-openai-from-microsoft-2fah</guid>
      <description>&lt;p&gt;Sam Altman, the CEO of OpenAI, has stated that his company is independent and not controlled by Microsoft. Despite this claim, Microsoft appears to be fully leveraging the capabilities of ChatGPT across its product lineup, particularly within its Bing search engine. While Microsoft is integrating ChatGPT extensively, OpenAI seems hesitant or slow in monetizing and commercializing the technology directly.&lt;/p&gt;

&lt;p&gt;There’s potential for OpenAI to disrupt the search engine market significantly if they chose to launch a dedicated product like gptsearch.com, which would combine ChatGPT with web search capabilities. Such a move could potentially shift market dynamics in just a week. However, from current observations, it appears that OpenAI has prioritized enabling Microsoft to commercialize ChatGPT first. This approach raises questions about whether OpenAI makes decisions independently from Microsoft or if there are underlying agreements or pressures that guide their strategies.&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>openai</category>
      <category>microsoft</category>
      <category>search</category>
    </item>
    <item>
      <title>KodiBot - Local Chatbot App for Desktop</title>
      <dc:creator>Firat</dc:creator>
      <pubDate>Thu, 11 Apr 2024 16:32:43 +0000</pubDate>
      <link>https://dev.to/firatkiral/kodibot-local-chatbot-app-for-desktop-1e6g</link>
      <guid>https://dev.to/firatkiral/kodibot-local-chatbot-app-for-desktop-1e6g</guid>
      <description>&lt;p&gt;KodiBot is a desktop app that enables users to run their own AI chat assistants locally and offline on Windows, Mac, and Linux operating systems. KodiBot is a standalone app and does not require an internet connection or additional dependencies to run local chat assistants. It supports both &lt;a href="https://github.com/ggerganov/llama.cpp"&gt;Llama.cpp&lt;/a&gt; compatible models and &lt;a href="https://openai.com/"&gt;OpenAI API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;KodiBot is free and open source app developed using electronjs framework and released under the GNU General Public License.&lt;/p&gt;

&lt;p&gt;Please visit &lt;a href="https://kodibot.com"&gt;kodibot.com&lt;/a&gt; for more information and downloads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Requirements&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average gaming PC or laptop with Windows, Mac, or Linux operating system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;KodiBot has a simple and user friendly interface. You can esily create chat assistant cards and customize them for specific tasks or topics by adding instructions. You can save cards to JSON file share them with others. It stores your history with each chat assistant separately. You can easily navigate and switch between chat assistants from the sidebar.&lt;/p&gt;

&lt;p&gt;KodiBot offers a versatile platform for users who want to utilize AI chatbot technology locally and offline. Here are some potential use cases for KodiBot:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privacy-Conscious Users:&lt;/strong&gt; For individuals or businesses concerned about data privacy, running an AI chat assistant locally ensures that sensitive information does not leave their device or get shared with third-party servers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Development and Testing:&lt;/strong&gt; Developers can use KodiBot to build, train, and test AI models in a local environment before deploying them online or integrating them into larger applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Education and Research:&lt;/strong&gt; Students, educators, and researchers can use KodiBot as a tool for learning about artificial intelligence and natural language processing without the need for constant internet access.&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>ai</category>
      <category>chatbot</category>
    </item>
    <item>
      <title>Peek: Simplify Screen Recordings</title>
      <dc:creator>Firat</dc:creator>
      <pubDate>Mon, 13 Feb 2023 19:52:07 +0000</pubDate>
      <link>https://dev.to/firatkiral/peek-simplify-screen-recordings-3h44</link>
      <guid>https://dev.to/firatkiral/peek-simplify-screen-recordings-3h44</guid>
      <description>&lt;p&gt;Hi there!&lt;/p&gt;

&lt;p&gt;If you are a developer, designer, student or someone in need of a tool to capture your screen for tutorials, bug reporting, technical support, or self-reflection, I have created Peek an open-source screen recorder that works on all your desktop devices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Peek&lt;/strong&gt; not only allows you to &lt;strong&gt;record your screen&lt;/strong&gt; as either a &lt;strong&gt;gif&lt;/strong&gt; or &lt;strong&gt;mp4&lt;/strong&gt; file, but it also lets you capture screenshots as &lt;strong&gt;jpg&lt;/strong&gt; images. With its &lt;strong&gt;annotation feature&lt;/strong&gt; you can add text, arrows, shapes, and highlights to your recordings to emphasize important information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K53RwEZ0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x7uge1pxzhyzp7fvyjao.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K53RwEZ0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x7uge1pxzhyzp7fvyjao.gif" alt="Peek is exciting" width="592" height="686"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The range slider option lets you trim your recording to the desired length, and the delay recording start feature gives you time to prepare before the recording begins. And if you prefer to keep your recordings a consistent length, it has fixed time recording option.&lt;/p&gt;

&lt;p&gt;Peek is built with &lt;strong&gt;Python&lt;/strong&gt; and &lt;strong&gt;PySide6&lt;/strong&gt; and you can find its GitHub repository &lt;a href="https://github.com/firatkiral/pypeek"&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can download the app at &lt;a href="https://apps.apple.com/us/app/peek-screen-recorder/id1670786300"&gt;&lt;strong&gt;App Store&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://apps.microsoft.com/store/detail/XP8CD3D3Q50MS2"&gt;&lt;strong&gt;Microsoft Store&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I believe Peek is a powerful and user-friendly tool that will help you capture your desktop with ease on different desktop platforms. If you have any questions or suggestions, don’t hesitate to reach out to me.&lt;/p&gt;

&lt;p&gt;Happy recording!&lt;/p&gt;

</description>
      <category>python</category>
      <category>gif</category>
      <category>pyside</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Introducing Blite, the Lightweight Node.js Backend Server</title>
      <dc:creator>Firat</dc:creator>
      <pubDate>Mon, 13 Feb 2023 07:55:42 +0000</pubDate>
      <link>https://dev.to/firatkiral/introducing-blite-the-lightweight-nodejs-backend-server-57fe</link>
      <guid>https://dev.to/firatkiral/introducing-blite-the-lightweight-nodejs-backend-server-57fe</guid>
      <description>&lt;p&gt;Building a backend server for a small sized apps can be a complex and time-consuming process. Blite offers a solution to simplify this process and get you up and running quickly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blite&lt;/strong&gt; is a monolithic &lt;strong&gt;Node.js backend server app&lt;/strong&gt; that provides built-in services such as routing, user authentication, database management, upload management, and email confirmation. This all-in-one solution aims to be lightweight and fast, making it a great choice for small to medium sized projects that need a backend server and database.&lt;/p&gt;

&lt;p&gt;It's an &lt;strong&gt;open source&lt;/strong&gt; project and you can check out the source code and docs &lt;a href="https://github.com/firatkiral/blite"&gt;here&lt;/a&gt;. You can run the &lt;strong&gt;demo app&lt;/strong&gt; following way to see how it works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;blite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;demo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// Check out the demo app at http://localhost:3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FEjT-IWT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ipt5e74j5tnuiwvad20r.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FEjT-IWT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ipt5e74j5tnuiwvad20r.jpg" alt="Demo app" width="685" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following hello world example illustrates defining simple routes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;blite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Serve static files&lt;/span&gt;
&lt;span class="nx"&gt;blite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/static&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;blite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`www`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Hello world&lt;/span&gt;
&lt;span class="nx"&gt;blite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;blite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// Check out the example app at http://localhost:8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are some examples of how you can use database with Blite.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;blite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]});&lt;/span&gt;

&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Odin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Alternatively, insert array of documents&lt;/span&gt;
&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Thor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loki&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;}]);&lt;/span&gt;

&lt;span class="c1"&gt;// Find documents&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$gt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// output:&lt;/span&gt;
&lt;span class="c1"&gt;// [&lt;/span&gt;
&lt;span class="c1"&gt;//     {&lt;/span&gt;
&lt;span class="c1"&gt;//       name: 'Odin',&lt;/span&gt;
&lt;span class="c1"&gt;//       age: 50,&lt;/span&gt;
&lt;span class="c1"&gt;//       meta: {&lt;/span&gt;
&lt;span class="c1"&gt;//         revision: 1,&lt;/span&gt;
&lt;span class="c1"&gt;//         created: 1676235325951,&lt;/span&gt;
&lt;span class="c1"&gt;//         version: 0,&lt;/span&gt;
&lt;span class="c1"&gt;//         updated: 1676235325952&lt;/span&gt;
&lt;span class="c1"&gt;//       },&lt;/span&gt;
&lt;span class="c1"&gt;//       '$ctrl': 1,&lt;/span&gt;
&lt;span class="c1"&gt;//       id: '80f81115-3e82-4603-bb04-3dae2540f554'&lt;/span&gt;
&lt;span class="c1"&gt;//     }&lt;/span&gt;
&lt;span class="c1"&gt;// ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Blite is a simple and fast library that allows you to create a full stack web application in minutes. It has a lot of features that you can use to build your next project. You can check out the documentation &lt;a href="https://github.com/firatkiral/blite"&gt;here&lt;/a&gt; for more details. If you have any questions or suggestions, feel free to contact me.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>node</category>
      <category>backend</category>
    </item>
    <item>
      <title>A First Look at PySketch: Python for Fun!</title>
      <dc:creator>Firat</dc:creator>
      <pubDate>Mon, 11 Apr 2022 07:17:25 +0000</pubDate>
      <link>https://dev.to/firatkiral/pysketch-python-playground-for-html5-365g</link>
      <guid>https://dev.to/firatkiral/pysketch-python-playground-for-html5-365g</guid>
      <description>&lt;p&gt;&lt;a href="https://pysketch.com" rel="noopener noreferrer"&gt;PySketch.com&lt;/a&gt; is a Python web editor that aims to provide social coding experience to anyone who likes creative coding. You can improve or showcase your Python skills on the web by building fun projects, games, graphics with access to HTML5 and JavaScript libraries or exploring other Python projects from other talented developers. It works on all major mobile and desktop browsers, and you can share your projects and games with your friends or embed them into your blog for your audience.&lt;/p&gt;

&lt;p&gt;If you are a Python person, you'll feel at home and enjoy all HTML5 features with &lt;a href="https://pysketch.com" rel="noopener noreferrer"&gt;PySketch&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Check this famous flappy bird game done in pysketch. &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/firat_kiral/embed/rNYWWJm?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get Started: Bouncing Logo&lt;/strong&gt;&lt;br&gt;
We'll learn the basics by doing a bouncing logo sketch covering the essential points. It's the most known screen saver, and it'll be fun to build it here. Here is the final sketch, feel free to play with code and run.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/firat_kiral/embed/BamggVb?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Let's take a closer look at the code:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Loading modules&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;browser.html&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CANVAS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IMG&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;randint&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Document&lt;/code&gt; and &lt;code&gt;window&lt;/code&gt; modules are equivalent to their JavaScript versions. These are for accessing JavaScript properties, global variables, etc.&lt;br&gt;
&lt;code&gt;browser.html&lt;/code&gt; is a wrapper module for HTML tags. It allows us to create and manipulate dom elements with ease in Python. For all other tags and examples, please check &lt;a href="https://brython.info/static_doc/en/html.html" rel="noopener noreferrer"&gt;here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dom Api&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CANVAS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;canvas&lt;/span&gt;

&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2d&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we create a canvas element and add it to the body of the HTML page. &lt;code&gt;ctx&lt;/code&gt; is the context of the canvas where we do our drawing operations. We are not going into detail on canvas API, but you can get more info &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API" rel="noopener noreferrer"&gt;here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Loading assets&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;logo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;IMG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;logo.png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Files are loaded asynchronously, which means that the image is not available on the following line and will take some time to load. So we set an &lt;code&gt;onload&lt;/code&gt; callback here. Once the logo is loaded, our app will start looping. We'll come to the looping part later.&lt;/p&gt;

&lt;p&gt;PySketch provides cloud hosting for assets to be able to use in sketches. Go to Sketch Details -&amp;gt; Files tab and upload your assets for your sketch.&lt;/p&gt;

&lt;p&gt;Sketch assets can be loaded by their filenames, as seen in the code snippet above.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Draw Function&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x_speed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_speed&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="n"&gt;does&lt;/span&gt; &lt;span class="n"&gt;calculations&lt;/span&gt; &lt;span class="n"&gt;here&lt;/span&gt;
  &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the main draw function, and it calculates the new position by taking speed into account and renders the logo in the canvas context. Please read inline comments on the final sketch to get the idea of drawing on context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Main loop&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="nf"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the heart of most graphical apps. It refers to the overall flow of the program and keeps looping infinitely until manually stopped. Browsers have built-in &lt;code&gt;requestAnimationFrame&lt;/code&gt; function. It's designed to run smooth animations on the browser without blocking the page. Your animation function is called before the browser performs the next repaint. The number of callbacks is usually 60 times per second if you request a new frame. &lt;/p&gt;

&lt;p&gt;In this loop, we call the &lt;code&gt;draw&lt;/code&gt; function, and after drawing, we request a new frame recursively. This process repeats forever until we stop the app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How is the Python being run by the browser?&lt;/strong&gt; &lt;br&gt;
Several impressive projects bring Python to the browser, such as &lt;a href="https://brython.info" rel="noopener noreferrer"&gt;Brython&lt;/a&gt;, &lt;a href="https://transcrypt.org/" rel="noopener noreferrer"&gt;Transcrypt&lt;/a&gt;, &lt;a href="https://skulpt.org/" rel="noopener noreferrer"&gt;Skulpt&lt;/a&gt;, &lt;a href="https://github.com/iodide-project/pyodide" rel="noopener noreferrer"&gt;Pyodide&lt;/a&gt;. PySketch uses Brython that compiles Python to JavaScript in the browser. You can take a look at &lt;a href="https://anvil.works/blog/python-in-the-browser-talk" rel="noopener noreferrer"&gt;this article&lt;/a&gt; about technologies and comparisons if you want to learn more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
We saw how to implement Python-based apps directly into the browser using PySketch. If you have familiarity with JavaScript and web development, you'll enjoy building apps and games using Python.&lt;/p&gt;

&lt;p&gt;No doubt that JavaScript can't be replaced in terms of speed, usability, and maintainability, but it's good to know that there are alternative ways to enjoy HTML5.&lt;/p&gt;

&lt;p&gt;For more examples and tutorials, visit &lt;a href="https://pysketch.com" rel="noopener noreferrer"&gt;pysketch.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>webdev</category>
      <category>showdev</category>
      <category>gamedev</category>
    </item>
  </channel>
</rss>
