<?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: Georgios Moustakas</title>
    <description>The latest articles on DEV Community by Georgios Moustakas (@gmoustakas).</description>
    <link>https://dev.to/gmoustakas</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%2F92253%2F86097589-a7c8-4251-abf9-093ebec10af1.png</url>
      <title>DEV Community: Georgios Moustakas</title>
      <link>https://dev.to/gmoustakas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gmoustakas"/>
    <language>en</language>
    <item>
      <title>Stop using AI as a search engine with extra steps.</title>
      <dc:creator>Georgios Moustakas</dc:creator>
      <pubDate>Tue, 16 Jun 2026 20:27:40 +0000</pubDate>
      <link>https://dev.to/gmoustakas/stop-using-ai-as-a-search-engine-with-extra-steps-49oo</link>
      <guid>https://dev.to/gmoustakas/stop-using-ai-as-a-search-engine-with-extra-steps-49oo</guid>
      <description>&lt;p&gt;I watched a developer spend forty minutes going back and forth with Claude on a database schema problem. Every message was a question. Every reply was an answer. At the end of forty minutes they had a schema that technically worked and felt wrong in ways they could not explain.&lt;/p&gt;

&lt;p&gt;The problem was not the model. The problem was the format. They were using a conversation as a Q&amp;amp;A session when they needed a thinking session. Those are different things.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the search engine habit forms
&lt;/h2&gt;

&lt;p&gt;Google trained a generation of developers to interact with computers through queries. You have a question, you form a concise search term, you get results, you close the tab. The whole interaction is built around a question you already know how to ask.&lt;/p&gt;

&lt;p&gt;That habit transfers badly to AI. When you treat a language model like a search engine you are constraining the interaction to questions you can already frame. You get answers, not insights. You get syntax, not architecture. You get what you asked for, which is often not what you needed.&lt;/p&gt;

&lt;p&gt;Search engines retrieve information that already exists somewhere. That is useful when you need a fact. It is useless when you need to think through a problem that does not have a pre-existing answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a reasoning engine can actually do
&lt;/h2&gt;

&lt;p&gt;The difference between retrieval and reasoning is the difference between a library and a colleague. A library gives you what is already written down. A colleague can work through something new with you, push back on your assumptions, and tell you when your plan has a hole in it.&lt;/p&gt;

&lt;p&gt;Language models can do the second thing, but only if you interact with them the right way. And the right way looks nothing like a search query.&lt;/p&gt;

&lt;p&gt;Here is what I mean in practice. These are two different interactions with the same underlying question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Search engine mode:&lt;/strong&gt; "What is the best way to structure a Python microservice?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thinking partner mode:&lt;/strong&gt; "I am building a Python microservice that processes webhook events from three external APIs. Each API has different retry behaviour and payload shapes. I am considering a single FastAPI app with a queue in front of it versus three separate lightweight consumers. We have two engineers who will maintain this. What are the tradeoffs I am not seeing?"&lt;/p&gt;

&lt;p&gt;The first interaction gets you a blog post. The second gets you a conversation that makes you think harder than you would have on your own.&lt;/p&gt;

&lt;h2&gt;
  
  
  The context is the work
&lt;/h2&gt;

&lt;p&gt;The engineers getting the most out of these tools are not the ones with the cleverest prompts. They are the ones who bring the most context before they ask anything. They describe what they are building, what constraints they are operating under, what they have already tried, and what feels wrong even if they cannot say why.&lt;/p&gt;

&lt;p&gt;That last part matters. "This feels wrong but I cannot say why" is one of the most productive things you can put in a prompt. It gives the model permission to probe your assumptions instead of just answering your question. Nine times out of ten it will surface the thing you were sensing but could not name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why most AI interactions feel shallow
&lt;/h2&gt;

&lt;p&gt;Shallow interactions happen when the question is too clean. Real engineering problems are messy. They have competing constraints, legacy decisions, team dynamics, and deadlines baked into them. When you strip all of that out and ask a clean question, you get a clean answer that does not account for any of it.&lt;/p&gt;

