<?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: Med Marrouchi</title>
    <description>The latest articles on DEV Community by Med Marrouchi (@marrouchi).</description>
    <link>https://dev.to/marrouchi</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%2F945989%2F2eae3154-24a6-4878-a8fc-afa2a1a274b2.jpeg</url>
      <title>DEV Community: Med Marrouchi</title>
      <link>https://dev.to/marrouchi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/marrouchi"/>
    <language>en</language>
    <item>
      <title>How do I use DevOps-style i18n</title>
      <dc:creator>Med Marrouchi</dc:creator>
      <pubDate>Tue, 19 May 2026 08:20:54 +0000</pubDate>
      <link>https://dev.to/marrouchi/how-do-i-use-devops-style-i18n-5edm</link>
      <guid>https://dev.to/marrouchi/how-do-i-use-devops-style-i18n-5edm</guid>
      <description>&lt;p&gt;Localization is one of those things every serious product eventually needs, but many teams still treat it as a separate, heavy process.&lt;/p&gt;

&lt;p&gt;You extract strings from your app, send them somewhere, wait for translations, copy files back, fix formatting issues, review inconsistencies, and repeat the same process every time the product changes.&lt;/p&gt;

&lt;p&gt;For developers, this often feels disconnected from the normal software delivery workflow.&lt;/p&gt;

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

&lt;p&gt;That is exactly where &lt;strong&gt;doloc&lt;/strong&gt; takes an interesting approach.&lt;/p&gt;

&lt;p&gt;Instead of trying to become another large localization management platform with dashboards, complex workflows, and translator management, doloc focuses on a simpler idea:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What if localization could work like a DevOps task?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is doloc?
&lt;/h2&gt;

&lt;p&gt;doloc is an API-first localization tool for developers and engineering teams.&lt;/p&gt;

&lt;p&gt;It takes your existing localization files, translates them using context-aware AI, and returns the result in the same structure and format, ready to review, commit, and ship.&lt;/p&gt;

&lt;p&gt;The main idea is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://api.doloc.io &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$API_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"@source.en.json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nv"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"@target.fr.json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; target.fr.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No complicated platform migration.&lt;br&gt;
No heavy onboarding.&lt;br&gt;
No new translation system to force into your stack.&lt;/p&gt;

&lt;p&gt;You keep your files, your Git workflow, your CI/CD pipeline, and your existing development habits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters for developers
&lt;/h2&gt;

&lt;p&gt;Most modern engineering teams already have a workflow for everything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;code is versioned in Git&lt;/li&gt;
&lt;li&gt;tests run in CI&lt;/li&gt;
&lt;li&gt;builds are automated&lt;/li&gt;
&lt;li&gt;deployments are scripted&lt;/li&gt;
&lt;li&gt;reviews happen through pull requests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But localization often remains outside that loop.&lt;/p&gt;

&lt;p&gt;doloc brings translations closer to the engineering workflow. You can run it locally, add it after your string extraction step, or integrate it into CI so translations stay updated as your application evolves.&lt;/p&gt;

&lt;p&gt;This makes i18n feel less like a separate project management process and more like a natural part of software delivery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key advantages of doloc
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. API-first by design
&lt;/h3&gt;

&lt;p&gt;doloc does not force developers to use a dashboard for every translation task.&lt;/p&gt;

&lt;p&gt;You can call the API directly using &lt;code&gt;curl&lt;/code&gt;, scripts, or CI jobs. That makes it easy to automate and easy to integrate into existing pipelines.&lt;/p&gt;

&lt;p&gt;For teams that prefer infrastructure-as-code, Git workflows, and reproducible processes, this is a big advantage.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Works with real localization file formats
&lt;/h3&gt;

&lt;p&gt;doloc supports common localization formats such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;XLIFF 1.2&lt;/li&gt;
&lt;li&gt;XLIFF 2.0&lt;/li&gt;
&lt;li&gt;JSON&lt;/li&gt;
&lt;li&gt;ARB&lt;/li&gt;
&lt;li&gt;Android XML resources&lt;/li&gt;
&lt;li&gt;Java Properties files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes it useful across different stacks, including Angular, React Intl / FormatJS, Flutter, Android, Java, and other JSON or XLIFF-based setups.&lt;/p&gt;

&lt;p&gt;Instead of exporting content into a separate tool and importing it back later, you can work directly with the files your app already uses.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Fits naturally into CI/CD
&lt;/h3&gt;

&lt;p&gt;Because doloc is API-based, it can be added to your development lifecycle in different ways.&lt;/p&gt;

&lt;p&gt;You can run it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;locally before opening a pull request&lt;/li&gt;
&lt;li&gt;during CI checks&lt;/li&gt;
&lt;li&gt;after extracting new strings&lt;/li&gt;
&lt;li&gt;as part of a scheduled localization job&lt;/li&gt;
&lt;li&gt;before preparing a release&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is especially helpful for fast-moving products where UI copy changes frequently.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Keeps translation files in your repository
&lt;/h3&gt;

&lt;p&gt;One of the strongest points of doloc is that your localization files stay in your repo.&lt;/p&gt;

&lt;p&gt;That means translations can be reviewed like code.&lt;/p&gt;

&lt;p&gt;You can check the &lt;code&gt;git diff&lt;/code&gt;, open a pull request, review changes, and roll back if needed. For engineering teams, this is much cleaner than managing translations in a disconnected platform where the source of truth becomes unclear.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Context-aware translations
&lt;/h3&gt;

&lt;p&gt;Basic machine translation can work for simple strings, but software localization needs consistency.&lt;/p&gt;

&lt;p&gt;Buttons, error messages, empty states, onboarding screens, and product-specific wording need to follow the same tone.&lt;/p&gt;

&lt;p&gt;doloc uses context from your existing translations to keep terminology and style more consistent across your app. This is especially useful when your project grows and contains many strings across multiple files.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Less platform overhead
&lt;/h3&gt;

&lt;p&gt;Traditional localization platforms are powerful, but they are not always necessary.&lt;/p&gt;

&lt;p&gt;Sometimes you do not need translator management, complex approval workflows, or a full dashboard. Sometimes you simply need to translate app strings quickly, review the output, and ship.&lt;/p&gt;

&lt;p&gt;doloc is a good fit for that use case.&lt;/p&gt;

&lt;p&gt;It gives developers a lightweight workflow without introducing a heavy process around localization.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Scales well with multiple languages
&lt;/h3&gt;

&lt;p&gt;Another interesting point is the pricing model.&lt;/p&gt;

&lt;p&gt;doloc pricing is based on unique source texts, not on the number of target languages or translation requests. So if your app has the same set of source keys and you want to translate them into several languages, you are not punished simply for expanding internationally.&lt;/p&gt;

&lt;p&gt;For startups, open-source projects, and small teams, this can make localization easier to plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should you consider doloc?
&lt;/h2&gt;

&lt;p&gt;doloc is especially useful if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you are building a multilingual app&lt;/li&gt;
&lt;li&gt;your localization files are already in Git&lt;/li&gt;
&lt;li&gt;you want to automate translation updates&lt;/li&gt;
&lt;li&gt;you prefer API-based workflows&lt;/li&gt;
&lt;li&gt;you do not want to manage a heavy localization platform&lt;/li&gt;
&lt;li&gt;you want translations to fit into your PR and CI process&lt;/li&gt;
&lt;li&gt;your team cares about developer experience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It may not replace a full translation management platform if you need a large translator team, approval workflows, or advanced project management features.&lt;/p&gt;

&lt;p&gt;But for many developer-led teams, that is exactly the point.&lt;/p&gt;

&lt;p&gt;doloc focuses on making localization simple, automated, and close to the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Localization should not slow down product development.&lt;/p&gt;

&lt;p&gt;For many teams, the ideal workflow is not another dashboard. It is a simple, reliable process that fits into the tools developers already use every day.&lt;/p&gt;

&lt;p&gt;That is what makes doloc interesting.&lt;/p&gt;

&lt;p&gt;It treats i18n as part of the development pipeline, not as a separate operational burden.&lt;/p&gt;

&lt;p&gt;If you are building a multilingual product and want a developer-friendly way to keep translations up to date, doloc is definitely worth trying.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://doloc.io/?linkId=lp_573318&amp;amp;sourceId=med-mar&amp;amp;tenantId=doloc" rel="noopener noreferrer"&gt;👉 Try doloc here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>development</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Install Hexabot CLI and Create Your First AI Workflow</title>
      <dc:creator>Med Marrouchi</dc:creator>
      <pubDate>Mon, 18 May 2026 17:57:12 +0000</pubDate>
      <link>https://dev.to/marrouchi/install-hexabot-cli-and-create-your-first-ai-workflow-3ah0</link>
      <guid>https://dev.to/marrouchi/install-hexabot-cli-and-create-your-first-ai-workflow-3ah0</guid>
      <description>&lt;h1&gt;
  
  
  Install Hexabot CLI and Create Your First AI Workflow Project
&lt;/h1&gt;

&lt;p&gt;Getting started with a new automation platform should not take hours.&lt;/p&gt;

