<?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>Forem: Talha BEKLER</title>
    <description>The latest articles on Forem by Talha BEKLER (@madduck54).</description>
    <link>https://forem.com/madduck54</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%2F3949362%2Fbe9c9e46-6cfe-419b-a7c3-bceae987c0b6.jpeg</url>
      <title>Forem: Talha BEKLER</title>
      <link>https://forem.com/madduck54</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/madduck54"/>
    <language>en</language>
    <item>
      <title>Beyond Excel</title>
      <dc:creator>Talha BEKLER</dc:creator>
      <pubDate>Sun, 24 May 2026 17:56:46 +0000</pubDate>
      <link>https://forem.com/madduck54/beyond-excel-1e6e</link>
      <guid>https://forem.com/madduck54/beyond-excel-1e6e</guid>
      <description>&lt;p&gt;&lt;code&gt;Last December I inherited a half-built ERP. The sales side was written in ASP.NET + C# + MS SQL; the production side was on the plan but not in code. I moved it onto a modern Laravel stack and wove the production chain from scratch. I've been at it for four and a half months and it still isn't done. What the field taught me, here.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I write internal tools for production and operations companies. The project that gets most of my time is the ERP/MES platform of the industrial business I work inside. This post isn’t about a system I built from scratch; it’s a note on a system that landed in my hands half-built, that I migrated, wove on top of, and am still weaving. Four and a half months had built up.&lt;/p&gt;

&lt;p&gt;The old life: Excel + WhatsApp + paper&lt;br&gt;
Before the system arrived, three tools ran in parallel at the factory. The sales team kept orders and reports in Excel files. Paper forms were used for order notifications, production reports, and shipping slips. The production team filled out the production reports, the shipping team filled out the shipping slips. Communication between units flowed over WhatsApp, in groups.&lt;/p&gt;

&lt;p&gt;From the outside this setup looks “handmade,” but inside there were two large cracks.&lt;/p&gt;

&lt;p&gt;The first was the necessity of writing the same information into two separate places. When sales opened an order, its details had to be copied verbatim over to the shipping side; inside production, the same data scattered across different records. Two people opening the same file at the same time and one overwriting the other was a typical case.&lt;/p&gt;

&lt;p&gt;The second was harsher. A board came out of production, went to sizing, then to puttying, sanding, and finally to the film press. A five-link chain. When you asked “which machine is this part on right now?” — in the old system, no one knew. The production manager? The sizing operator? The press operator? No one, because there was no systematic record anyone was responsible for. Either you remembered, or you got up and went to look yourself.&lt;/p&gt;

&lt;p&gt;On top of a data map this scattered, there was no way of picking up the customer’s call and answering “okay, yours is on sanding right now.”&lt;/p&gt;

&lt;p&gt;The system I inherited: a half-scoped spec&lt;br&gt;
In December 2025 I received a package. Inside was an ERP written in ASP.NET Core 9 + C# + MS SQL Server 2016, a seventy-four-page feature spec document, and screen designs. The system’s scope was cleanly defined: customer management, products (parametric pricing + manual products), quote lifecycle, work orders, multi-currency (daily rates from the TCMB API), multi-company (host-tenant data separation), roles and permissions, dashboard, platform settings.&lt;/p&gt;

&lt;p&gt;So the sales side was complete. The part from taking a quote from a customer, pricing the product against its parameters, versioning the quote, and turning it into a work order once approved — all that was written.&lt;/p&gt;

&lt;p&gt;The spec’s own sentence was clear:&lt;/p&gt;

&lt;p&gt;“this proposal system is intended as the very first part of a much larger ERP system that is being planned. It can be taught as the first module of a complete ERP system, which can be used to manage the entire plywood factory’s production and other operations.”&lt;/p&gt;

&lt;p&gt;In other words: on the plan, not in code. Up until the work order is issued, things were systematic. After that — production, sizing, shipping, stock, lot tracking, labeling — on the field, it was still Excel + WhatsApp + paper.&lt;/p&gt;

&lt;p&gt;The decision took shape here.&lt;/p&gt;

