<?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: RayMiles</title>
    <description>The latest articles on DEV Community by RayMiles (@raymiles94).</description>
    <link>https://dev.to/raymiles94</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F680225%2F9c24fb0d-99c9-4b6c-987b-8bf4d837b941.jpeg</url>
      <title>DEV Community: RayMiles</title>
      <link>https://dev.to/raymiles94</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/raymiles94"/>
    <language>en</language>
    <item>
      <title>Mastering QWeb PDF Reports in Odoo 19: From Beginner to Advanced</title>
      <dc:creator>RayMiles</dc:creator>
      <pubDate>Sun, 02 Aug 2026 15:51:30 +0000</pubDate>
      <link>https://dev.to/raymiles94/mastering-qweb-pdf-reports-in-odoo-19-from-beginner-to-advanced-585l</link>
      <guid>https://dev.to/raymiles94/mastering-qweb-pdf-reports-in-odoo-19-from-beginner-to-advanced-585l</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Learn how to build professional PDF reports in &lt;strong&gt;Odoo 19&lt;/strong&gt; using &lt;strong&gt;QWeb&lt;/strong&gt;. This guide covers everything from creating your first report to advanced techniques like reusable templates, custom paper formats, barcodes, multilingual reports, RTL support, and performance optimization.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Every Odoo application relies on reports.&lt;/p&gt;

&lt;p&gt;Whether you're printing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sales Quotations&lt;/li&gt;
&lt;li&gt;Customer Invoices&lt;/li&gt;
&lt;li&gt;Purchase Orders&lt;/li&gt;
&lt;li&gt;Delivery Slips&lt;/li&gt;
&lt;li&gt;Manufacturing Orders&lt;/li&gt;
&lt;li&gt;Inventory Labels&lt;/li&gt;
&lt;li&gt;Payroll Documents&lt;/li&gt;
&lt;li&gt;Custom Certificates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;you're using &lt;strong&gt;QWeb&lt;/strong&gt;, Odoo's XML-based templating engine.&lt;/p&gt;

&lt;p&gt;Although creating a basic report is straightforward, building &lt;strong&gt;maintainable, scalable, and professional&lt;/strong&gt; reports requires understanding how the entire reporting pipeline works.&lt;/p&gt;

&lt;p&gt;In this tutorial, we'll build a complete report from scratch while exploring best practices used by experienced Odoo developers.&lt;/p&gt;

&lt;p&gt;By the end of this guide, you'll be able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create custom PDF reports&lt;/li&gt;
&lt;li&gt;Understand how Odoo generates PDFs&lt;/li&gt;
&lt;li&gt;Design reusable templates&lt;/li&gt;
&lt;li&gt;Display relational data&lt;/li&gt;
&lt;li&gt;Build dynamic tables&lt;/li&gt;
&lt;li&gt;Format currencies and dates correctly&lt;/li&gt;
&lt;li&gt;Add company logos, images, barcodes, and QR codes&lt;/li&gt;
&lt;li&gt;Create custom paper formats&lt;/li&gt;
&lt;li&gt;Pass additional data from Python&lt;/li&gt;
&lt;li&gt;Optimize report performance&lt;/li&gt;
&lt;li&gt;Debug common QWeb issues&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  How Odoo Generates a PDF
&lt;/h1&gt;

&lt;p&gt;Before writing any XML, it's important to understand the report generation process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User clicks "Print"
        │
        ▼
ir.actions.report
        │
        ▼
Report Model (_get_report_values)
        │
        ▼
QWeb Template
        │
        ▼
Rendered HTML
        │
        ▼
wkhtmltopdf
        │
        ▼
PDF Download
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each step has a specific responsibility:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ir.actions.report&lt;/td&gt;
&lt;td&gt;Registers the report&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Report Model&lt;/td&gt;
&lt;td&gt;Prepares business data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QWeb&lt;/td&gt;
&lt;td&gt;Generates HTML&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wkhtmltopdf&lt;/td&gt;
&lt;td&gt;Converts HTML into PDF&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Understanding this workflow makes debugging significantly easier.&lt;/p&gt;




&lt;h1&gt;
  
  
  Project Structure
&lt;/h1&gt;

&lt;p&gt;A clean module structure helps keep reports maintainable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my_module/
│
├── models/
│   └── sale_order.py
│
├── report/
│   ├── sale_order_report.xml
│   ├── report_action.xml
│   └── paperformat.xml
│
├── security/
│
├── views/
│
└── __manifest__.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keeping reports inside a dedicated &lt;code&gt;report&lt;/code&gt; directory is considered best practice.&lt;/p&gt;




&lt;h1&gt;
  
  
  Step 1 — Create the Report Action
&lt;/h1&gt;