&lt;p&gt;In this tutorial, I’ll show you how to install the Hexabot CLI, create a new project from the starter template, and run it locally.&lt;/p&gt;

&lt;p&gt;This is the fastest way to start experimenting with Hexabot and build your first AI workflow project.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Watch the full video here:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/EWVST74fQkg"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Hexabot?
&lt;/h2&gt;

&lt;p&gt;Hexabot is an AI workflow automation platform designed for building workflows, actions, agents, and conversational channels in one runtime.&lt;/p&gt;

&lt;p&gt;You can use it to create automations that connect conversations to real actions, integrate with external services, and build AI-powered assistants that are more controlled, observable, and extensible.&lt;/p&gt;

&lt;p&gt;Instead of starting from a large monorepo or manually wiring everything yourself, the Hexabot CLI helps you generate a clean project workspace and start building faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before installing Hexabot, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js installed&lt;/li&gt;
&lt;li&gt;npm or another package manager&lt;/li&gt;
&lt;li&gt;A terminal&lt;/li&gt;
&lt;li&gt;Docker, if you want to run Docker-based services locally&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you do not have Node.js installed yet, I recommend using NVM so you can easily manage Node.js versions.&lt;/p&gt;

&lt;p&gt;Node.js with NVM guide:&lt;br&gt;
&lt;a href="https://docs.hexabot.ai/developer-guide/setup-node.js-with-nvm" rel="noopener noreferrer"&gt;https://docs.hexabot.ai/developer-guide/setup-node.js-with-nvm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can quickly check your local setup with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--version&lt;/span&gt;
npm &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  1. Install the Hexabot CLI
&lt;/h2&gt;

&lt;p&gt;Install the Hexabot CLI globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @hexabot-ai/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed, check that the CLI is available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hexabot &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use the CLI without installing it globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @hexabot-ai/cli &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Create a New Hexabot Project
&lt;/h2&gt;

&lt;p&gt;Now create your first project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hexabot create my-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI will scaffold a new Hexabot project and guide you through the initial setup.&lt;/p&gt;

&lt;p&gt;You may be asked to provide initial admin account details such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First name&lt;/li&gt;
&lt;li&gt;Last name&lt;/li&gt;
&lt;li&gt;Email&lt;/li&gt;
&lt;li&gt;Password&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These credentials will be used to access your local Hexabot admin interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Move Into the Project Folder
&lt;/h2&gt;

&lt;p&gt;Once the project is created, move into the new workspace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;my-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, you have a generated Hexabot project ready to run locally.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Start the Local Development Server
&lt;/h2&gt;

&lt;p&gt;Run the project with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hexabot dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This starts your local Hexabot development environment.&lt;/p&gt;

&lt;p&gt;Once the app is running, you can open the admin interface in your browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may also find the local API and API documentation at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000/api
http://localhost:3000/docs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Useful CLI Commands
&lt;/h2&gt;

&lt;p&gt;Here are a few commands you will probably use often:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hexabot create &amp;lt;project-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a new Hexabot project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hexabot dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the project locally in development mode.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hexabot check
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check your local project setup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hexabot migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run database migrations when needed.&lt;/p&gt;

&lt;p&gt;For the full CLI reference, check the official documentation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.hexabot.ai/developer-guide/cli-command-reference" rel="noopener noreferrer"&gt;https://docs.hexabot.ai/developer-guide/cli-command-reference&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;hexabot: command not found&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This usually means the CLI was not installed globally or your npm global path is not available in your terminal.&lt;/p&gt;

&lt;p&gt;You can try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @hexabot-ai/cli &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or reinstall the CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @hexabot-ai/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Wrong Node.js version
&lt;/h3&gt;

&lt;p&gt;Use NVM to install and switch Node.js versions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;install &lt;/span&gt;20
nvm use 20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Port already in use
&lt;/h3&gt;

&lt;p&gt;If the app cannot start because a port is already being used, stop the process using that port or update your local configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Do Next
&lt;/h2&gt;

&lt;p&gt;Once your project is running, the next step is to create your first workflow.&lt;/p&gt;

&lt;p&gt;You can start here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.hexabot.ai/quickstart/create-your-1st-workflow" rel="noopener noreferrer"&gt;https://docs.hexabot.ai/quickstart/create-your-1st-workflow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also explore the installation guide:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.hexabot.ai/quickstart/installation" rel="noopener noreferrer"&gt;https://docs.hexabot.ai/quickstart/installation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Useful Links
&lt;/h2&gt;

&lt;p&gt;Hexabot Website:&lt;br&gt;
&lt;a href="https://hexabot.ai" rel="noopener noreferrer"&gt;https://hexabot.ai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Documentation:&lt;br&gt;
&lt;a href="https://docs.hexabot.ai" rel="noopener noreferrer"&gt;https://docs.hexabot.ai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Installation Guide:&lt;br&gt;
&lt;a href="https://docs.hexabot.ai/quickstart/installation" rel="noopener noreferrer"&gt;https://docs.hexabot.ai/quickstart/installation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setup Node.js with NVM:&lt;br&gt;
&lt;a href="https://docs.hexabot.ai/developer-guide/setup-node.js-with-nvm" rel="noopener noreferrer"&gt;https://docs.hexabot.ai/developer-guide/setup-node.js-with-nvm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CLI Command Reference:&lt;br&gt;
&lt;a href="https://docs.hexabot.ai/developer-guide/cli-command-reference" rel="noopener noreferrer"&gt;https://docs.hexabot.ai/developer-guide/cli-command-reference&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create Your First Workflow:&lt;br&gt;
&lt;a href="https://docs.hexabot.ai/quickstart/create-your-1st-workflow" rel="noopener noreferrer"&gt;https://docs.hexabot.ai/quickstart/create-your-1st-workflow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub Repository:&lt;br&gt;
&lt;a href="https://github.com/hexabot-ai/hexabot" rel="noopener noreferrer"&gt;https://github.com/hexabot-ai/hexabot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Community Forum:&lt;br&gt;
&lt;a href="https://community.hexabot.ai" rel="noopener noreferrer"&gt;https://community.hexabot.ai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;YouTube Channel:&lt;br&gt;
&lt;a href="https://www.youtube.com/@hexabot-videos" rel="noopener noreferrer"&gt;https://www.youtube.com/@hexabot-videos&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The Hexabot CLI is the easiest way to start building with Hexabot.&lt;/p&gt;

&lt;p&gt;In just a few commands, you can install the CLI, generate a new project, run it locally, and start creating AI workflows.&lt;/p&gt;

&lt;p&gt;If you find Hexabot useful, consider giving the repository a star on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/hexastack/hexabot" rel="noopener noreferrer"&gt; &lt;br&gt; Star the Hexabot Github Repository ⭐&lt;br&gt; &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It helps support the project and makes it easier for more developers to discover it.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>ai</category>
      <category>automation</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Automating LinkedIn Posts from Telegram with Hexabot</title>
      <dc:creator>Med Marrouchi</dc:creator>
      <pubDate>Fri, 15 May 2026 17:06:11 +0000</pubDate>
      <link>https://dev.to/marrouchi/automating-linkedin-posts-from-telegram-with-hexabot-1j4a</link>
      <guid>https://dev.to/marrouchi/automating-linkedin-posts-from-telegram-with-hexabot-1j4a</guid>
      <description>&lt;p&gt;In this article, I want to share a practical Hexabot demo: publishing a LinkedIn post directly from Telegram.&lt;/p&gt;

&lt;p&gt;The idea is simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You send a message to a Telegram bot.&lt;/li&gt;
&lt;li&gt;Hexabot receives it.&lt;/li&gt;
&lt;li&gt;An AI workflow prepares the LinkedIn post.&lt;/li&gt;
&lt;li&gt;The content is published to LinkedIn automatically.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a small example, but it demonstrates something important: AI workflows do not have to live only inside dashboards or internal tools. They can start from a conversation, connect to external services, use AI, and trigger real business actions.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/rPscG-TulyQ"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What we are building
&lt;/h2&gt;

&lt;p&gt;This example connects three main pieces:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Telegram&lt;/strong&gt; as the input channel&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hexabot&lt;/strong&gt; as the AI workflow automation engine&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LinkedIn&lt;/strong&gt; as the publishing destination&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The workflow starts when a user sends a message to a Telegram bot. Hexabot receives the message through the Telegram channel extension, processes it through a workflow, generates or formats the LinkedIn post using an AI model, then publishes it using the LinkedIn API.&lt;/p&gt;

&lt;p&gt;You can find the full example here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/hexabot-ai/linkedin-post-from-telegram-example" rel="noopener noreferrer"&gt;https://github.com/hexabot-ai/linkedin-post-from-telegram-example&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this example matters
&lt;/h2&gt;

&lt;p&gt;A lot of AI demos stop at generating text.&lt;/p&gt;

&lt;p&gt;But in real operations, generating text is rarely the final step.&lt;/p&gt;