&lt;p&gt;The migration decision: why Laravel + PHP + MySQL&lt;br&gt;
Continuing on the existing C# stack and just adding the new modules was an option too. But three cost items vanished at once, so the decision was easy:&lt;/p&gt;

&lt;p&gt;No licenses. MS SQL Server and Windows Server licenses were a permanent line in the budget. PHP, MySQL, Linux are free.&lt;br&gt;
The server was already set up. I had my own Linux server; Caddy for the reverse proxy, Tailscale for the private network, Docker for the services. There was no need to stand up an extra Windows server.&lt;br&gt;
The person on the development line was me. If a software team had been hired, every feature request would have meant a man-hour cost. If I did it, that line dropped out of the budget too, because the person on that line was me.&lt;br&gt;
With three cost items gone at once, choosing to move from ASP.NET Core 9 to Laravel 12 + PHP 8.3 + MySQL made sense. The frontend was already HTML 5 + CSS 3 + JavaScript; that stack didn’t change. I rewrote the equivalent with the Blade template engine + Alpine.js + TailwindCSS.&lt;/p&gt;

&lt;p&gt;The first few months were almost entirely port work: reading the C# code line by line and writing the PHP/Laravel code that did the same job. Customers, products, parametric pricing, quote lifecycle, work orders, multi-tenant data separation, multi-currency, snapshot versioning — all of it was in the spec, and I ported all of it one by one.&lt;/p&gt;

&lt;p&gt;What I wove on top&lt;br&gt;
The interesting part really began after the port: adding the production chain that wasn’t in the spec.&lt;/p&gt;

&lt;p&gt;The first module was production planning. I started there on purpose, because it was the head of the chain; all the next steps (sizing, puttying, sanding, film press) would feed off production. Then I wove the field chain link by link:&lt;/p&gt;

&lt;p&gt;Sizing: machine assignments, work-day planning, in/out tracking&lt;br&gt;
Puttying: work pool, completion record, waste/scrap tracking&lt;br&gt;
Sanding: status pool, volume calculation (m³)&lt;br&gt;
Film press: press definition, slot configuration, film-sheet planning, daily log&lt;br&gt;
Around all of that came the lot tracking system. Each piece’s unique number, which stage it’s at, who’s responsible, when it passed through. To that I added labeling + QR + TSPL printer integration; now a board gets labeled as it comes out of production and stays scannable all the way through the field. Then stock, shipping, export documents (ATR, EUR.1, invoice, waybill), tenant-specific order statuses, pessimistic locking on production updates: so two people writing to the same row don’t fall into a race condition.&lt;/p&gt;

&lt;p&gt;My method wasn’t sprint discipline. I write scenarios day by day: “in this scene the operator does this, the system records that, this calculation runs.” Then I go down to the field, get the teams to use it, collect their feedback, fix the bugs, and ship it again. So there’s no closing modules in sequence and leaving them behind; I keep coming back on top of most of them.&lt;/p&gt;

&lt;p&gt;The two lessons the field taught me&lt;br&gt;
There are two lessons, without which the platform — even a “million-dollar” one — goes in the bin.&lt;/p&gt;

&lt;p&gt;”If the first input is wrong, the chain is rotten”&lt;br&gt;
However elegant the system is, if the raw data is entered wrong, the report at the end of the chain is wrong too. The most obvious version of this showed up here: a lot recorded as 100 units at the production exit gets verified as 95 units when it arrives at sizing. The 5 in between are ghosts; they wander inside the system, they’re in the report, they’re not on the field.&lt;/p&gt;

&lt;p&gt;Hardening against this is the topic I’m actively working on right now. You have to model the variables ahead of time and enforce them at the raw input step. Who entered it, when, under what conditions, based on what? I hadn’t noticed any of this during the system design; I learned it by going to the field and back, again and again.&lt;/p&gt;

&lt;p&gt;The GIGO classic — garbage in, garbage out — is a textbook sentence. The field’s version is much harsher: the software charges you for the second half of the sentence; the person on the field charges you for the first half.&lt;/p&gt;