&lt;p&gt;The mess is not noise. The mess is the actual problem. A model that does not know about the mess cannot help you with the mess.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shift in practice
&lt;/h2&gt;

&lt;p&gt;Before your next significant prompt, spend two minutes writing down: what you are trying to accomplish, what approach you are considering, and what you are uncertain about. Then give all three to the model before you ask your question.&lt;/p&gt;

&lt;p&gt;This sounds like more work. It is more work. It is also the work you should have been doing before you started writing code. The model did not add that step - it just makes skipping it more expensive.&lt;/p&gt;

&lt;p&gt;A search engine needs a clean query. A thinking partner needs the full picture.&lt;/p&gt;

&lt;p&gt;Stop cleaning up the mess before you ask. The mess is the context. The context is everything.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
      <category>claudecode</category>
    </item>
    <item>
      <title>Your AI assistant is not hallucinating. It's guessing, and you asked it to guess.</title>
      <dc:creator>Georgios Moustakas</dc:creator>
      <pubDate>Tue, 16 Jun 2026 20:18:27 +0000</pubDate>
      <link>https://dev.to/gmoustakas/your-ai-assistant-is-not-hallucinating-its-guessing-and-you-asked-it-to-guess-56of</link>
      <guid>https://dev.to/gmoustakas/your-ai-assistant-is-not-hallucinating-its-guessing-and-you-asked-it-to-guess-56of</guid>
      <description>&lt;p&gt;Andrej Karpathy said it plainly in 2023: language models do not know they are wrong. They have no internal signal that flags uncertainty. They generate the most probable continuation of whatever you gave them, and they do it with the same confidence whether the output is correct or completely fabricated.&lt;/p&gt;

&lt;p&gt;That is not hallucination. That is how the architecture works.&lt;/p&gt;

&lt;p&gt;The word "hallucination" implies the model drifted on its own - that it wandered into fiction unprompted. That framing lets you off the hook. The more accurate framing does not.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is actually happening under the hood
&lt;/h2&gt;

&lt;p&gt;Large language models are next-token predictors. At every step, the model produces a probability distribution over the entire vocabulary and samples from it. The output that emerges is the sequence that seemed most likely given everything before it. There is no lookup table, no database of facts it checks against. It is pattern completion operating at scale.&lt;/p&gt;

&lt;p&gt;When the model produces something wrong, it is not because it had a moment of confusion. It is because the probability distribution it built from your prompt pointed toward that output. The wrong answer was the most likely answer given the input you provided.&lt;/p&gt;

&lt;p&gt;This distinction matters because it changes where you look when things go wrong. If the model hallucinated, there is nothing you can do - it is a flaw in the system. If the model guessed badly because you gave it a vague prompt, that is your problem to fix and you can fix it right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gap is always in the specification
&lt;/h2&gt;

&lt;p&gt;The pattern that shows up most consistently: outputs that look wrong are almost always responding to inputs that were underspecified. The model gave a reasonable answer to the question that was actually asked, not the question the engineer thought they asked.&lt;/p&gt;

&lt;p&gt;These are different questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"How do I connect to Postgres in Python?" - the model answers with something that works somewhere, probably not your exact setup.&lt;/li&gt;
&lt;li&gt;"How do I connect to Postgres in Python using psycopg3, connection pool of 10, on Ubuntu 24.04, behind a Cloudflare Tunnel, with a 30-second timeout?" - now it has actual constraints to work with.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first prompt has six implied decisions the model has to guess. The second prompt has none.&lt;/p&gt;

&lt;p&gt;The difficulty of writing a specific prompt is the difficulty of knowing what you actually need. If you cannot write the specific prompt, you do not yet know what you need. That is useful information - it means you should stop prompting and start thinking.&lt;/p&gt;

&lt;h2&gt;
  
  
  The confidence problem
&lt;/h2&gt;