&lt;p&gt;Usually, you need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;receive input from a user or a system&lt;/li&gt;
&lt;li&gt;understand the request&lt;/li&gt;
&lt;li&gt;transform it into structured content&lt;/li&gt;
&lt;li&gt;call an external API&lt;/li&gt;
&lt;li&gt;track what happened&lt;/li&gt;
&lt;li&gt;and keep the process reusable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is where workflow automation becomes useful.&lt;/p&gt;

&lt;p&gt;In this example, Telegram is not just a chat interface. It becomes the entry point for an automation process. LinkedIn is not just a manual publishing destination. It becomes an action executed by the workflow.&lt;/p&gt;

&lt;p&gt;Hexabot sits in the middle as the orchestration layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the workflow works
&lt;/h2&gt;

&lt;p&gt;At a high level, the flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Telegram message
      ↓
Hexabot Telegram channel
      ↓
AI workflow
      ↓
LinkedIn publisher action
      ↓
LinkedIn post
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A user sends a prompt such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Write me a LinkedIn post about this first test post that I sent from Telegram to my Hexabot LinkedIn integration.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hexabot receives the message, runs the imported workflow, uses the configured AI model to prepare the content, then publishes the final post to LinkedIn.&lt;/p&gt;

&lt;h2&gt;
  
  
  Main setup steps
&lt;/h2&gt;

&lt;p&gt;The repository includes a detailed README, but here is the overall process.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create a Hexabot project
&lt;/h3&gt;

&lt;p&gt;First, install the Hexabot CLI and create a new project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @hexabot-ai/cli
hexabot create hexabot-linkedin-bot
&lt;span class="nb"&gt;cd &lt;/span&gt;hexabot-linkedin-bot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then start the project locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hexabot dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The admin interface will be available at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Create a Telegram bot
&lt;/h3&gt;

&lt;p&gt;To receive messages from Telegram, you need to create a bot using &lt;code&gt;@BotFather&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In Telegram:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/start
/newbot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After choosing a name and username, Telegram gives you a bot token. This token will later be configured inside Hexabot as a credential.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Install the Telegram channel extension
&lt;/h3&gt;

&lt;p&gt;The example uses the Hexabot Telegram channel extension:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;hexabot-channel-telegram
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This extension allows Hexabot to receive messages from Telegram and use them as workflow inputs.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Expose your local API
&lt;/h3&gt;

&lt;p&gt;Telegram needs a public webhook URL to send messages to your local Hexabot instance.&lt;/p&gt;

&lt;p&gt;For local development, you can use a tunneling service such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ngrok
pinggy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once your local API is exposed, update your &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API_ORIGIN=https://your-public-url.example.com/api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Configure the Telegram source in Hexabot
&lt;/h3&gt;

&lt;p&gt;Inside the Hexabot admin panel, go to the sources settings page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000/settings/sources
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From there, configure the Telegram source:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;enable the source&lt;/li&gt;
&lt;li&gt;select the default workflow&lt;/li&gt;
&lt;li&gt;add the Telegram bot token credential&lt;/li&gt;
&lt;li&gt;add a webhook secret credential&lt;/li&gt;
&lt;li&gt;enable automatic webhook setup if needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows Telegram messages to be routed into the correct Hexabot workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Configure LinkedIn access
&lt;/h3&gt;

&lt;p&gt;To publish to LinkedIn, you need a LinkedIn developer application and an access token with the required permissions.&lt;/p&gt;

&lt;p&gt;The README walks through the process of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;creating a LinkedIn app&lt;/li&gt;
&lt;li&gt;enabling the required LinkedIn products&lt;/li&gt;
&lt;li&gt;generating an OAuth access token&lt;/li&gt;
&lt;li&gt;retrieving the LinkedIn &lt;code&gt;sub&lt;/code&gt; identifier&lt;/li&gt;
&lt;li&gt;using that identifier as the author reference for publishing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You will need two important values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LinkedIn access token
LinkedIn member identifier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These values are used by the LinkedIn publisher step in the workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Import the workflow
&lt;/h3&gt;

&lt;p&gt;The repository includes a ready-made workflow file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;linkedin-post-form-telegram.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import it from the Hexabot workflow editor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000/workflow-editor/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After importing it, configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the AI model provider&lt;/li&gt;
&lt;li&gt;the model name&lt;/li&gt;
&lt;li&gt;the AI API key credential&lt;/li&gt;
&lt;li&gt;the LinkedIn access token&lt;/li&gt;
&lt;li&gt;the default LinkedIn author identifier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once saved, the workflow is ready to run.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes Hexabot useful here
&lt;/h2&gt;

&lt;p&gt;This example is not only about publishing to LinkedIn.&lt;/p&gt;

&lt;p&gt;It shows how Hexabot can be used as an AI automation layer where workflows can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;start from a conversation&lt;/li&gt;
&lt;li&gt;connect to channels like Telegram&lt;/li&gt;
&lt;li&gt;use AI models&lt;/li&gt;
&lt;li&gt;call external APIs&lt;/li&gt;
&lt;li&gt;execute real actions&lt;/li&gt;
&lt;li&gt;stay self-hostable and extensible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For developers, this is especially useful because Hexabot workflows can be extended with custom actions, channels, and integrations.&lt;/p&gt;

&lt;p&gt;That means you are not limited to Telegram and LinkedIn.&lt;/p&gt;

&lt;p&gt;The same pattern could be adapted for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;posting to other social platforms&lt;/li&gt;
&lt;li&gt;creating CRM notes&lt;/li&gt;
&lt;li&gt;sending internal notifications&lt;/li&gt;
&lt;li&gt;generating support replies&lt;/li&gt;
&lt;li&gt;preparing marketing content&lt;/li&gt;
&lt;li&gt;triggering approval workflows&lt;/li&gt;
&lt;li&gt;building internal AI assistants&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;This Telegram-to-LinkedIn example is intentionally simple, but it shows the power of connecting conversations with real automation.&lt;/p&gt;

&lt;p&gt;Instead of opening multiple tools, copying text, formatting content, and publishing manually, you can start the whole process from a Telegram message and let Hexabot orchestrate the workflow.&lt;/p&gt;

&lt;p&gt;You can explore the full example here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/hexabot-ai/linkedin-post-from-telegram-example" rel="noopener noreferrer"&gt;https://github.com/hexabot-ai/linkedin-post-from-telegram-example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if you find Hexabot useful, consider giving the main repository a star on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/hexastack/hexabot" rel="noopener noreferrer"&gt; &lt;br&gt; Star the Hexabot Github Repository ⭐&lt;br&gt; &lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>tooling</category>
      <category>programming</category>
    </item>
    <item>
      <title>First Night at Web Summit 2024: The Energy is Electric!</title>
      <dc:creator>Med Marrouchi</dc:creator>
      <pubDate>Mon, 11 Nov 2024 17:08:14 +0000</pubDate>
      <link>https://dev.to/marrouchi/first-night-at-web-summit-2024-the-energy-is-electric-4561</link>
      <guid>https://dev.to/marrouchi/first-night-at-web-summit-2024-the-energy-is-electric-4561</guid>
      <description>&lt;p&gt;Stepping into the opening night of Web Summit 2024 in Lisbon feels like stepping into the beating heart of innovation. The venue is packed, buzzing with excitement as thousands of attendees gather from around the globe. The sheer energy in the air is palpable, and it’s clear this is the place to be for anyone passionate about technology, startups, and groundbreaking ideas.&lt;/p&gt;

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

&lt;p&gt;For me, this night is just the beginning. I’m thrilled to announce that on Wednesday, I’ll be showcasing &lt;a href="https://hexabot.ai" rel="noopener noreferrer"&gt;Hexabot&lt;/a&gt;, our open-source conversational AI builder. Hexabot has been a labor of love, and I can’t wait to share it with the world.&lt;/p&gt;