&lt;p&gt;Every report starts with an &lt;code&gt;ir.actions.report&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This record tells Odoo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which model the report belongs to&lt;/li&gt;
&lt;li&gt;which template should be rendered&lt;/li&gt;
&lt;li&gt;whether it should generate HTML or PDF&lt;/li&gt;
&lt;li&gt;where the report appears in the UI
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;record&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"action_sale_order_custom"&lt;/span&gt; &lt;span class="na"&gt;model=&lt;/span&gt;&lt;span class="s"&gt;"ir.actions.report"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Sale Order PDF&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"model"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;sale.order&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"report_type"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;qweb-pdf&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"report_name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        my_module.sale_order_report
    &lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"report_file"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        my_module.sale_order_report
    &lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"binding_model_id"&lt;/span&gt;
           &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"sale.model_sale_order"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"binding_type"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        report
    &lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/record&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installing the module, your report automatically appears inside the &lt;strong&gt;Print&lt;/strong&gt; menu.&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Pro Tip:&lt;/strong&gt; Always use descriptive report IDs. It makes debugging much easier.&lt;/p&gt;




&lt;h1&gt;
  
  
  Step 2 — Create the QWeb Template
&lt;/h1&gt;

&lt;p&gt;The template defines the visual appearance of your report.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"sale_order_report"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;t&lt;/span&gt; &lt;span class="na"&gt;t-call=&lt;/span&gt;&lt;span class="s"&gt;"web.html_container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;t&lt;/span&gt; &lt;span class="na"&gt;t-foreach=&lt;/span&gt;&lt;span class="s"&gt;"docs"&lt;/span&gt; &lt;span class="na"&gt;t-as=&lt;/span&gt;&lt;span class="s"&gt;"o"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;t&lt;/span&gt; &lt;span class="na"&gt;t-call=&lt;/span&gt;&lt;span class="s"&gt;"web.external_layout"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"page"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Sale Order&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;Customer:&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;t-field=&lt;/span&gt;&lt;span class="s"&gt;"o.partner_id"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;Date:&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;t-field=&lt;/span&gt;&lt;span class="s"&gt;"o.date_order"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/t&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/t&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/t&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although this template is small, it demonstrates the three most important building blocks of every QWeb report.&lt;/p&gt;




&lt;h1&gt;
  
  
  Understanding Every XML Tag
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;web.html_container&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Creates the HTML document wrapper required before converting HTML into PDF.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;t&lt;/span&gt; &lt;span class="na"&gt;t-call=&lt;/span&gt;&lt;span class="s"&gt;"web.html_container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;code&gt;web.external_layout&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Adds the standard company layout automatically.&lt;/p&gt;

&lt;p&gt;It includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Company Logo&lt;/li&gt;
&lt;li&gt;Company Address&lt;/li&gt;
&lt;li&gt;Header&lt;/li&gt;
&lt;li&gt;Footer&lt;/li&gt;
&lt;li&gt;Page Numbers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without this layout your report will not look like a standard Odoo document.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;div.page&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Every printable page should be wrapped inside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"page"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells wkhtmltopdf where pages begin.&lt;/p&gt;




&lt;h1&gt;
  
  
  Accessing Data
&lt;/h1&gt;

&lt;p&gt;When multiple records are printed, Odoo sends them to the template inside the variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;docs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This loop iterates over every selected record.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;t&lt;/span&gt; &lt;span class="na"&gt;t-foreach=&lt;/span&gt;&lt;span class="s"&gt;"docs"&lt;/span&gt; &lt;span class="na"&gt;t-as=&lt;/span&gt;&lt;span class="s"&gt;"o"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of it like Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Displaying Fields
&lt;/h1&gt;

&lt;p&gt;The preferred way to display model fields is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;t-field=&lt;/span&gt;&lt;span class="s"&gt;"o.partner_id"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;t-field&lt;/code&gt; automatically applies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Translations&lt;/li&gt;
&lt;li&gt;Currency formatting&lt;/li&gt;
&lt;li&gt;Date formatting&lt;/li&gt;
&lt;li&gt;Timezone conversion&lt;/li&gt;
&lt;li&gt;Decimal precision&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whenever you're displaying an Odoo field, prefer &lt;code&gt;t-field&lt;/code&gt; over &lt;code&gt;t-out&lt;/code&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;code&gt;t-field&lt;/code&gt; vs &lt;code&gt;t-out&lt;/code&gt;
&lt;/h1&gt;

&lt;h2&gt;
  
  
  t-field
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;t-field=&lt;/span&gt;&lt;span class="s"&gt;"o.amount_total"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Automatically formats values.&lt;/p&gt;




&lt;h2&gt;
  
  
  t-out
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;t&lt;/span&gt; &lt;span class="na"&gt;t-out=&lt;/span&gt;&lt;span class="s"&gt;"o.amount_total"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outputs the raw evaluated expression.&lt;/p&gt;