&lt;p&gt;”Convincing the user isn’t a technical question”&lt;br&gt;
The system is ready, the screen works, the buttons are in place. The operator still wants to write into Excel. Because Excel is the file he’s kept for years; opening it is reflex. Your system is new, unfamiliar, a screen layout he doesn’t get.&lt;/p&gt;

&lt;p&gt;If the field team isn’t willing and accountable, the system rots all the same. The software can be good, the training can be done, but if one or two people say “I’m going to keep tracking it in Excel,” the chain breaks. Because once a single link in the chain stops keeping records, the report you can look back at isn’t honest.&lt;/p&gt;

&lt;p&gt;This isn’t a problem you solve by writing code. UX improvements solve part of it (make it easier to use than Excel); the rest depends on the team’s decision and the manager’s stance.&lt;/p&gt;

&lt;p&gt;Being the developer and the end user at the same time&lt;br&gt;
Not a usual combination. I write an ERP and, at the same time, use it as the person responsible for sales and shipping.&lt;/p&gt;

&lt;p&gt;The advantage is clear: when reading the spec I don’t think “how would the sales lead behave,” I think “as the sales lead, what do I want right now?” I’m in my 11th year in the industry. How a quote is opened, the routes a container takes from Turkey to wherever it goes, how freight cost is calculated, what the customer asks on the phone — the screen comes to me already built in my head. That’s a context an outside developer can never have.&lt;/p&gt;

&lt;p&gt;But there’s a price to this, and I have to be honest.&lt;/p&gt;

&lt;p&gt;First risk: this isn’t my main job. Sales and shipping are the main job; software is the side. So there’s no sprint discipline. I add a piece when I feel like it, on another day I don’t touch it at all. I can’t make a “this will take two weeks” plan for an important feature, because two weeks of workdays are already booked for the sales work.&lt;/p&gt;

&lt;p&gt;Second risk: no opposing view. When you use what you’ve written, your “it would be better if it were like this” thought is closed off from the outside developer’s “who’s using this, does this person actually think this way?” check. Some of my software decisions might be off, because I work without discipline. Since I’m the only one who knows, there’s no outside eye to say so either.&lt;/p&gt;

&lt;p&gt;This post is, in part, a note against that blindness.&lt;/p&gt;

&lt;p&gt;Closing&lt;br&gt;
Without data integrity, however elegantly you’ve designed your “million-dollar” software, it ends up in the bin. If the field team doesn’t feel accountable, the system rots all the same. Those two sentences are the hardest thing four and a half months have taught me, looking back.&lt;/p&gt;

&lt;p&gt;There’s no “done.” Maybe it goes on like this for another year, maybe three. Weaving the system, testing it on the field, the user habits shifting, the “first input” discipline settling in — none of these are work with a release date. You finish the software, the feedback comes back from the field, you go back and fix it. Then again.&lt;/p&gt;

&lt;p&gt;Maybe the main lesson is this: writing a factory isn’t a one-time job. It’s an ongoing, field-embedded, permanent relationship. I wrote about the independent warehouse system I wove alongside this one in the post A timber’s diary.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>manufacturing</category>
      <category>webdev</category>
    </item>
    <item>
      <title>A timber's diary</title>
      <dc:creator>Talha BEKLER</dc:creator>
      <pubDate>Sun, 24 May 2026 17:25:20 +0000</pubDate>
      <link>https://forem.com/madduck54/a-timbers-diary-1713</link>
      <guid>https://forem.com/madduck54/a-timbers-diary-1713</guid>
      <description>&lt;p&gt;While building the ERP described in the previous post, I came to realize that some jobs are jobs of their own systems. When timber imports started, this became concrete: tracking hundreds of raw materials at the unit level, measuring with handheld terminals, following them with QR codes — a separate warehouse system that needed to be built from scratch. This post tells the story of a single piece of timber, from the moment it lands at the yard to the moment it climbs onto a customer's truck, along with the software decisions I made along the way.&lt;/p&gt;

&lt;p&gt;In the previous post, I described how I migrated an inherited ERP onto a modern stack and, on top of that, wove the missing production chain on the field from scratch. This post is a sequel of sorts, because there’s something I understood while building that ERP: some jobs are not the ERP’s job. This project was born out of that realization.&lt;/p&gt;