&lt;p&gt;Stay tuned for more updates as the week unfolds. If you’re attending, swing by our booth on Wednesday—we’d love to meet you and hear your thoughts. Let’s make this Web Summit an unforgettable experience!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>websummit</category>
      <category>startup</category>
      <category>opensource</category>
    </item>
    <item>
      <title>5 Interesting New Github Repos You Need to Explore</title>
      <dc:creator>Med Marrouchi</dc:creator>
      <pubDate>Wed, 06 Nov 2024 09:28:59 +0000</pubDate>
      <link>https://dev.to/marrouchi/5-interesting-new-github-repos-you-need-to-explore-2oi</link>
      <guid>https://dev.to/marrouchi/5-interesting-new-github-repos-you-need-to-explore-2oi</guid>
      <description>&lt;p&gt;If you're like me, always on the lookout for cool new projects to dive into on GitHub, you're in for a treat! I've rounded up five standout repositories that are making waves right now—whether you're into chatbot builders, next-gen CRM, document parsing, or visualizing cloud architecture, there's something here for everyone. Let's explore!&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;a href="https://github.com/hexastack/hexabot" rel="noopener noreferrer"&gt;Hexabot&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Hexabot is conversational AI builder that enables you to create and manage bots, chatbots and/or agents, across multiple channels with a visual editor. It includes a plugin system that makes it highly customizable and extendable. There is even an extension library from where you can download extensions like plugins, channels, etc to add additional features: &lt;a href="https://hexabot.ai/extensions" rel="noopener noreferrer"&gt;https://hexabot.ai/extensions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/hexastack/hexabot" rel="noopener noreferrer"&gt;Star on GitHub ⭐ - Hexabot&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;a href="https://github.com/yobix-ai/extractous" rel="noopener noreferrer"&gt;Extractous&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Extractous offers a fast and efficient solution for extracting content and metadata from various document types such as PDF, Word, HTML, and many other formats. Built in Rust, Extractous delivers speed and efficiency while providing bindings for many programming languages. Whether you're working with documents in different formats or building your own document processing pipeline, Extractous is here to help.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/yobix-ai/extractous" rel="noopener noreferrer"&gt;Star on GitHub ⭐ - Extractous&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;a href="https://github.com/twentyhq/twenty" rel="noopener noreferrer"&gt;Twenty&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The CRM landscape is evolving, and Twenty is leading the charge into a new era of customer relationship management. Say goodbye to vendor lock-in and say hello to full freedom: host it yourself, fork it, contribute back—the choice is yours. Inspired by Notion, Twenty makes it intuitive to track customers, create opportunities, take notes, and manage tasks with a beautiful interface that's built for you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/twentyhq/twenty" rel="noopener noreferrer"&gt;Star on GitHub ⭐ - Twenty&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;a href="https://github.com/DS4SD/docling" rel="noopener noreferrer"&gt;Docling&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Docling makes document parsing as easy as it should be. Whether you're dealing with PDFs, DOCX, PPTX, HTML, or even scanned images, Docling can transform them into Markdown or JSON with minimal hassle. It's perfect for anyone looking to integrate document parsing into a workflow, with powerful tools like OCR and advanced document understanding capabilities to handle tables and layouts.&lt;/p&gt;

&lt;p&gt;If you're working with LlamaIndex or LangChain, Docling integrates seamlessly, making it a great choice for RAG or QA applications. Go ahead and &lt;a href="https://github.com/DS4SD/docling" rel="noopener noreferrer"&gt;star Docling&lt;/a&gt; if this sounds like something you need—it's a must-have tool for document wrangling.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/DS4SD/docling" rel="noopener noreferrer"&gt;Star on GitHub ⭐ - Docling&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;a href="https://github.com/mingrammer/diagrams" rel="noopener noreferrer"&gt;Diagrams&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Diagrams lets you create system architecture diagrams using Python code. Imagine being able to describe cloud system architectures—AWS, Azure, GCP, Kubernetes—all through Python without ever touching a diagramming tool. This is Diagram-as-Code at its finest, providing a way to visualize, share, and track your architecture plans in version control.&lt;/p&gt;

&lt;p&gt;From on-premises nodes to SaaS solutions, &lt;a href="https://github.com/mingrammer/diagrams" rel="noopener noreferrer"&gt;Diagrams&lt;/a&gt; supports them all, making it perfect for prototyping or documenting your existing setup. Interested? Give it a try and don't forget to star the project if you find it useful!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mingrammer/diagrams" rel="noopener noreferrer"&gt;Star on GitHub ⭐ - Diagrams&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;These are some of the most interesting repositories that you should definitely check out if you haven't already. Be sure to give them a star if you find value in what they're doing—a simple star can help projects grow and gain the attention they deserve. Which one are you going to explore first?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>How I used an OpenSource LLM in Wordpress</title>
      <dc:creator>Med Marrouchi</dc:creator>
      <pubDate>Tue, 05 Nov 2024 09:09:15 +0000</pubDate>
      <link>https://dev.to/marrouchi/how-i-used-a-opensource-llm-in-wordpress-5b1a</link>
      <guid>https://dev.to/marrouchi/how-i-used-a-opensource-llm-in-wordpress-5b1a</guid>
      <description>&lt;p&gt;Today, I'll guide you through integrating an open source LLM model into a WordPress website using Hexabot—a powerful, open source AI conversational builder that lets you create chatbots or AI agents. If you love open source projects, consider giving Hexabot a star on GitHub and exploring our documentation. Let’s get started!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/hyJW6JGCga4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Install Hexabot CLI
&lt;/h3&gt;

&lt;p&gt;First, you'll need to install the Hexabot CLI globally. You can do this easily using npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; hexabot-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create a new Hexabot project by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hexabot create wordpress-chatbot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will generate a folder containing your chatbot project. Navigate to the new project directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;wordpress-chatbot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the necessary dependencies by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before proceeding, make sure you have Node.js and Docker installed, as Docker is required to run the project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Initialize Hexabot
&lt;/h3&gt;

&lt;p&gt;After installing the dependencies, initialize the environment file "docker/.env":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hexabot init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will generate an environment configuration file. Once done, you can launch your project in development mode by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hexabot dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will also need to enable &lt;strong&gt;Ollama&lt;/strong&gt;, an open source LLM tool, which is integrated by default to run the AI model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Setting Up Ollama
&lt;/h3&gt;

&lt;p&gt;Ollama is an important part of our setup, as it handles the open source LLM model that powers your chatbot. Once you’ve started the services, it’s time to configure Ollama.&lt;/p&gt;

&lt;p&gt;To pull the required LLM model (for example, &lt;strong&gt;Ollama 3.2&lt;/strong&gt;), SSH into the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-ti&lt;/span&gt; ollama bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then pull the model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull ollama-3.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the model is pulled, you’re ready to configure the chatbot in the Hexabot admin panel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Accessing the Admin Panel
&lt;/h3&gt;

&lt;p&gt;With the services up and running, open your browser and head to &lt;code&gt;http://localhost:8080&lt;/code&gt;. This will open the Hexabot admin panel.&lt;/p&gt;

&lt;p&gt;Navigate to the &lt;strong&gt;Visual Editor&lt;/strong&gt;. Here, you can drag and drop blocks into the canvas to create the conversation flow for your chatbot. Add the Ollama block plugin to enable the AI model response. Configure the plugin settings, such as defining a context like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"You are an AI assistant working for Etudes, an architecture firm."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Make sure you also pull the appropriate model as instructed in the previous step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Integrate Hexabot with Your WordPress Website
&lt;/h3&gt;

&lt;p&gt;Now, let’s connect this chatbot to your WordPress website. First, navigate to your WordPress project and start your site using Docker Compose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;path/to/wordpress

docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Access your WordPress site, then go to the &lt;strong&gt;Plugins&lt;/strong&gt; section and search for the &lt;strong&gt;Hexabot plugin&lt;/strong&gt;. Install and activate it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Configure the Chat Widget
&lt;/h3&gt;

&lt;p&gt;Once the Hexabot plugin is activated, go to the &lt;strong&gt;Settings&lt;/strong&gt; to configure the chat widget. You’ll need to set the &lt;strong&gt;API URL&lt;/strong&gt; to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:4000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure the correct token is set, and select the &lt;strong&gt;web channel&lt;/strong&gt; to complete the configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 7: Customize the Widget
&lt;/h3&gt;

&lt;p&gt;After adding the widget to your site, you can further customize it by changing its settings. For example, you can adjust the widget title, colors, and other elements to match the branding of your WordPress website. Refresh your website, and you should see the widget live and ready to engage with users.&lt;/p&gt;

&lt;p&gt;Try interacting with your chatbot: say "Hello" and watch as Ollama powers the responses, providing the AI experience you configured earlier. You can further tweak the settings to provide a personalized touch.&lt;/p&gt;

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

&lt;p&gt;Congratulations! You've successfully integrated an open source LLM with your WordPress website using Hexabot. This setup allows you to build a powerful and interactive chatbot, perfect for engaging users directly on your WordPress platform.&lt;/p&gt;

&lt;p&gt;If you found this guide helpful, please consider starring our &lt;a href="https://github.com//hexastack/hexabot" rel="noopener noreferrer"&gt;Hexabot GitHub repository&lt;/a&gt; and getting involved in our community. Hexabot is built by the community, for the community, and we would love for you to join our journey! You can also connect with us on &lt;a href="https://discord.gg/rNb9t2MFkG" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;, and check out our &lt;a href="https://www.youtube.com/@hexabot-videos" rel="noopener noreferrer"&gt;YouTube channel&lt;/a&gt; for more tutorials and tips.&lt;/p&gt;

&lt;p&gt;Thanks for reading, and happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>llm</category>
      <category>wordpress</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Top 8 OpenSource Tools for AI Startups</title>
      <dc:creator>Med Marrouchi</dc:creator>
      <pubDate>Mon, 28 Oct 2024 07:37:28 +0000</pubDate>
      <link>https://dev.to/marrouchi/top-8-opensource-tools-for-ai-startups-196g</link>
      <guid>https://dev.to/marrouchi/top-8-opensource-tools-for-ai-startups-196g</guid>
      <description>&lt;p&gt;Are you building the next AI unicorn? 🦄&lt;/p&gt;

&lt;p&gt;Whether you're in the early stages of an AI startup or scaling up, having the right set of open-source tools can make a world of difference. I've put together a list of some top-notch open-source tools that have been invaluable to me, and I think they'll be incredibly helpful for your AI journey too:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Hexabot&lt;/strong&gt;
&lt;/h3&gt;

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