&lt;p&gt;Use it when displaying Python expressions instead of model fields.&lt;/p&gt;




&lt;h1&gt;
  
  
  Creating Tables
&lt;/h1&gt;

&lt;p&gt;Most reports display one2many records.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"table"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Product&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Qty&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Unit Price&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Total&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;t-foreach=&lt;/span&gt;&lt;span class="s"&gt;"o.order_line"&lt;/span&gt; &lt;span class="na"&gt;t-as=&lt;/span&gt;&lt;span class="s"&gt;"line"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;t-field=&lt;/span&gt;&lt;span class="s"&gt;"line.product_id"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;t-field=&lt;/span&gt;&lt;span class="s"&gt;"line.product_uom_qty"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;t-field=&lt;/span&gt;&lt;span class="s"&gt;"line.price_unit"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;t-field=&lt;/span&gt;&lt;span class="s"&gt;"line.price_total"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works exactly like iterating over a Python list.&lt;/p&gt;




&lt;h1&gt;
  
  
  Conditional Rendering
&lt;/h1&gt;

&lt;p&gt;Display content only when necessary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;t&lt;/span&gt; &lt;span class="na"&gt;t-if=&lt;/span&gt;&lt;span class="s"&gt;"o.state == 'sale'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"alert alert-success"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

Confirmed Order

&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/t&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Else:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;t&lt;/span&gt; &lt;span class="na"&gt;t-if=&lt;/span&gt;&lt;span class="s"&gt;"o.amount_total &amp;gt; 1000"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

VIP Customer

&lt;span class="nt"&gt;&amp;lt;/t&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;t&lt;/span&gt; &lt;span class="na"&gt;t-else=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

Regular Customer

&lt;span class="nt"&gt;&amp;lt;/t&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Images
&lt;/h1&gt;

&lt;p&gt;Company Logo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
&lt;span class="na"&gt;t-if=&lt;/span&gt;&lt;span class="s"&gt;"o.company_id.logo"&lt;/span&gt;
&lt;span class="na"&gt;t-att-src=&lt;/span&gt;&lt;span class="s"&gt;"image_data_uri(o.company_id.logo)"&lt;/span&gt;
&lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"height:80px;"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Product Image&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
&lt;span class="na"&gt;t-if=&lt;/span&gt;&lt;span class="s"&gt;"line.product_id.image_128"&lt;/span&gt;
&lt;span class="na"&gt;t-att-src=&lt;/span&gt;&lt;span class="s"&gt;"image_data_uri(line.product_id.image_128)"&lt;/span&gt;
&lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width:60px;"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Barcodes
&lt;/h1&gt;

&lt;p&gt;Odoo can generate barcodes without additional libraries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
&lt;span class="na"&gt;t-att-src=&lt;/span&gt;&lt;span class="s"&gt;"'/report/barcode/Code128/%s' % o.name"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inventory&lt;/li&gt;
&lt;li&gt;Manufacturing&lt;/li&gt;
&lt;li&gt;Shipping&lt;/li&gt;
&lt;li&gt;Warehouses&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  QR Codes
&lt;/h1&gt;

&lt;p&gt;Generating QR codes follows the same principle.&lt;/p&gt;

&lt;p&gt;Perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Payment Links&lt;/li&gt;
&lt;li&gt;Product URLs&lt;/li&gt;
&lt;li&gt;Customer Verification&lt;/li&gt;
&lt;li&gt;Digital Certificates&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Custom Paper Formats
&lt;/h1&gt;

&lt;p&gt;Need receipts?&lt;/p&gt;

&lt;p&gt;Shipping labels?&lt;/p&gt;

&lt;p&gt;A5?&lt;/p&gt;

&lt;p&gt;Letter?&lt;/p&gt;

&lt;p&gt;Create a custom paper format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;record&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"paperformat_custom"&lt;/span&gt;
        &lt;span class="na"&gt;model=&lt;/span&gt;&lt;span class="s"&gt;"report.paperformat"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;A5 Landscape&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"format"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;A5&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"orientation"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Landscape&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/record&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then assign it to your report action.&lt;/p&gt;




&lt;h1&gt;
  
  
  Passing Extra Data from Python
&lt;/h1&gt;

&lt;p&gt;Complex calculations belong in Python—not XML.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SaleOrderReport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AbstractModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;report.my_module.sale_order_report&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_get_report_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;docids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

        &lt;span class="n"&gt;docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sale.order&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;browse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;docids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;docs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grand_total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mapped&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;amount_total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside QWeb:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;t&lt;/span&gt; &lt;span class="na"&gt;t-out=&lt;/span&gt;&lt;span class="s"&gt;"grand_total"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 &lt;strong&gt;Best Practice:&lt;/strong&gt; Keep business logic inside Python. Use QWeb only for presentation.&lt;/p&gt;