&lt;p&gt;”You can’t fit this into the ERP”&lt;br&gt;
While building the ERP, I kept asking myself the same question: which work belongs inside it, and which belongs to its own application? Because when you try to pile everything into a single system, either the system gets bloated or the usability falls apart. There were areas on the field still being managed with Excel and WhatsApp; I was uneasy about not touching them, but cramming all of them into the ERP wasn’t right either.&lt;/p&gt;

&lt;p&gt;Then a new line of business emerged at the factory: timber imports. Previously, we’d been buying raw material from various suppliers built on years of relationships. Timber imports were something else: heavy volume, sizable quantities, a business whose details we mostly didn’t know. A container would arrive in Turkey by ship, get unloaded at the warehouse, with the raw timber inside sitting on shelves for days or months, and then be sold to customers piece by piece or by the pallet.&lt;/p&gt;

&lt;p&gt;At first I considered adding it to the ERP as a module. But the more I thought about it, the harder it got to insist: that ERP was a quote/order ERP. The timber in the warehouse, on the other hand, was raw material that needed to be measured, labeled, and tracked at the unit level until it was sold — hundreds of pieces of it. A field-heavy flow like that inside the ERP would have blurred the system’s center of gravity. There was a stack mismatch too: the ERP was built on Blade + Alpine + MySQL, and what I’d be building here was Vue + Inertia + Postgres + PWA. Field devices, offline operation, talking to a label printer directly over TCP — those are features of a different application.&lt;/p&gt;

&lt;p&gt;The decision to write it from scratch, separately, and again on my own came easily. Software cost was the main reason, again.&lt;/p&gt;

&lt;p&gt;First encounter with the device world&lt;br&gt;
Before the software decision, there was a fear: handheld terminals. Field devices were a world I knew nothing about.&lt;/p&gt;

&lt;p&gt;I ordered a test device. A cheap Chinese Android handheld with a crookedly glued cover. I spent two nights wrestling with it. How does barcode scanning work, how does the system detect the device, how does the screen behave, which browser does it use. I realized it was more or less a standard Android device, just with a rugged case, a trigger button, and a laser scanner on it.&lt;/p&gt;

&lt;p&gt;That was a relief, but at the same time it surfaced a new fear: if it’s Android, I’d have to write the application as an APK. I had zero Android experience. What’s an APK, what language is it written in, what DB does it use, how do you deploy it — I had no idea. “How am I going to pull this off?” was a real moment for me.&lt;/p&gt;

&lt;p&gt;The solution was actually hidden in the application’s background: I didn’t have to write a native APK. For the warehouse tracking app, something running in a web browser would suffice; the Chrome on the handheld would run Vue just fine. On top of that I added PWA (manifest, service worker, offline cache), which still gives the user the “app” feel. Fullscreen on launch, offline operation, addable to the home screen.&lt;/p&gt;

&lt;p&gt;So my PWA choice wasn’t “let’s try a modern technology.” It was a maneuver to pull an unfamiliar area (Android native) into a familiar one (web). Will the user notice? No. Will it benefit me? Hugely.&lt;/p&gt;

&lt;p&gt;Our current field device is the Zebra TC21, a professional Android handheld. The label printer side fell into place in two steps too: we first tried a small portable Zebra ZPL 320, but the connection was unreliable and the label size was insufficient. We switched to a TSC TE210 (203 dpi, 70×50 mm). Efficient, problem-free, still in use. We talk to the printer directly over a TCP socket on port 9100; the server generates TSPL2 commands and prints Turkish characters cleanly with code page 1254.&lt;/p&gt;


&lt;div class="crayons-card c-embed"&gt;

  

&lt;h3&gt;
  
  
  The Hardware Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Handheld:&lt;/strong&gt; Zebra TC21 (Android)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Printer:&lt;/strong&gt; TSC TE210 (203 dpi)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protocol:&lt;/strong&gt; TCP Socket (Port 9100)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commands:&lt;/strong&gt; TSPL2

&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;