&lt;p&gt;If you're building AI-powered chatbots, you need something flexible, powerful, and open. &lt;a href="https://github.com/hexastack/hexabot" rel="noopener noreferrer"&gt;&lt;strong&gt;Hexabot&lt;/strong&gt;&lt;/a&gt; is an open-source chatbot solution designed to be highly extensible. It supports multi-channel chat, powerful NLP capabilities, and a great plugin system. Perfect for rapid prototyping or launching your chatbot product.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/hexastack/hexabot" rel="noopener noreferrer"&gt;Star on GitHub ⭐ - Hexabot&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;StableStudio&lt;/strong&gt;
&lt;/h3&gt;

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

&lt;p&gt;StableStudio is Stability AI's official open-source version of DreamStudio, providing a user-friendly interface for generative AI. This web-based application enables users to create and edit generated images, and we're eager to see how the community contributes to its evolution!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Stability-AI/StableStudio" rel="noopener noreferrer"&gt;Star on GitHub ⭐ - StableStudio&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;ChatGPT4all&lt;/strong&gt;
&lt;/h3&gt;

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

&lt;p&gt;Generative AI is hot, and &lt;a href="https://github.com/nomic-ai/gpt4all" rel="noopener noreferrer"&gt;&lt;strong&gt;ChatGPT4all&lt;/strong&gt;&lt;/a&gt; is an exciting open-source option. It allows you to run your own language model without needing proprietary APIs, enabling a private and customizable experience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/nomic-ai/gpt4all" rel="noopener noreferrer"&gt;Star on GitHub ⭐ - ChatGPT4all&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Ollama&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;Ollama&lt;/strong&gt;&lt;/a&gt; is an emerging tool that helps you bring open LLMs into production with ease. It simplifies serving and running models in a production environment, whether on the cloud or locally. It's the bridge between prototyping LLMs and making them work for your customers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ollama/ollama" rel="noopener noreferrer"&gt;Star on GitHub ⭐ - Ollama&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;MLflow&lt;/strong&gt;
&lt;/h3&gt;

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

&lt;p&gt;Managing experiments, versioning, and deployments can quickly get chaotic. &lt;a href="https://mlflow.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;MLflow&lt;/strong&gt;&lt;/a&gt; is an open-source platform that helps with tracking experiments, managing models, and deploying them. It’s a must-have tool if you're serious about ML engineering.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mlflow/mlflow" rel="noopener noreferrer"&gt;Star on GitHub ⭐ - MLflow&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;TensorFlow&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This one hardly needs an introduction. &lt;a href="https://www.tensorflow.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;TensorFlow&lt;/strong&gt;&lt;/a&gt; by Google is a staple for many AI projects. It’s an end-to-end open-source platform for machine learning, capable of handling everything from initial prototyping to full deployment in production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/tensorflow/tensorflow" rel="noopener noreferrer"&gt;Star on GitHub ⭐ - Tensorflow&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;PyTorch&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For those who prefer a more flexible, Pythonic interface, &lt;a href="https://pytorch.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;PyTorch&lt;/strong&gt;&lt;/a&gt; is often the way to go. Its dynamic computation graphs and ease of use have made it a favorite for researchers and AI startups alike. Plus, the thriving PyTorch community means plenty of support and open-source examples.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/pytorch/pytorch" rel="noopener noreferrer"&gt;Star on GitHub ⭐ - PyTorch&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Keras&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you need simplicity, &lt;a href="https://keras.io/" rel="noopener noreferrer"&gt;&lt;strong&gt;Keras&lt;/strong&gt;&lt;/a&gt; is a great high-level API built on top of TensorFlow. It lets you quickly prototype neural networks without worrying about low-level implementations. Keras is perfect for getting those first models up and running—an essential part of the startup hustle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/keras-team/keras" rel="noopener noreferrer"&gt;Star on GitHub ⭐ - Keras&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These tools have proven themselves time and time again, not only in the projects I've worked on but also within the broader AI community. Whether you are building advanced NLP systems, tackling MLOps, or developing a full-fledged chatbot platform, these open-source tools can accelerate your development, save you time, and help you avoid reinventing the wheel.&lt;/p&gt;

&lt;p&gt;Have you used any of these tools? Which ones have made the biggest impact in your startup journey? I'd love to hear about your experience!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>startup</category>
      <category>ai</category>
    </item>
    <item>
      <title>Why Vivaldi Might Be the Browser You've Been Waiting For</title>
      <dc:creator>Med Marrouchi</dc:creator>
      <pubDate>Sat, 12 Oct 2024 22:52:19 +0000</pubDate>
      <link>https://dev.to/marrouchi/why-vivaldi-might-be-the-browser-youve-been-waiting-for-4n4j</link>
      <guid>https://dev.to/marrouchi/why-vivaldi-might-be-the-browser-youve-been-waiting-for-4n4j</guid>
      <description>&lt;p&gt;Why Vivaldi Might Be the Browser You've Been Waiting For&lt;/p&gt;

&lt;p&gt;In a web dominated by mainstream browsers, Vivaldi stands out as a refreshing alternative, offering a unique approach to browsing that prioritizes customization, privacy, and user empowerment. If you’ve ever felt that your current browser falls short of catering to your specific needs, Vivaldi might just be the solution you didn’t know you needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Ultimate Customization
&lt;/h2&gt;

&lt;p&gt;At its core, Vivaldi is designed for power users who demand flexibility and control over their browsing environment. Unlike other browsers that offer limited customization, Vivaldi allows you to fine-tune every aspect of your browsing experience, from interface colors and tab management to keyboard shortcuts and even mouse gestures. Whether you’re someone who likes to keep things minimal or prefer a feature-rich setup, Vivaldi adapts to your preferences effortlessly.&lt;/p&gt;

&lt;p&gt;Two-Level Tab Stacking&lt;/p&gt;

&lt;p&gt;Tab chaos can quickly become a nightmare, but Vivaldi’s innovative two-level tab stacks help you group and navigate your tabs in an intuitive way. With visual tab previews and the ability to stack unlimited tabs, you can organize your workspace more efficiently and save time as you switch between tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Privacy Built-In, Not Bolted On
&lt;/h2&gt;

&lt;p&gt;In today’s internet landscape, privacy is a key concern. With Vivaldi, privacy isn't just a feature—it’s part of their philosophy. The browser blocks trackers and prevents ads from invading your browsing space without relying on third-party plugins. Most importantly, Vivaldi doesn’t track your behavior, giving you the freedom to browse without worrying about surveillance or profiling. And with end-to-end encryption on synced data, even your passwords and browsing history are protected from prying eyes.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. All-in-One Tools
&lt;/h2&gt;

&lt;p&gt;Forget the endless parade of extensions. Vivaldi comes with built-in tools that reduce your reliance on third-party apps, all while keeping your data secure. With features like:&lt;/p&gt;

&lt;p&gt;Private email client (yes, built into your browser),&lt;/p&gt;

&lt;p&gt;Calendar,&lt;/p&gt;

&lt;p&gt;Feed reader,&lt;/p&gt;

&lt;p&gt;Quick note taker, and&lt;/p&gt;

&lt;p&gt;Full-page screen capture,&lt;/p&gt;

&lt;p&gt;Vivaldi packs a punch, ensuring that you have everything you need in one place, saving you time and effort.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Seamless Syncing Across Devices
&lt;/h2&gt;

&lt;p&gt;Another standout feature is Vivaldi’s seamless syncing capabilities. Whether you’re using Vivaldi on your desktop, tablet, or mobile, you can securely sync your browsing history, bookmarks, and even open tabs with end-to-end encryption. Your data is stored on servers in Iceland, protected by some of the world’s strictest privacy laws, so you can trust that your information stays where it belongs—under your control.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Designed for Mobile
&lt;/h2&gt;

&lt;p&gt;Vivaldi’s mobile version isn’t just an afterthought. It’s equipped with the same powerful features you’d expect on desktop, including an ad blocker, tracking protection, and the ability to sync with your desktop effortlessly. Vivaldi also brings its customization magic to mobile, allowing you to tailor your experience even on the go.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Why Choose Vivaldi?
&lt;/h2&gt;

&lt;p&gt;With Big Tech increasingly encroaching on our privacy and pushing their own agendas, Vivaldi offers an escape—a way to take back control of your browsing experience without compromising on speed, security, or customization. It’s not just a browser; it’s a statement against the way the web is increasingly commodified, reminding us that the internet can be a place where privacy and personalization coexist.&lt;/p&gt;

&lt;p&gt;Get away from Big Tech, and have fun doing it—that’s Vivaldi in a nutshell.&lt;/p&gt;