&lt;h1&gt;
  
  
  Calling Reports from Python
&lt;/h1&gt;

&lt;p&gt;Generate reports programmatically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my_module.action_sale_order_custom&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;report_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Buttons&lt;/li&gt;
&lt;li&gt;Wizards&lt;/li&gt;
&lt;li&gt;Scheduled Actions&lt;/li&gt;
&lt;li&gt;Automated Workflows&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Reusable Templates
&lt;/h1&gt;

&lt;p&gt;Instead of duplicating headers or tables, extract them into reusable templates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;t&lt;/span&gt; &lt;span class="na"&gt;t-call=&lt;/span&gt;&lt;span class="s"&gt;"my_module.report_header"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This dramatically reduces maintenance.&lt;/p&gt;




&lt;h1&gt;
  
  
  Multilingual Reports
&lt;/h1&gt;

&lt;p&gt;Odoo automatically translates field labels according to the customer's language.&lt;/p&gt;

&lt;p&gt;Always use translated strings whenever possible.&lt;/p&gt;




&lt;h1&gt;
  
  
  RTL Support
&lt;/h1&gt;

&lt;p&gt;Need Arabic reports?&lt;/p&gt;

&lt;p&gt;Add RTL CSS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="nl"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;rtl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use fonts that support Arabic glyphs for consistent rendering.&lt;/p&gt;




&lt;h1&gt;
  
  
  Performance Tips
&lt;/h1&gt;

&lt;p&gt;Large reports can become slow.&lt;/p&gt;

&lt;p&gt;Follow these recommendations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Move calculations into Python.&lt;/li&gt;
&lt;li&gt;Avoid nested loops.&lt;/li&gt;
&lt;li&gt;Minimize database queries.&lt;/li&gt;
&lt;li&gt;Reuse templates.&lt;/li&gt;
&lt;li&gt;Cache expensive computations.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;mapped()&lt;/code&gt; instead of repeated traversals.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Common Mistakes
&lt;/h1&gt;

&lt;p&gt;❌ Putting business logic inside XML.&lt;/p&gt;

&lt;p&gt;❌ Using &lt;code&gt;t-out&lt;/code&gt; instead of &lt;code&gt;t-field&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;❌ Forgetting &lt;code&gt;web.external_layout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;❌ Missing &lt;code&gt;&amp;lt;div class="page"&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;❌ Large nested loops.&lt;/p&gt;

&lt;p&gt;❌ Hardcoded text instead of translations.&lt;/p&gt;




&lt;h1&gt;
  
  
  Debugging Checklist
&lt;/h1&gt;

&lt;p&gt;If the PDF is blank:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check XML syntax.&lt;/li&gt;
&lt;li&gt;Verify the template ID.&lt;/li&gt;
&lt;li&gt;Confirm the report action.&lt;/li&gt;
&lt;li&gt;Test HTML rendering.&lt;/li&gt;
&lt;li&gt;Review server logs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If CSS is broken:&lt;/p&gt;

&lt;p&gt;Remember that &lt;strong&gt;wkhtmltopdf&lt;/strong&gt; doesn't support every modern CSS feature.&lt;/p&gt;

&lt;p&gt;Keep layouts simple.&lt;/p&gt;




&lt;h1&gt;
  
  
  Best Practices
&lt;/h1&gt;

&lt;p&gt;✅ Use descriptive template names.&lt;/p&gt;

&lt;p&gt;✅ Keep XML focused on presentation.&lt;/p&gt;

&lt;p&gt;✅ Put calculations in Python.&lt;/p&gt;

&lt;p&gt;✅ Reuse templates.&lt;/p&gt;

&lt;p&gt;✅ Test with realistic data.&lt;/p&gt;

&lt;p&gt;✅ Support multiple languages.&lt;/p&gt;

&lt;p&gt;✅ Follow Odoo coding standards.&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;QWeb is much more than an XML templating engine—it's the foundation of every printable business document in Odoo.&lt;/p&gt;

&lt;p&gt;By understanding the entire reporting pipeline, structuring templates correctly, separating business logic from presentation, and following best practices, you can build reports that are scalable, maintainable, and production-ready.&lt;/p&gt;

&lt;p&gt;Whether you're creating invoices, quotations, delivery slips, manufacturing work orders, inventory labels, or custom business documents, mastering QWeb is an essential skill for every Odoo developer.&lt;/p&gt;

&lt;p&gt;If you're just starting with Odoo reporting, begin with a simple template, experiment with dynamic fields and loops, then progressively explore advanced topics like reusable templates, multilingual reports, RTL support, custom paper formats, and report optimization.&lt;/p&gt;

&lt;p&gt;Happy coding! 🚀&lt;/p&gt;