&lt;p&gt;Full pallet, or piecemeal?&lt;br&gt;
When I started building the system, there was a deliberate design decision: we never break a pallet. The customer buys a pallet; we don’t sell retail. This would both make things easier operationally and keep the system simple — there’d be no need for an extra state machine to track things at the unit level.&lt;/p&gt;

&lt;p&gt;But a corner of my mind kept coming back to the same question: what if someone breaks open a pallet and asks for individual pieces — how do we track what’s left?&lt;/p&gt;

&lt;p&gt;Eventually that question demanded an answer. I designed the system so it could track all the way down to the unit: the pallet QR stays fixed, but the state of the timber inside it (in stock / reserved / sold) is carried in JSON data. Once a handheld scans a pallet, the system can now say: “This pallet was opened, 3 pieces from it were sold to this customer, 7 pieces remain.”&lt;/p&gt;

&lt;p&gt;The concrete payoff of this decision will show up in the next section: the field flow for unit-level sales was built around this evolution.&lt;/p&gt;

&lt;p&gt;The scenarios were tested; I can’t see any holes. But whether something I missed will surface in real life — I don’t know. We’ll see in time.&lt;/p&gt;

&lt;p&gt;A timber’s journey&lt;br&gt;
The best way to describe what the system does is through a single piece of timber.&lt;/p&gt;

&lt;p&gt;Days before the container arrives in Turkey, the supplier sends a packing list — a breakdown of “this container has timber of these dimensions, of these grades, in these quantities.” We upload the PDF into the system; the goods receipt user opens it on the handheld and gets a preview of what’s coming. It’s a small detail, but it makes a big difference on the field: the user starts forming a picture of the product before the container even arrives. Without it, every time he’d have to call the office to ask “what’s coming again?”&lt;/p&gt;

&lt;p&gt;Once the container is unloaded, the goods receipt process begins. The user taps “receive goods” on the handheld:&lt;/p&gt;

&lt;p&gt;He picks the date and confirms.&lt;br&gt;
He selects the supplier. There’s a deliberate design decision here: the system doesn’t show him all suppliers — only those whose purchases have been made and are due for delivery soon. With dozens of suppliers side by side in a list, the user could accidentally pick the wrong one; by narrowing the list, I drive that error rate to zero.&lt;br&gt;
Product and grade are selected.&lt;br&gt;
The system asks a question: “Are the length and thickness of the timber you’re going to enter the same?” If all the timber on the pallet has the same thickness × length, he says “yes,” the system takes those two common values once, and from then on only asks for the width of each piece. Otherwise, each piece must be entered with all three values. This cuts the amount of work done on the handheld to roughly a third — and more importantly, it proves to the user that the handheld isn’t grinding him down.&lt;br&gt;
The user measures each piece one by one: 10×20×400, 10×10×300… The system automatically computes the cubic meters of each (six decimal places, because the m³ difference looks small, but accumulates as the lot grows).&lt;br&gt;
When the pallet is done, he taps “close pallet.” At that moment the system triggers the printer: the pallet QR code, plus an individual QR code for every piece in it, all come out of the printer one after another in a single shot.&lt;br&gt;
The user sticks each label on its piece, sticks the pallet label on the pallet, and the pallet enters stock.&lt;br&gt;
Same flow for the next pallet. Until the container is empty.&lt;/p&gt;

&lt;p&gt;Months later, a buyer asks for timber. A sales order is opened in the office. A notification lands on the handheld. The user on the field opens the order and starts confirming the physical shipment.&lt;/p&gt;

&lt;p&gt;For full-pallet sales, the flow is simple: he scans the pallet QR, and the system marks every piece on that pallet as “sold” in one go. For unit-level sales, I built an elegant verification flow: first the pallet is scanned. The system checks that this is actually the pallet that’s supposed to be sold; if it’s wrong, it throws an error to the user, and scanning starts over until the right pallet is found. Once the correct pallet is opened, the pieces inside become selectable for the user; he marks the pieces to be sold by scanning them one by one. The system won’t close the shipment until verification is complete.&lt;/p&gt;

&lt;p&gt;The only reason I put this logic in is one thing: to drive the risk of selling the wrong piece from the wrong pallet to zero. The field is dim, tired, distractions are everywhere; the system has to block the mistake even when attention slips.&lt;/p&gt;