&lt;p&gt;Download Vivaldi today and start experiencing the web on your terms: &lt;a href="https://vivaldi.com/" rel="noopener noreferrer"&gt;https://vivaldi.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>web3</category>
      <category>web</category>
      <category>html</category>
    </item>
    <item>
      <title>6 Best Open-Source AI Chatbot Builders 🔥</title>
      <dc:creator>Med Marrouchi</dc:creator>
      <pubDate>Sat, 12 Oct 2024 08:31:31 +0000</pubDate>
      <link>https://dev.to/marrouchi/6-best-open-source-ai-chatbot-builder-29jk</link>
      <guid>https://dev.to/marrouchi/6-best-open-source-ai-chatbot-builder-29jk</guid>
      <description>&lt;p&gt;Open-source chatbots are not just tools for automated responses—they represent a thriving community of developers who contribute to building versatile, transparent, and customizable conversational agents. Whether you’re looking to embed a chatbot on a website, create a corporate assistant, or explore the potential of AI-based chat, open-source solutions provide the flexibility and power to make your vision a reality.&lt;/p&gt;

&lt;p&gt;Here’s a look at six of the best open-source chatbots available today, from visual no-code builders to frameworks that let you build chatbots tailored to your specific needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Hexabot ⭐️
&lt;/h3&gt;

&lt;p&gt;Hexabot is an advanced open-source chatbot builder that focuses on AI-powered, multilingual, and highly customizable chatbots. With its open plugin system, Hexabot makes it easy to extend the functionality by adding new channels, blocks, or integrations. Developers will love the rich feature set: a visual editor for chat flows, an analytics dashboard, and multilingual capabilities are just a few highlights.&lt;/p&gt;

&lt;p&gt;Hexabot is built for developers who need more control over customization while still being straightforward to use. The project is licensed under AGPLv3, encouraging community collaboration while ensuring fair use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/hexastack/hexabot" rel="noopener noreferrer"&gt;GitHub - Hexabot&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Typebot 🌐
&lt;/h3&gt;

&lt;p&gt;Serving the same purpose as TypeForm, Typebot is a lightweight open-source chatbot builder designed for simplicity. The drag-and-drop UI allows users to create automated chat flows without writing a single line of code. Typebot excels in scenarios where you need a chatbot to answer repetitive questions—like customer support or educational use cases.&lt;/p&gt;

&lt;p&gt;If you’re a beginner looking to launch a chatbot without worrying about code, Typebot is a perfect fit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/baptisteArno/typebot.io" rel="noopener noreferrer"&gt;GitHub - Typebot&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Botpress: No-Code Visual Chatbot Builder 🖋️
&lt;/h3&gt;

&lt;p&gt;Botpress is well-known for its powerful visual flow editor, where users can build conversational agents without diving into the complexities of programming. This is a chatbot solution that fits perfectly in environments that value a graphical, low-code approach to bot creation—ideal for both small businesses and large enterprises.&lt;/p&gt;

&lt;p&gt;Botpress also provides NLU capabilities to ensure that chatbots can understand natural language, making it a great choice for non-technical users looking for an effective solution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/botpress/botpress" rel="noopener noreferrer"&gt;GitHub - Botpress&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Rasa: The Developer’s Choice for Custom Chatbots 🛠️
&lt;/h3&gt;

&lt;p&gt;Rasa is a open-source frameworks for building highly customized chatbots, particularly for enterprise-level solutions. Written in Python, it offers extensive tools for NLU, dialogue management, and integrations with a variety of services.&lt;/p&gt;

&lt;p&gt;Rasa stands out as a great choice for developers building serious, sophisticated chatbots tailored to specific corporate requirements. Its flexibility and support for conversational AI pipelines give it a unique edge in custom projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/RasaHQ/rasa" rel="noopener noreferrer"&gt;GitHub - Rasa&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Tock: Offline-First Chatbots for Embedded Devices 🛡️
&lt;/h3&gt;

&lt;p&gt;Tock is an impressive open-source platform that targets not just cloud-based chat but also embedded devices. Designed with an offline-first approach, Tock makes it possible to run chatbots on devices that do not have stable Internet connectivity—ideal for use cases in IoT, vehicles, or other scenarios where embedded intelligence is crucial.&lt;/p&gt;

&lt;p&gt;If you need a solution for creating chatbots on embedded devices with or without an Internet connection, Tock is a solid choice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/theopenconversationkit/tock" rel="noopener noreferrer"&gt;GitHub - Tock&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  6. BotMan: PHP-Powered Conversational Bots 💻
&lt;/h3&gt;

&lt;p&gt;BotMan is an open-source chatbot framework specifically for PHP developers. It provides an easy-to-use syntax to create conversational agents that can be integrated with messaging services like Slack, Telegram, Facebook Messenger, and others.&lt;/p&gt;

&lt;p&gt;For those in the PHP ecosystem, BotMan is an excellent tool for building chatbots, providing well-documented features and community-driven support.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/botman/botman" rel="noopener noreferrer"&gt;GitHub - BotMan&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Honorable Mentions: DeepPavlov &amp;amp; HuggingChat 🤖💖
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DeepPavlov&lt;/strong&gt;: An AI framework for creating highly advanced conversational agents and virtual assistants. It offers pre-built deep learning models and flexibility to develop sophisticated applications.&lt;br&gt;
&lt;a href="https://github.com/deeppavlov/DeepPavlov" rel="noopener noreferrer"&gt;GitHub - DeepPavlov&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;HuggingChat&lt;/strong&gt;: HuggingChat uses open-source GPT-based models for building conversational experiences that leverage natural language generation. Perfect if you want to bring LLM capabilities to your chatbot projects.&lt;br&gt;
&lt;a href="https://github.com/huggingface/chat-ui" rel="noopener noreferrer"&gt;GitHub - HuggingChat&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Open-source chatbots offer endless possibilities—from simple, no-code tools to frameworks that power sophisticated AI. Depending on your needs—whether it's no-code simplicity with Botpress, custom development with Rasa, embedded applications with Tock, or multilingual chatbots with Hexabot—you’ll find an open-source solution that fits your project perfectly.&lt;/p&gt;

&lt;p&gt;Join these open-source communities and contribute to make conversational AI accessible to everyone. Which of these chatbot platforms have you tried, or are planning to use? Let me know in the comments!&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>webdev</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Understanding the Shadow DOM and When to Use It</title>
      <dc:creator>Med Marrouchi</dc:creator>
      <pubDate>Thu, 10 Oct 2024 18:10:29 +0000</pubDate>
      <link>https://dev.to/marrouchi/understanding-the-shadow-dom-and-when-to-use-it-44hc</link>
      <guid>https://dev.to/marrouchi/understanding-the-shadow-dom-and-when-to-use-it-44hc</guid>
      <description>&lt;h3&gt;
  
  
  Understanding the Shadow DOM and When to Use It
&lt;/h3&gt;

&lt;p&gt;The Shadow DOM is a powerful feature in the modern web development toolkit that helps developers encapsulate elements and isolate styles. Essentially, the Shadow DOM allows you to create a "mini-DOM" inside an element that is completely isolated from the rest of the page. This means that the CSS and JavaScript inside this shadow DOM won't interfere with anything outside of it, and vice versa.&lt;/p&gt;

&lt;p&gt;One of the key problems the Shadow DOM solves is CSS style leakage—where styles defined for one part of your application inadvertently affect other parts, leading to a lack of predictability and harder-to-maintain code. The Shadow DOM creates a style boundary, preventing this issue.&lt;/p&gt;

&lt;p&gt;Here's an example use case where the Shadow DOM is particularly useful:&lt;/p&gt;

&lt;p&gt;Imagine you have a chatbot widget—like the Hexabot widget—that you want to embed on multiple websites. Each of these websites has its own CSS, and some styles might interfere with how your widget should look and behave. For instance, a website might have global styles for &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; elements, and if your widget's elements are simply added to the DOM, those styles could change the look and feel of your widget.&lt;/p&gt;

&lt;p&gt;To prevent the website's CSS from conflicting with your widget's CSS, you can leverage the Shadow DOM to encapsulate your widget. Here's a simple example to illustrate this:&lt;/p&gt;

&lt;h4&gt;
  
  
  Without Shadow DOM:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;crossorigin&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/react@18/umd/react.production.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;crossorigin&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"./style.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;&amp;lt;WIDGET URL&amp;gt;&amp;gt;/hexabot-widget.umd.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"hb-chat-widget"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;domContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hb-chat-widget&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;el&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HexabotWidget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;apiUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.yourdomain.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token123&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;domContainer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, any global styles from the website might interfere with the widget's look.&lt;/p&gt;

&lt;h4&gt;
  
  
  With Shadow DOM:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;crossorigin&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/react@18/umd/react.production.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;crossorigin&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/react-dom@18/umd/react-dom.production.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;&amp;lt;WIDGET URL&amp;gt;&amp;gt;/hexabot-widget.umd.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"hb-chat-widget"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;// Create the shadow root and attach it to the widget container&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shadowContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hb-chat-widget&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="nf"&gt;attachShadow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;open&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;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; 
        &lt;span class="nx"&gt;shadowContainer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;link&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;rel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stylesheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;&amp;lt;WIDGET URL&amp;gt;&amp;gt;/style.css&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="c1"&gt;// Render the widget inside the shadow root&lt;/span&gt;
  &lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HexabotWidget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;apiUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.yourdomain.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token123&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;shadowContainer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this version, the widget is rendered inside a shadow root. This means that the styles defined for the website won't impact the widget, and vice versa. The CSS styles for your widget are kept isolated, ensuring a consistent look across any website the widget is embedded in.&lt;/p&gt;