</description>
      <category>odoo</category>
      <category>learning</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>16 Websites Like HackerNoon Every Developer Should Know</title>
      <dc:creator>RayMiles</dc:creator>
      <pubDate>Sun, 02 Aug 2026 15:47:55 +0000</pubDate>
      <link>https://dev.to/raymiles94/16-websites-like-hackernoon-every-developer-should-know-3pk2</link>
      <guid>https://dev.to/raymiles94/16-websites-like-hackernoon-every-developer-should-know-3pk2</guid>
      <description>&lt;p&gt;If you're a developer, software engineer, startup founder, or technical writer, chances are you've read articles on HackerNoon. It's one of the most popular platforms for sharing deep technical insights, programming tutorials, startup stories, AI research, and software engineering experiences.&lt;/p&gt;

&lt;p&gt;But HackerNoon isn't the only place where high-quality technical content lives.&lt;/p&gt;

&lt;p&gt;Whether you're looking to &lt;strong&gt;publish your own articles&lt;/strong&gt;, &lt;strong&gt;grow your personal brand&lt;/strong&gt;, or simply &lt;strong&gt;discover great engineering content&lt;/strong&gt;, here are the best HackerNoon alternatives.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Medium
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; General technology, AI, startups, and software engineering&lt;/p&gt;

&lt;p&gt;Medium is one of the largest publishing platforms on the internet. Thousands of developers write about programming, cloud computing, cybersecurity, AI, and entrepreneurship.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Massive audience&lt;/li&gt;
&lt;li&gt;Easy publishing&lt;/li&gt;
&lt;li&gt;Supports technical formatting&lt;/li&gt;
&lt;li&gt;Great SEO&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best if:&lt;/strong&gt; You want maximum exposure.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. DEV Community (dev.to)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Programming tutorials and developer experiences&lt;/p&gt;

&lt;p&gt;DEV Community is one of the friendliest places for developers to share knowledge. Articles range from beginner tutorials to advanced architecture discussions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Popular topics
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Rust&lt;/li&gt;
&lt;li&gt;Go&lt;/li&gt;
&lt;li&gt;DevOps&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Kubernetes&lt;/li&gt;
&lt;li&gt;AI&lt;/li&gt;
&lt;li&gt;Odoo&lt;/li&gt;
&lt;li&gt;Open Source&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best if:&lt;/strong&gt; You enjoy engaging with other developers.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Hashnode
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Building your own developer blog&lt;/p&gt;

&lt;p&gt;Hashnode lets you publish on your own custom domain while benefiting from an active developer community.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why developers love it
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Free custom domain support&lt;/li&gt;
&lt;li&gt;Great Markdown editor&lt;/li&gt;
&lt;li&gt;Fast SEO indexing&lt;/li&gt;
&lt;li&gt;Developer-focused audience&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. DZone
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Enterprise software development&lt;/p&gt;

&lt;p&gt;DZone focuses on professional software engineering topics such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;li&gt;Spring Boot&lt;/li&gt;
&lt;li&gt;Microservices&lt;/li&gt;
&lt;li&gt;Cloud Computing&lt;/li&gt;
&lt;li&gt;Databases&lt;/li&gt;
&lt;li&gt;DevOps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike HackerNoon, articles go through editorial review.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. InfoQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Senior engineers and software architects&lt;/p&gt;

&lt;p&gt;InfoQ publishes high-quality technical articles about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Software architecture&lt;/li&gt;
&lt;li&gt;Distributed systems&lt;/li&gt;
&lt;li&gt;Kubernetes&lt;/li&gt;
&lt;li&gt;AI&lt;/li&gt;
&lt;li&gt;Performance engineering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Content is editorially curated, making it one of the most respected engineering publications.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. The New Stack
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Cloud-native technologies&lt;/p&gt;

&lt;p&gt;Topics include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Linux&lt;/li&gt;
&lt;li&gt;Cloud Infrastructure&lt;/li&gt;
&lt;li&gt;Platform Engineering&lt;/li&gt;
&lt;li&gt;AI Infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you work with modern cloud technologies, this should be on your reading list.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. freeCodeCamp News
&lt;/h2&gt;

&lt;p&gt;One of the largest programming education platforms.&lt;/p&gt;

&lt;p&gt;You'll find:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complete programming guides&lt;/li&gt;
&lt;li&gt;Career advice&lt;/li&gt;
&lt;li&gt;Web development tutorials&lt;/li&gt;
&lt;li&gt;Machine learning&lt;/li&gt;
&lt;li&gt;Open-source projects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Perfect for beginners and experienced developers alike.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. CodeProject
&lt;/h2&gt;

&lt;p&gt;One of the oldest programming communities on the web.&lt;/p&gt;

&lt;p&gt;Great for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;C#&lt;/li&gt;
&lt;li&gt;C++&lt;/li&gt;
&lt;li&gt;.NET&lt;/li&gt;
&lt;li&gt;Desktop development&lt;/li&gt;
&lt;li&gt;Algorithms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're a Microsoft stack developer, you'll probably enjoy CodeProject.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Java Code Geeks
&lt;/h2&gt;