&lt;p&gt;What makes this genuinely tricky is that LLMs produce wrong outputs with the same fluency and confidence as correct ones. The prose sounds authoritative. The code looks clean. There is no stutter, no hedge, no signal that says "I am filling in a gap here."&lt;/p&gt;

&lt;p&gt;This is where experience matters. A junior engineer reads the output and trusts it because it looks right. A senior engineer reads the output and asks: where did I leave room for interpretation? Every ambiguous word in the prompt is a decision the model made without you. Every missing constraint is a place where probability took over.&lt;/p&gt;

&lt;h2&gt;
  
  
  The second-order problem: retrying without changing anything
&lt;/h2&gt;

&lt;p&gt;When an output is wrong, the most common response is to resubmit with a slightly different wording and hope for a different result. Sometimes that works. More often it does not, because the problem was not the phrasing - it was the missing context.&lt;/p&gt;

&lt;p&gt;Retrying without fixing the specification is the AI equivalent of restarting a service without checking the logs. You might get lucky. You have not fixed anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to actually do
&lt;/h2&gt;

&lt;p&gt;When an AI output is wrong, read your prompt before you rewrite it. Ask where you left room for interpretation. Add the missing constraints. Be specific about inputs, outputs, error handling, dependencies, and edge cases before you ask for the implementation.&lt;/p&gt;

&lt;p&gt;A useful habit: before submitting a prompt, reread it as if you were a new engineer joining the project with no context. What would you have to guess? Everything you would have to guess is a place the model will guess too.&lt;/p&gt;

&lt;p&gt;The model is not lying to you. It is showing you the shape of what you did not specify. Once you see it that way, the fix is always the same.&lt;/p&gt;

&lt;p&gt;Write tighter prompts.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
      <category>claudecode</category>
    </item>
    <item>
      <title>The networking problem behind every "random" backend outage.</title>
      <dc:creator>Georgios Moustakas</dc:creator>
      <pubDate>Sat, 13 Jun 2026 13:21:07 +0000</pubDate>
      <link>https://dev.to/gmoustakas/the-networking-problem-behind-every-random-backend-outage-ei3</link>
      <guid>https://dev.to/gmoustakas/the-networking-problem-behind-every-random-backend-outage-ei3</guid>
      <description>&lt;p&gt;You get paged at 2am. The service is down. You check the app — no deploys, no config changes, nothing. You restart the container and it comes back. You go to sleep. It happens again Thursday.&lt;/p&gt;

&lt;p&gt;It was never the app.&lt;/p&gt;

&lt;p&gt;I spent three years doing satellite internet support before I moved into backend engineering. That job taught me one thing: most "application" problems are network problems wearing a disguise. I see the same patterns now in backend systems that I saw then in rural broadband infrastructure.&lt;/p&gt;

&lt;p&gt;Here are the ones that get teams every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The timeout that isn't a timeout
&lt;/h2&gt;

&lt;p&gt;Your service calls a third-party API. It times out. You log it, you retry, life goes on. But the retries pile up. Each retry holds a connection open. Your connection pool fills. New requests start queuing. The queue backs up. Now your service looks down — but the third-party API recovered ten seconds ago.&lt;/p&gt;

&lt;p&gt;The fix is not a shorter timeout. The fix is a circuit breaker. Don't retry into a wall. Detect the wall and stop knocking.&lt;/p&gt;

&lt;h2&gt;
  
  
  DNS TTL lying to you in production
&lt;/h2&gt;

&lt;p&gt;You rotate a database host. You update the DNS record. You wait for TTL to expire — 300 seconds, fine. But your app has been running for six hours and the old IP is baked into the JVM DNS cache, or your connection pool, or a library that ignores TTL entirely.&lt;/p&gt;

&lt;p&gt;The new host is up. The app is still talking to the old one. The old one is gone. Outage.&lt;/p&gt;

&lt;p&gt;Always set TTL aggressively low before a planned DNS change. And test your app's actual DNS resolution behaviour, not just the record.&lt;/p&gt;