&lt;h3&gt;
  
  
  When Should You Use the Shadow DOM?
&lt;/h3&gt;

&lt;p&gt;The Shadow DOM is useful whenever you need to create self-contained components that won't be affected by or affect other parts of the application. Here are some scenarios where you should consider using it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Widgets or Plugins:&lt;/strong&gt; When developing reusable widgets that could be embedded in various environments, using the Shadow DOM will prevent external CSS conflicts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex UI Components:&lt;/strong&gt; If you're building custom elements like sliders, carousels, or other UI components where you want tight control over styling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolation Needs:&lt;/strong&gt; Any scenario where you need complete isolation of CSS and JavaScript to avoid unintentional interactions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By encapsulating the styles and behavior of a component, the Shadow DOM can be a crucial tool for developers building modular, reusable, and robust web components.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/hexastack/hexabot" rel="noopener noreferrer"&gt;Hexabot&lt;/a&gt; live chat widget uses this method to ensure a seamless and consistent user experience across different websites, without any interference from external styles. If you're interested in seeing this in action, feel free to check out Hexabot and star the GitHub repository to support the project!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/hexastack/hexabot" rel="noopener noreferrer"&gt; &lt;br&gt; Star the Hexabot Github Repository ⭐&lt;br&gt; &lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>css</category>
    </item>
    <item>
      <title>Gemini + Facebook Bot with Hexabot.ai</title>
      <dc:creator>Med Marrouchi</dc:creator>
      <pubDate>Mon, 07 Oct 2024 17:52:36 +0000</pubDate>
      <link>https://dev.to/marrouchi/gemini-facebook-bot-with-hexabotai-4gcg</link>
      <guid>https://dev.to/marrouchi/gemini-facebook-bot-with-hexabotai-4gcg</guid>
      <description>&lt;p&gt;In our latest video, we showcased the basics of &lt;strong&gt;Hexabot&lt;/strong&gt;, diving into how to setup and build a basic chat flow. If you’ve been following along with our development journey, this is one video you don’t want to miss!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/sHALCSB7fiA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Here’s a breakdown of what we covered:
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Natural Language Understanding (NLU) for Intent Detection
&lt;/h3&gt;

&lt;p&gt;We demonstrated how &lt;strong&gt;Hexabot's NLU&lt;/strong&gt; takes chatbot interactions to the next level. While simple keyword matching works in many cases, NLU allows the bot to truly understand user intent. For example, if the user says "good morning" or "hello," Hexabot can correctly detect the greeting intent and respond accordingly, regardless of the variation in phrases.&lt;/p&gt;

&lt;p&gt;The NLU engine also allows you to &lt;strong&gt;train custom models&lt;/strong&gt; by importing your own datasets. You can then configure the bot to identify and infer user intent, which is a game changer for more complex conversational flows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multilingual Support
&lt;/h3&gt;

&lt;p&gt;With Hexabot’s robust &lt;strong&gt;multilingual support&lt;/strong&gt;, you can easily create chatbots that speak multiple languages. The built-in localization manager makes it simple to define languages, translate messages, and ensure that your chatbot can communicate effectively with users around the world. &lt;/p&gt;

&lt;p&gt;In our demo, we translated messages into French, enabling the chatbot to seamlessly switch between English and French, responding to users based on their preferred language. Imagine the possibilities for global customer engagement!&lt;/p&gt;

&lt;h3&gt;
  
  
  Google Gemini Integration for Generative AI
&lt;/h3&gt;

&lt;p&gt;Next, we explored Hexabot’s integration with &lt;strong&gt;Google Gemini&lt;/strong&gt; to unlock generative AI capabilities. This allows Hexabot to generate intelligent, context-aware responses based on user input, making conversations feel even more natural.&lt;/p&gt;

&lt;p&gt;Installing the &lt;strong&gt;Gemini plugin&lt;/strong&gt; is as simple as running a command in your terminal. Once set up, Hexabot can use the Gemini API to provide detailed responses, grounded in knowledge from predefined content. For example, we set up a scenario where Hexabot acts as a pizza shop assistant, offering real-time pizza suggestions like a pro!&lt;/p&gt;

&lt;h3&gt;
  
  
  Facebook Messenger Integration
&lt;/h3&gt;

&lt;p&gt;To top it off, we demonstrated how to connect Hexabot to &lt;strong&gt;Facebook Messenger&lt;/strong&gt;, enabling you to engage with users directly on your business page. By installing the &lt;strong&gt;Messenger channel plugin&lt;/strong&gt;, Hexabot can communicate with your Facebook audience, providing real-time responses and handling customer queries effortlessly.&lt;/p&gt;

&lt;p&gt;With easy-to-follow steps, you can configure your chatbot’s connection to Facebook, ensuring your chatbot is live and ready to assist customers on Messenger, whether it's for pizza orders or any other use case.&lt;/p&gt;




&lt;h3&gt;
  
  
  Want to Try Hexabot for Yourself?
&lt;/h3&gt;

&lt;p&gt;If you're excited about the potential of Hexabot, now is the time to dive in! Whether you’re looking to build a multilingual chatbot, integrate powerful generative AI, or set up multi-channel support, Hexabot’s open-source framework is ready to handle it all.&lt;/p&gt;

&lt;p&gt;Head over to our &lt;a href="https://github.com/hexastack/hexabot" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; to get started and explore the full documentation. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/hexastack/hexabot" rel="noopener noreferrer"&gt; &lt;br&gt; Star the Hexabot Github Repository ⭐&lt;br&gt; &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have any questions or suggestions for future videos? Drop a comment below or join the conversation with our amazing community. Don’t forget to &lt;strong&gt;subscribe&lt;/strong&gt; to our channel for more deep dives into Hexabot's capabilities!&lt;/p&gt;

&lt;p&gt;Until next time, happy coding! 👾&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>beginners</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Setup SSL with Certbot + Nginx in a Dockerized App</title>
      <dc:creator>Med Marrouchi</dc:creator>
      <pubDate>Sun, 06 Oct 2024 09:37:44 +0000</pubDate>
      <link>https://dev.to/marrouchi/the-challenge-about-ssl-in-docker-containers-no-one-talks-about-32gh</link>
      <guid>https://dev.to/marrouchi/the-challenge-about-ssl-in-docker-containers-no-one-talks-about-32gh</guid>
      <description>&lt;p&gt;If you've ever struggled with setting up SSL in a Docker environment, you're not alone. SSL can be an intimidating hurdle for many, but it's crucial to secure your application, especially when it's exposed to the internet. In this post, I'll guide you through adding Nginx and Certbot for Let's Encrypt SSL generation in a Dockerized setup. This allows you to automatically renew certificates and keep your environment secure with minimal hassle.&lt;/p&gt;

&lt;p&gt;Let's dive in!&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Docker and Docker Compose installed on your machine.&lt;/li&gt;
&lt;li&gt;Basic understanding of Docker Compose and Nginx.&lt;/li&gt;
&lt;li&gt;A domain name pointing to your server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this example, we are using Nginx as a reverse proxy and Certbot to manage SSL certificates. Below, you'll find the &lt;code&gt;docker-compose.yml&lt;/code&gt;, shell script for auto-reloading Nginx, and necessary configuration files to set up everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker Compose Configuration
&lt;/h3&gt;

&lt;p&gt;First, let me show you the Docker Compose configuration to set up Nginx and Certbot.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:latest&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.env&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;your-app-network&lt;/span&gt; &lt;span class="c1"&gt;# Update this with your application service network&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;80:80&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;443:443&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;your-app&lt;/span&gt; &lt;span class="c1"&gt;# Your application service&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx/secure/:/etc/nginx/templates/&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/etc/localtime:/etc/localtime:ro&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx/certbot/conf:/etc/letsencrypt&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx/certbot/www:/var/www/certbot&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx/99-autoreload.sh:/docker-entrypoint.d/99-autoreload.sh&lt;/span&gt;  &lt;span class="c1"&gt;# Script to autoreload Nginx when certs are renewed&lt;/span&gt;

  &lt;span class="na"&gt;certbot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;certbot/certbot&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx/certbot/conf:/etc/letsencrypt&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx/certbot/www:/var/www/certbot&lt;/span&gt;
    &lt;span class="na"&gt;entrypoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/bin/sh&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-c&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'trap&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;exit&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;TERM;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;while&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;:;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;do&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;certbot&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;renew;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sleep&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;12h&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;wait&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$${!};&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;done;'"&lt;/span&gt;  &lt;span class="c1"&gt;# Renew certificates every 12 hours&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This Docker Compose file defines two services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nginx&lt;/strong&gt;: Acts as a reverse proxy and serves requests to your backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Certbot&lt;/strong&gt;: Takes care of generating and renewing SSL certificates using Let's Encrypt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;certbot&lt;/code&gt; service runs in an infinite loop, renewing certificates every 12 hours. Certificates are stored in a shared volume (&lt;code&gt;./nginx/certbot/conf&lt;/code&gt;), allowing Nginx to access the latest certificate files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nginx Configuration