&lt;p&gt;As the name suggests, this site focuses on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;li&gt;Spring Boot&lt;/li&gt;
&lt;li&gt;JVM&lt;/li&gt;
&lt;li&gt;Kafka&lt;/li&gt;
&lt;li&gt;Maven&lt;/li&gt;
&lt;li&gt;Gradle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ideal for backend developers.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. KDnuggets
&lt;/h2&gt;

&lt;p&gt;A must-read if you're interested in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Artificial Intelligence&lt;/li&gt;
&lt;li&gt;Machine Learning&lt;/li&gt;
&lt;li&gt;Data Science&lt;/li&gt;
&lt;li&gt;LLMs&lt;/li&gt;
&lt;li&gt;Analytics&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  11. Towards AI
&lt;/h2&gt;

&lt;p&gt;One of the fastest-growing AI publications.&lt;/p&gt;

&lt;p&gt;Popular topics include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ChatGPT&lt;/li&gt;
&lt;li&gt;OpenAI&lt;/li&gt;
&lt;li&gt;RAG&lt;/li&gt;
&lt;li&gt;Agents&lt;/li&gt;
&lt;li&gt;Vector Databases&lt;/li&gt;
&lt;li&gt;LangChain&lt;/li&gt;
&lt;li&gt;LlamaIndex&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  12. Towards Data Science
&lt;/h2&gt;

&lt;p&gt;Hosted on Medium, this publication features in-depth articles on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Deep Learning&lt;/li&gt;
&lt;li&gt;Statistics&lt;/li&gt;
&lt;li&gt;Data Engineering&lt;/li&gt;
&lt;li&gt;LLMs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  13. CSS-Tricks
&lt;/h2&gt;

&lt;p&gt;A classic resource for frontend developers.&lt;/p&gt;

&lt;p&gt;Topics include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CSS&lt;/li&gt;
&lt;li&gt;HTML&lt;/li&gt;
&lt;li&gt;JavaScript&lt;/li&gt;
&lt;li&gt;Accessibility&lt;/li&gt;
&lt;li&gt;UI Design&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  14. Smashing Magazine
&lt;/h2&gt;

&lt;p&gt;One of the highest-quality web development magazines covering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UX&lt;/li&gt;
&lt;li&gt;Frontend&lt;/li&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Accessibility&lt;/li&gt;
&lt;li&gt;Design Systems&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  15. Daily.dev
&lt;/h2&gt;

&lt;p&gt;Unlike the others, Daily.dev aggregates the best developer articles from across the internet into one personalized feed.&lt;/p&gt;

&lt;p&gt;It's an excellent way to discover new writers and publications.&lt;/p&gt;




&lt;h2&gt;
  
  
  16. Substack
&lt;/h2&gt;

&lt;p&gt;If your goal is building a personal audience, Substack lets you publish articles and newsletters directly to subscribers.&lt;/p&gt;

&lt;p&gt;Many experienced engineers have moved to Substack to create independent technical publications.&lt;/p&gt;




&lt;h1&gt;
  
  
  Which Platform Should You Choose?
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Goal&lt;/th&gt;
&lt;th&gt;Best Choice&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Reach the largest audience&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Join an active developer community&lt;/td&gt;
&lt;td&gt;DEV Community&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Own your personal blog&lt;/td&gt;
&lt;td&gt;Hashnode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enterprise software engineering&lt;/td&gt;
&lt;td&gt;DZone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Software architecture&lt;/td&gt;
&lt;td&gt;InfoQ&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud &amp;amp; Kubernetes&lt;/td&gt;
&lt;td&gt;The New Stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI &amp;amp; Machine Learning&lt;/td&gt;
&lt;td&gt;Towards AI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Science&lt;/td&gt;
&lt;td&gt;Towards Data Science&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend development&lt;/td&gt;
&lt;td&gt;CSS-Tricks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long-term personal brand&lt;/td&gt;
&lt;td&gt;Substack&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;HackerNoon remains one of the best places to publish technical content, but it's far from the only option. Depending on your goals, you may benefit from publishing across multiple platforms.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write tutorials on DEV Community.&lt;/li&gt;
&lt;li&gt;Publish long-form technical articles on Medium.&lt;/li&gt;
&lt;li&gt;Build your personal brand with Hashnode or Substack.&lt;/li&gt;
&lt;li&gt;Submit enterprise-focused content to DZone or InfoQ.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best strategy is not to choose just one platform—it's to consistently create valuable content and share it where your target audience spends time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What other developer publishing platforms do you recommend? Share your favorites in the comments!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>hackernoon</category>
      <category>learning</category>
      <category>news</category>
      <category>science</category>
    </item>
    <item>
      <title>How to Create a Simple Widget in Odoo 19</title>
      <dc:creator>RayMiles</dc:creator>
      <pubDate>Wed, 15 Apr 2026 09:25:43 +0000</pubDate>
      <link>https://dev.to/raymiles94/how-to-create-a-simple-widget-in-odoo-19-507</link>
      <guid>https://dev.to/raymiles94/how-to-create-a-simple-widget-in-odoo-19-507</guid>
      <description>&lt;p&gt;Odoo 19 uses the OWL (Odoo Web Library) framework for building frontend components. Widgets are reusable UI elements that allow you to customize how fields are displayed and interacted with in the interface.&lt;/p&gt;