&lt;h2&gt;
  
  
  The packet that never comes back
&lt;/h2&gt;

&lt;p&gt;TCP connections are stateful. A NAT device, a load balancer, a firewall — they all keep track of active connections. Leave a connection idle long enough and that state entry gets evicted. The next packet on that connection goes nowhere. Your app is still waiting for a response that will never arrive.&lt;/p&gt;

&lt;p&gt;This is the silent killer of database connection pools. The DB is fine. The network path is fine. But the connection your pool thinks is open has been silently dropped by a load balancer that forgot it existed.&lt;/p&gt;

&lt;p&gt;Keepalives exist for this reason. Use them. Set &lt;code&gt;tcp_keepalive_time&lt;/code&gt; lower than your NAT timeout. Most default settings are wrong for production.&lt;/p&gt;

&lt;h2&gt;
  
  
  MTU mismatch on the path nobody checks
&lt;/h2&gt;

&lt;p&gt;A packet leaves your server at 1500 bytes. Somewhere between you and the destination, a link has an MTU of 1400. The packet needs to be fragmented. If the DF (don't fragment) bit is set and ICMP is blocked — which it often is — the packet is silently dropped. The connection hangs. Nothing in your application logs explains why.&lt;/p&gt;

&lt;p&gt;I saw this constantly in satellite networks where overhead compression changed effective MTU. I still see it in cloud environments where overlay networks, VPNs, and tunnel encapsulation all shave bytes off the path.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;tracepath&lt;/code&gt; instead of &lt;code&gt;traceroute&lt;/code&gt;. Check PMTUD. If you're running on Kubernetes with Flannel or Calico, know what your overlay MTU actually is.&lt;/p&gt;

&lt;h2&gt;
  
  
  The retry storm
&lt;/h2&gt;

&lt;p&gt;Your upstream is slow. Your service retries. Every service instance retries at the same time because they all hit the same timeout window. Your upstream — which was recovering — now gets hit with 10x normal traffic. It goes down again.&lt;/p&gt;

&lt;p&gt;Add jitter to your retries. Exponential backoff without jitter is a coordinated attack on your own infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters more now
&lt;/h2&gt;

&lt;p&gt;More surface area means more network paths. Microservices, managed databases, external APIs, LLM providers — each hop is a place for the network to betray you. The app is often the last thing to blame.&lt;/p&gt;

&lt;p&gt;When something breaks randomly and the restart fixes it, start at the network. Check connection pool state, check DNS, check keepalive settings. The answer is usually there.&lt;/p&gt;

&lt;p&gt;The app was fine the whole time.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>backend</category>
      <category>python</category>
      <category>devops</category>
    </item>
    <item>
      <title>Stop vibe coding. Start using AI with intent.</title>
      <dc:creator>Georgios Moustakas</dc:creator>
      <pubDate>Sat, 13 Jun 2026 11:27:01 +0000</pubDate>
      <link>https://dev.to/gmoustakas/stop-vibe-coding-start-using-ai-with-intent-3km3</link>
      <guid>https://dev.to/gmoustakas/stop-vibe-coding-start-using-ai-with-intent-3km3</guid>
      <description>&lt;p&gt;Everyone is vibe coding. Prompting an AI, accepting whatever comes out, shipping it. It works until it doesn't, and when it doesn't, nobody knows why.&lt;/p&gt;

&lt;p&gt;I use Claude Code every day. Across planning, implementation, and review. But the way I use it looks nothing like what gets posted on Twitter.&lt;/p&gt;

&lt;h2&gt;
  
  
  The vibe coding trap
&lt;/h2&gt;

&lt;p&gt;Vibe coding assumes the model knows what you want. It doesn't. It knows what you typed. If you type vague things, you get vague code that passes a surface-level read and breaks on the third edge case.&lt;/p&gt;

&lt;p&gt;The output is only as good as the intent behind the prompt. That's not a model problem. That's a thinking problem.&lt;/p&gt;

&lt;p&gt;I have watched engineers prompt their way into a working demo in 20 minutes and spend two days debugging production because the model made a reasonable-looking decision that was wrong for their specific data shape. The model was not wrong in any general sense. It was wrong for that context, and nobody checked.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "with intent" actually means
&lt;/h2&gt;

&lt;p&gt;Before I write a single prompt, I know three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What this piece of code is supposed to do&lt;/li&gt;
&lt;li&gt;What it must not do&lt;/li&gt;
&lt;li&gt;How I will verify it works&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That sounds obvious. Most people skip steps two and three entirely.&lt;/p&gt;

&lt;p&gt;Step two is where security holes live. It is where the off-by-one errors live. It is where "handle the error case" gets interpreted as "swallow the exception and return None." The model will do something reasonable. Reasonable is not always correct.&lt;/p&gt;

&lt;p&gt;Step three is where you find out if you actually understood the problem before you started prompting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I hand it the wheel and where I don't
&lt;/h2&gt;

&lt;p&gt;I use Claude Code to move fast on the parts where speed is the point: boilerplate, repetitive transforms, first drafts of tests, scaffolding a new route that follows an existing pattern. These are low-risk, high-repetition tasks. The model is faster than I am and the output is easy to verify.&lt;/p&gt;

&lt;p&gt;I slow down and take over on the parts where judgment matters: data modeling, failure modes, anything that touches auth or external APIs, anything where "plausible" and "correct" are different things.&lt;/p&gt;

&lt;p&gt;The model is a force multiplier. Force multipliers amplify what you bring. If you bring nothing, you get nothing, faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  The review step nobody does
&lt;/h2&gt;

&lt;p&gt;After Claude Code writes something, I read it. Not skim it. Read it line by line. I treat it like code from a junior engineer who is very confident and occasionally wrong in ways that are hard to spot.&lt;/p&gt;

&lt;p&gt;I evaluate AI models professionally at Datawise. We run structured benchmarks across dozens of tasks. One thing I have learned from that work: these models are very good at producing output that looks right. Looking right and being right are not the same thing. The gap between them is where bugs live.&lt;/p&gt;

&lt;p&gt;Reading the output is not optional. It is the job.&lt;/p&gt;

&lt;h2&gt;
  
  
  The prompting discipline that actually matters
&lt;/h2&gt;

&lt;p&gt;Vague prompt: "write a function that processes user input"&lt;/p&gt;

&lt;p&gt;Specific prompt: "write a Python function that validates and sanitizes a username: ASCII only, 3 to 30 characters, no spaces, raise ValueError with a clear message on failure, no dependencies outside the standard library"&lt;/p&gt;

&lt;p&gt;The second prompt gets you something you can ship. The first gets you something you have to rewrite.&lt;/p&gt;

&lt;p&gt;The more specific your prompt, the less reviewing you have to do. That is the actual skill. Not knowing which AI tool to use. Not having the right subscription. Writing prompts that leave no room for interpretation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual workflow
&lt;/h2&gt;

&lt;p&gt;Plan in plain language first. Write out what you want and what you do not want before you open Claude Code. Let it draft. Read what comes back. Push back on anything clever. Verify against the original intent. Ship.&lt;/p&gt;

&lt;p&gt;That's it. No magic. Just using a powerful tool with the same discipline you'd bring to any other part of the stack.&lt;/p&gt;

&lt;p&gt;Vibe coding is a fine way to prototype. It is a bad way to build things that need to keep working.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
      <category>claudecode</category>
    </item>
    <item>
      <title>LLM API Tokens burning your Bank even on testing ? Not anymore, cuesheet is here to help with that.</title>
      <dc:creator>Georgios Moustakas</dc:creator>
      <pubDate>Wed, 27 May 2026 08:01:26 +0000</pubDate>
      <link>https://dev.to/gmoustakas/llm-api-tokens-burning-your-bank-even-on-testing-not-anymore-cuesheet-is-here-to-help-with-that-4pgc</link>
      <guid>https://dev.to/gmoustakas/llm-api-tokens-burning-your-bank-even-on-testing-not-anymore-cuesheet-is-here-to-help-with-that-4pgc</guid>
      <description>&lt;p&gt;Tests that called &lt;strong&gt;#Claude&lt;/strong&gt; in CI were quietly burning tokens and breaking on every other run.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;cuesheet&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One decorator around your test. The first run hits the real API and saves the response to a YAML file you commit to your repo. Every run &lt;br&gt;
after that replays from the file. Byte-identical, no network, no cost.&lt;/p&gt;

&lt;p&gt;It works with any Python SDK that sits on httpx, which is most of them in 2026. #Anthropic, #OpenAI, #Google Gemini, #Mistral AI, #DeepSeek AI, and more, Together. &lt;/p&gt;

&lt;p&gt;The pytest plugin auto-discovers cassettes in tests/cassettes/. Streaming responses get recorded as raw SSE chunks and replayed in order. API keys, JWTs, and emails are scrubbed before write so cassettes are safe to commit.&lt;/p&gt;

&lt;p&gt;There is a local web UI too. Dark + ochre, watches the filesystem, refreshes live as your tests record new conversations. Useful for code review and for the "what did the model actually say" moment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;v0.2.0 is out today.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/gmoustakas/cuesheet" rel="noopener noreferrer"&gt;https://github.com/gmoustakas/cuesheet&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Project Details:&lt;/strong&gt; &lt;a href="https://www.georgemou.gr/projects/cuesheet" rel="noopener noreferrer"&gt;https://www.georgemou.gr/projects/cuesheet&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Open source, MIT. If you have been writing LLM tests and quietly hating it, this might give you a few hours back.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>claude</category>
      <category>discuss</category>
    </item>
    <item>
      <title>🚀 Why Every Developer Should Think Like a Product Builder (Not Just a Coder)</title>
      <dc:creator>Georgios Moustakas</dc:creator>
      <pubDate>Thu, 21 Aug 2025 19:36:19 +0000</pubDate>
      <link>https://dev.to/gmoustakas/why-every-developer-should-think-like-a-product-builder-not-just-a-coder-17pl</link>
      <guid>https://dev.to/gmoustakas/why-every-developer-should-think-like-a-product-builder-not-just-a-coder-17pl</guid>
      <description>&lt;p&gt;Software development isn’t just about writing lines of code. It’s about solving real problems, making things that people actually use, and shaping the web in ways that impact millions. Too often, we focus only on frameworks, languages, and tools—but forget the bigger picture: &lt;strong&gt;we’re builders.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Trap: Chasing Tech Trends
&lt;/h2&gt;

&lt;p&gt;Every week, Twitter (sorry, X) lights up with debates:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;“Is React dead?”&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;“Is Rust the new C++?”&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;“Will AI replace developers?”&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chasing every new technology can feel like running on a treadmill—you’re moving fast but going nowhere.  &lt;/p&gt;




&lt;h2&gt;
  
  
  The Shift: From Coder to Creator
&lt;/h2&gt;

&lt;p&gt;The best developers I’ve worked with didn’t just know syntax—they thought like product people. They asked:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Who is this feature for?&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Does this design make sense?&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Is this solving the actual problem?&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This mindset shift transforms your work from “just code” into something meaningful.  &lt;/p&gt;




&lt;h2&gt;
  
  
  Web Development Today: Building With Superpowers
&lt;/h2&gt;

&lt;p&gt;We’re living in a golden age of web development. With tools like &lt;strong&gt;Next.js&lt;/strong&gt;, &lt;strong&gt;Vite&lt;/strong&gt;, and &lt;strong&gt;TailwindCSS&lt;/strong&gt;, spinning up a slick, production-ready app is faster than ever.  &lt;/p&gt;

&lt;p&gt;But with great tools comes a responsibility: &lt;strong&gt;don’t just build cool stuff—build useful stuff.&lt;/strong&gt;  &lt;/p&gt;




&lt;h2&gt;
  
  
  The Human Side of Development
&lt;/h2&gt;

&lt;p&gt;At the end of the day, code is for people. Whether it’s an e-commerce checkout flow or a developer CLI, real users will interact with what you create. Thinking about their experience is what separates a “good developer” from a “great one.”  &lt;/p&gt;




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

&lt;p&gt;Being a developer isn’t about being a “code monkey.” It’s about being a problem solver, a builder, a creator. If you approach every project with the mindset of &lt;em&gt;“how will this actually help someone?”&lt;/em&gt;—you’ll not only stand out as a developer, you’ll make work that matters.&lt;/p&gt;




&lt;p&gt;✍️ &lt;em&gt;If you liked this article, follow me for more thoughts on web development, software, and building products that matter.&lt;/em&gt;  &lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>product</category>
    </item>
    <item>
      <title>Update on my PDF file manipulation Script</title>
      <dc:creator>Georgios Moustakas</dc:creator>
      <pubDate>Mon, 24 Feb 2020 13:43:58 +0000</pubDate>
      <link>https://dev.to/gmoustakas/update-on-my-pdf-file-manipulation-script-44el</link>
      <guid>https://dev.to/gmoustakas/update-on-my-pdf-file-manipulation-script-44el</guid>
      <description>&lt;p&gt;Hi again, in my previous post i had a problem on how to search a large PDF file for a keyword which can be found in multiple pages of the file and in some cases more than once in single page!&lt;/p&gt;

&lt;p&gt;I've used &lt;strong&gt;PyPDF2&lt;/strong&gt; to open a given PDF file, then extract the text page by page, search that text for the given keyword and then check in what page the keyword was found and how many times per page and finally split those pages from the original file and merge them all together to create my final file so it can be printed with the useful data and not with other non-useful data from the original file.&lt;/p&gt;

&lt;p&gt;All works fine with test/dummy data in &lt;strong&gt;English&lt;/strong&gt; Characters but the original file is in &lt;strong&gt;Greek&lt;/strong&gt; and the&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;PdfPageObj.extractText()&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 function of &lt;strong&gt;PyPDF2&lt;/strong&gt; returns an empty string.&lt;/p&gt;

&lt;p&gt;So how would you approach this problem?&lt;br&gt;
Any Suggestions?&lt;/p&gt;

</description>
      <category>python</category>
      <category>help</category>
      <category>problem</category>
      <category>solution</category>
    </item>
    <item>
      <title>PDF file manipulation with python 3 (Problem)</title>
      <dc:creator>Georgios Moustakas</dc:creator>
      <pubDate>Sun, 23 Feb 2020 10:16:19 +0000</pubDate>
      <link>https://dev.to/gmoustakas/pdf-file-manipulation-with-python-3-problem-14l1</link>
      <guid>https://dev.to/gmoustakas/pdf-file-manipulation-with-python-3-problem-14l1</guid>
      <description>&lt;p&gt;Hi, I have a problem I would like help with, i'm working on a project/script with python 3 where I want to manipulate a large PDF file (50-60 plus pages long) where I would like to find a specific keyword in that file, this keyword is repeated multiple times in the file and each time this keyword is referring to a different data set, then save how many times the keyword was found, in what pages was found and then split those pages from the original file and then merge those pages together in a single file.&lt;/p&gt;

&lt;p&gt;I will use multithreading of course, because this script will run alongside other's in a small in-house server and it's already running quite a lot, other scripts.&lt;/p&gt;

&lt;p&gt;I found some things online but no luck in what my problem is, except some python libraries that is possible to do what i'm looking for, but i have no idea how i will found this keyword in the file, because the keyword isn't in the same page order in the files, it's different in every file!! &lt;/p&gt;

</description>
      <category>python</category>
      <category>help</category>
      <category>question</category>
    </item>
  </channel>
</rss>