&lt;/h3&gt;

&lt;p&gt;Nginx serves as the reverse proxy, handling both HTTP and HTTPS traffic. For the initial request, Certbot needs HTTP (port 80) to complete the domain verification process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# default.conf.template&lt;/span&gt;

&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; $&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;APP_DOMAIN&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://&lt;/span&gt;&lt;span class="nv"&gt;$host$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/.well-known/acme-challenge/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/certbot&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="kn"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; $&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;APP_DOMAIN&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_tokens&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;client_max_body_size&lt;/span&gt; &lt;span class="mi"&gt;20M&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/&lt;/span&gt;$&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;APP_DOMAIN&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="n"&gt;/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/&lt;/span&gt;$&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;APP_DOMAIN&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="n"&gt;/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/options-ssl-nginx.conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_dhparam&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/ssl-dhparams.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="s"&gt;https&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Url-Scheme&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$http_host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_redirect&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://my-app:3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;//&lt;/span&gt; &lt;span class="s"&gt;Your&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt; &lt;span class="s"&gt;service&lt;/span&gt; &lt;span class="s"&gt;name&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the configuration file above, Nginx does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Redirects HTTP requests to HTTPS to ensure secure communication.&lt;/li&gt;
&lt;li&gt;Handles SSL termination and proxies requests to your backend service (e.g., &lt;code&gt;my-app:3000&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Auto-Reloading Nginx Configuration
&lt;/h3&gt;

&lt;p&gt;After the SSL certificates are renewed, Nginx should be reloaded to apply the updated certificates. To automate this process, add a simple auto-reload script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 99-autoreload.sh&lt;/span&gt;

&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; :&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c"&gt;# Optional: Instead of sleep, detect config changes and only reload if necessary.&lt;/span&gt;
    &lt;span class="nb"&gt;sleep &lt;/span&gt;6h
    nginx &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; nginx &lt;span class="nt"&gt;-s&lt;/span&gt; reload
&lt;span class="k"&gt;done&lt;/span&gt; &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script runs inside the Nginx container and reloads Nginx every 6 hours, or whenever the certificate is renewed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Environment Variables
&lt;/h3&gt;

&lt;p&gt;Create an &lt;code&gt;.env&lt;/code&gt; file to store your domain name and email address for Certbot registration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# .env file

APP_DOMAIN=your-domain.com
SSL_EMAIL=contact@your-domain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Initial SSL Certificate Generation
&lt;/h3&gt;

&lt;p&gt;Before Nginx can serve HTTPS traffic, you need to generate the initial SSL certificate. Use the following bash script (init-letsencrypt.sh) to generate the SSL certificate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# Source the .env file&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; .env &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s1"&gt;'^#'&lt;/span&gt; .env | xargs&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;fi

if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; docker compose&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Error: docker compose is not installed.'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nv"&gt;domains&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;APP_DOMAIN&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.com&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;rsa_key_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4096
&lt;span class="nv"&gt;data_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"./nginx/certbot"&lt;/span&gt;
&lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SSL_EMAIL&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;@example.com&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="c"&gt;# Adding a valid address is strongly recommended&lt;/span&gt;
&lt;span class="nv"&gt;staging&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="c"&gt;# Set to 1 if you're testing your setup to avoid hitting request limits&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$data_path&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"Existing data found for &lt;/span&gt;&lt;span class="nv"&gt;$domains&lt;/span&gt;&lt;span class="s2"&gt;. Continue and replace existing certificate? (y/N) "&lt;/span&gt; decision
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$decision&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"Y"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$decision&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"y"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;exit
    &lt;/span&gt;&lt;span class="k"&gt;fi
fi

if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$data_path&lt;/span&gt;&lt;span class="s2"&gt;/conf/options-ssl-nginx.conf"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$data_path&lt;/span&gt;&lt;span class="s2"&gt;/conf/ssl-dhparams.pem"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"### Downloading recommended TLS parameters ..."&lt;/span&gt;
    &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$data_path&lt;/span&gt;&lt;span class="s2"&gt;/conf"&lt;/span&gt;
    curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$data_path&lt;/span&gt;&lt;span class="s2"&gt;/conf/options-ssl-nginx.conf"&lt;/span&gt;
    curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$data_path&lt;/span&gt;&lt;span class="s2"&gt;/conf/ssl-dhparams.pem"&lt;/span&gt;
    &lt;span class="nb"&gt;echo
&lt;/span&gt;&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"### Creating dummy certificate for &lt;/span&gt;&lt;span class="nv"&gt;$domains&lt;/span&gt;&lt;span class="s2"&gt; ..."&lt;/span&gt;
&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/etc/letsencrypt/live/&lt;/span&gt;&lt;span class="nv"&gt;$domains&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$data_path&lt;/span&gt;&lt;span class="s2"&gt;/conf/live/&lt;/span&gt;&lt;span class="nv"&gt;$domains&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"docker-compose.yml"&lt;/span&gt; run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--entrypoint&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  openssl req -x509 -nodes -newkey rsa:&lt;/span&gt;&lt;span class="nv"&gt;$rsa_key_size&lt;/span&gt;&lt;span class="s2"&gt; -days 1&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    -keyout '&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="s2"&gt;/privkey.pem' &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    -out '&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="s2"&gt;/fullchain.pem' &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    -subj '/CN=localhost'"&lt;/span&gt; certbot
&lt;span class="nb"&gt;echo

echo&lt;/span&gt; &lt;span class="s2"&gt;"### Starting nginx ..."&lt;/span&gt;
docker compose  &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"docker-compose.yml"&lt;/span&gt; up &lt;span class="nt"&gt;--force-recreate&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; nginx
&lt;span class="nb"&gt;echo

echo&lt;/span&gt; &lt;span class="s2"&gt;"### Deleting dummy certificate for &lt;/span&gt;&lt;span class="nv"&gt;$domains&lt;/span&gt;&lt;span class="s2"&gt; ..."&lt;/span&gt;
docker compose  &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"docker-compose.yml"&lt;/span&gt; run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--entrypoint&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  rm -Rf /etc/letsencrypt/live/&lt;/span&gt;&lt;span class="nv"&gt;$domains&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  rm -Rf /etc/letsencrypt/archive/&lt;/span&gt;&lt;span class="nv"&gt;$domains&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  rm -Rf /etc/letsencrypt/renewal/&lt;/span&gt;&lt;span class="nv"&gt;$domains&lt;/span&gt;&lt;span class="s2"&gt;.conf"&lt;/span&gt; certbot
&lt;span class="nb"&gt;echo

echo&lt;/span&gt; &lt;span class="s2"&gt;"### Requesting Let's Encrypt certificate for &lt;/span&gt;&lt;span class="nv"&gt;$domains&lt;/span&gt;&lt;span class="s2"&gt; ..."&lt;/span&gt;
&lt;span class="c"&gt;#Join $domains to -d args&lt;/span&gt;
&lt;span class="nv"&gt;domain_args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;domain &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;domains&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nv"&gt;domain_args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$domain_args&lt;/span&gt;&lt;span class="s2"&gt; -d &lt;/span&gt;&lt;span class="nv"&gt;$domain&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="c"&gt;# Select appropriate email arg&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;email_arg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"--register-unsafely-without-email"&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;email_arg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"--email &lt;/span&gt;&lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="k"&gt;esac&lt;/span&gt;

&lt;span class="c"&gt;# Enable staging mode if needed&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$staging&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"0"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then &lt;/span&gt;&lt;span class="nv"&gt;staging_arg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"--staging"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;fi

&lt;/span&gt;docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"docker-compose.yml"&lt;/span&gt; run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--entrypoint&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  certbot certonly --webroot -w /var/www/certbot &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$staging_arg&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$email_arg&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$domain_args&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    --rsa-key-size &lt;/span&gt;&lt;span class="nv"&gt;$rsa_key_size&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    --agree-tos &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    --force-renewal"&lt;/span&gt; certbot
&lt;span class="nb"&gt;echo&lt;/span&gt;

&lt;span class="c"&gt;#echo "### Reloading nginx ..."&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"docker-compose.yml"&lt;/span&gt; &lt;span class="nb"&gt;exec &lt;/span&gt;nginx nginx &lt;span class="nt"&gt;-s&lt;/span&gt; reload

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;In summary, the configuration provided above sets up Nginx as a reverse proxy for your Dockerized application, with Let's Encrypt SSL certificates automatically managed by Certbot. This setup ensures a secure connection to your application without the headache of manual SSL renewals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Notes
&lt;/h3&gt;

&lt;p&gt;To bring up your environment the first time, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;a+x init-letsencrypt.sh
./init-letsencrypt.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following times you can bring up your environment with the usual docker compose command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure your domain points to your server and that ports 80 and 443 are open to allow access to HTTP and HTTPS traffic.&lt;/p&gt;

&lt;p&gt;If you run into any issues or have suggestions for improvements, let me know in the comments below! I'm happy to help troubleshoot or expand on specific topics.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