&lt;p&gt;This guide explains how to create a simple custom field widget.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Create a Custom Module
&lt;/h2&gt;

&lt;p&gt;Start by generating a new module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;odoo-bin scaffold my_widget_module addons/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The structure will look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my_widget_module/
├── __init__.py
├── __manifest__.py
├── static/
│   └── src/
│       ├── js/
│       ├── xml/
│       └── css/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Update the Manifest
&lt;/h2&gt;

&lt;p&gt;Edit &lt;code&gt;__manifest__.py&lt;/code&gt; and include your assets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;assets&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;web.assets_backend&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;my_widget_module/static/src/js/my_widget.js&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;my_widget_module/static/src/xml/my_widget.xml&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;my_widget_module/static/src/css/my_widget.css&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Create the Widget (OWL Component)
&lt;/h2&gt;

&lt;p&gt;Create the file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;static/src/js/my_widget.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** @odoo-module **/&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@odoo/owl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;registry&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@web/core/registry&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyWidget&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&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="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&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="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No value&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="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;MyWidget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my_widget_module.MyWidget&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;category&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fields&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my_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="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyWidget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;supportedTypes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;char&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Create the Template
&lt;/h2&gt;

&lt;p&gt;Create:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;static/src/xml/my_widget.xml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;templates&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;t&lt;/span&gt; &lt;span class="na"&gt;t-name=&lt;/span&gt;&lt;span class="s"&gt;"my_widget_module.MyWidget"&lt;/span&gt; &lt;span class="na"&gt;owl=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"o_my_widget"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;t-esc=&lt;/span&gt;&lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/t&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/templates&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Use the Widget in a View
&lt;/h2&gt;

&lt;p&gt;Apply the widget to a field in your XML view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;widget=&lt;/span&gt;&lt;span class="s"&gt;"my_widget"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;record&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"view_form_example"&lt;/span&gt; &lt;span class="na"&gt;model=&lt;/span&gt;&lt;span class="s"&gt;"ir.ui.view"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;example.form&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"model"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;res.partner&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"arch"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"xml"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;form&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;sheet&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;group&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;widget=&lt;/span&gt;&lt;span class="s"&gt;"my_widget"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/group&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/sheet&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/record&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Add Optional Styling
&lt;/h2&gt;

&lt;p&gt;Create:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;static/src/css/my_widget.css&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.o_my_widget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. Restart and Upgrade
&lt;/h2&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./odoo-bin &lt;span class="nt"&gt;-u&lt;/span&gt; my_widget_module &lt;span class="nt"&gt;-d&lt;/span&gt; your_db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then refresh your browser using a hard reload.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Concepts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Widgets in Odoo 19 are OWL components.&lt;/li&gt;
&lt;li&gt;Field values are accessed using:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="k"&gt;this&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="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&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="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The widget must be registered in the fields registry.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;supportedTypes&lt;/code&gt; defines which field types the widget can handle.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Creating a widget in Odoo 19 involves defining an OWL component, linking it to a template, registering it, and using it in a view. With this structure, you can extend the widget to include interactivity, backend communication, or more advanced UI behavior.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>ui</category>
    </item>
    <item>
      <title>Setting Up Nerd Fonts in Alacritty on Ubuntu</title>
      <dc:creator>RayMiles</dc:creator>
      <pubDate>Wed, 04 Mar 2026 14:29:00 +0000</pubDate>
      <link>https://dev.to/raymiles94/setting-up-nerd-fonts-in-alacritty-on-ubuntu-13j6</link>
      <guid>https://dev.to/raymiles94/setting-up-nerd-fonts-in-alacritty-on-ubuntu-13j6</guid>
      <description>&lt;h2&gt;
  
  
  1. Download &amp;amp; Install the Nerd Font
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create fonts directory&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.local/share/fonts

&lt;span class="c"&gt;# Download JetBrainsMono Nerd Font (or any you prefer)&lt;/span&gt;
wget https://github.com/ryanoasis/nerd-fonts/releases/latest/download/JetBrainsMono.zip