&lt;p&gt;The developer’s mind and the field’s mind are the same mind&lt;br&gt;
In the previous post I’d written: “I don’t think ‘how would the sales lead behave,’ I think ‘as the sales lead, what do I want right now?’” In this project I lived through the conditions where I actually had to put that thesis into practice.&lt;/p&gt;

&lt;p&gt;The system’s design didn’t come to me from someone outside. The packing list idea, narrowing the supplier list during goods receipt, the “are length and thickness the same?” question, the pallet verification logic — none of it came to me from “let’s ask the salesperson,” “let’s ask the warehouse guy,” “let’s ask the developer.” I found all of it on my own, by running my own scenarios, by letting my own experience speak.&lt;/p&gt;

&lt;p&gt;While doing this, I felt almost split, honestly.&lt;/p&gt;

&lt;p&gt;I went down to the field, took the terminal in my hand, and actually received goods. I pulled out my laptop, checked the system, saw the gaps. I measured timber dozens of times, lived through a goods receipt from start to finish. Whenever I found a flow that made a user’s job harder, I thought it through, solved it, tested it, fixed the gaps, analyzed the bugs, and coded it again. Then I went back down to the field.&lt;/p&gt;

&lt;p&gt;What I’m trying to say is this: I was the one taking the goods, the one receiving them, the one selling them. I programmed myself as every part of the system. Until I had the right data.&lt;/p&gt;

&lt;p&gt;This is a quiet but powerful mode of writing software. If another developer had built this project, he’d have to go to the field, talk to the user, learn the loop, come back to the desk and try to code, then come back a week later saying “this didn’t work.” I was writing the code while standing inside the loop; the latency between them was zero.&lt;/p&gt;

&lt;p&gt;That’s also why I never had a “I thought like a developer, but it doesn’t work that way on the field” moment in this project. I’d had plenty of those in the previous post; there, someone else’s decisions had been pushed onto me, and I had to go through the experience phase. Here, every decision was the result of a remembered goods-receipt moment or a sales-call scene.&lt;/p&gt;

&lt;p&gt;What I still haven’t solved&lt;br&gt;
Even so, there’s one open problem, to be honest.&lt;/p&gt;

&lt;p&gt;At goods receipt, measuring each piece of timber one by one is still bound to human labor. A user picks up a piece, opens the tape measure, enters the thickness, width, and length values into the handheld one at a time. With hundreds of pieces, that’s a multi-hour job, and fatigue turns into measurement error. The system feeds off this raw data both at the very beginning and at the very end; in other words, the lesson “if the first input is wrong, the chain is rotten” from the previous post applies here too, but the trigger is different: a wrong value entered out of fatigue causes the system to carry the wrong cubic meters forever.&lt;/p&gt;

&lt;p&gt;The solution in my head is pallet-level measurement. The global practice points that way: instead of measuring each piece with a tape, measuring the entire pallet as a whole and computing its total volume. I haven’t moved there yet, but that’s the direction.&lt;/p&gt;

&lt;p&gt;Closing&lt;br&gt;
Somewhere in this post I wrote the line: “If multiple suppliers’ goods arrive in the same period in the future, things might get tangled — for now, it’s an open issue.” I noticed that line while writing the post. It hadn’t occurred to me before.&lt;/p&gt;

&lt;p&gt;In the closing of the previous post I’d said, “this post is, in a way, a note against that blindness.” Here’s a real-time piece of evidence: writing is a thinking tool, not just a record. Sitting under a section, sequencing the flow, a gap in the system I hadn’t noticed before suddenly surfaces. I jot it down on the side of the file.&lt;/p&gt;

&lt;p&gt;Maybe blogging is, in the long run, a development tool that feeds the system, not just a way to broadcast it. I’ll keep testing this for a while.&lt;/p&gt;

&lt;p&gt;This system is still growing. There’s still no “done.” The next step will probably be moving to pallet-level measurement. For now: human hand, tape measure, terminal screen.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>pwa</category>
    </item>
  </channel>
</rss>