&lt;span class="c"&gt;# Unzip&lt;/span&gt;
unzip JetBrainsMono.zip &lt;span class="nt"&gt;-d&lt;/span&gt; ~/.local/share/fonts/JetBrainsMono

&lt;span class="c"&gt;# Refresh font cache&lt;/span&gt;
fc-cache &lt;span class="nt"&gt;-fv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Verify the Exact Font Name
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fc-list | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"JetBrains"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see output like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.local/share/fonts/JetBrainsMono/JetBrainsMonoNerdFont-Regular.ttf: JetBrainsMono Nerd Font:style=Regular
~/.local/share/fonts/JetBrainsMono/JetBrainsMonoNerdFontMono-Regular.ttf: JetBrainsMono Nerd Font Mono:style=Regular
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Use → &lt;code&gt;JetBrainsMono Nerd Font&lt;/code&gt;&lt;br&gt;
❌ Avoid → &lt;code&gt;JetBrainsMono Nerd Font Mono&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Configure Alacritty
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create config directory if it doesn't exist&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.config/alacritty

&lt;span class="c"&gt;# Open config file&lt;/span&gt;
nano ~/.config/alacritty/alacritty.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Add this to the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[font]&lt;/span&gt;
&lt;span class="py"&gt;size&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;13.0&lt;/span&gt;

&lt;span class="nn"&gt;[font.normal]&lt;/span&gt;
&lt;span class="py"&gt;family&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"JetBrainsMono Nerd Font"&lt;/span&gt;
&lt;span class="py"&gt;style&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Regular"&lt;/span&gt;

&lt;span class="nn"&gt;[font.bold]&lt;/span&gt;
&lt;span class="py"&gt;family&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"JetBrainsMono Nerd Font"&lt;/span&gt;
&lt;span class="py"&gt;style&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Bold"&lt;/span&gt;

&lt;span class="nn"&gt;[font.italic]&lt;/span&gt;
&lt;span class="py"&gt;family&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"JetBrainsMono Nerd Font"&lt;/span&gt;
&lt;span class="py"&gt;style&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Italic"&lt;/span&gt;

&lt;span class="nn"&gt;[font.bold_italic]&lt;/span&gt;
&lt;span class="py"&gt;family&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"JetBrainsMono Nerd Font"&lt;/span&gt;
&lt;span class="py"&gt;style&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Bold Italic"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save with &lt;code&gt;Ctrl+O&lt;/code&gt; → &lt;code&gt;Enter&lt;/code&gt; → &lt;code&gt;Ctrl+X&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Install Alacritty (if not yet installed)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ubuntu 22.04+&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;alacritty

&lt;span class="c"&gt;# Or via snap&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;snap &lt;span class="nb"&gt;install &lt;/span&gt;alacritty &lt;span class="nt"&gt;--classic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Restart Alacritty
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Simply close and reopen, or:&lt;/span&gt;
alacritty &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! Your icons in tools like &lt;strong&gt;Starship&lt;/strong&gt;, &lt;strong&gt;lsd&lt;/strong&gt;, &lt;strong&gt;eza&lt;/strong&gt;, or &lt;strong&gt;Neovim&lt;/strong&gt; should now render at full size. 🎉&lt;/p&gt;

</description>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>RayMiles</dc:creator>
      <pubDate>Sat, 14 Feb 2026 20:39:54 +0000</pubDate>
      <link>https://dev.to/raymiles94/-11ip</link>
      <guid>https://dev.to/raymiles94/-11ip</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/tapava/computekit-a-react-toolkit-for-heavy-computations-without-freezing-the-ui-559a" class="crayons-story__hidden-navigation-link"&gt;Computekit — Reusable heavy computations for JS &amp;amp; React&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/tapava" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3562091%2F5fe46084-1c9b-4a3f-9f0d-8d3052eb79d1.png" alt="tapava profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/tapava" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Ghassen Ben Hadj Lassoued
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Ghassen Ben Hadj Lassoued
                
              
              &lt;div id="story-author-preview-content-3131480" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/tapava" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3562091%2F5fe46084-1c9b-4a3f-9f0d-8d3052eb79d1.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Ghassen Ben Hadj Lassoued&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/tapava/computekit-a-react-toolkit-for-heavy-computations-without-freezing-the-ui-559a" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Dec 28 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/tapava/computekit-a-react-toolkit-for-heavy-computations-without-freezing-the-ui-559a" id="article-link-3131480"&gt;
          Computekit — Reusable heavy computations for JS &amp;amp; React
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/react"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;react&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webassembly"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webassembly&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/performance"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;performance&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/typescript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;typescript&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/tapava/computekit-a-react-toolkit-for-heavy-computations-without-freezing-the-ui-559a" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;3&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/tapava/computekit-a-react-toolkit-for-heavy-computations-without-freezing-the-ui-559a#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            1 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>react</category>
      <category>webassembly</category>
      <category>performance</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
