<?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: Aftan Ahmad</title>
    <description>The latest articles on DEV Community by Aftan Ahmad (@aftandevelops).</description>
    <link>https://dev.to/aftandevelops</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%2F4058186%2F6847008f-195d-4661-9858-6bb544ff33da.png</url>
      <title>DEV Community: Aftan Ahmad</title>
      <link>https://dev.to/aftandevelops</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aftandevelops"/>
    <language>en</language>
    <item>
      <title>AI Can Write Code. So What Makes You Valuable as a Developer?</title>
      <dc:creator>Aftan Ahmad</dc:creator>
      <pubDate>Fri, 16 Oct 2026 08:40:00 +0000</pubDate>
      <link>https://dev.to/aftandevelops/ai-can-write-code-so-what-makes-you-valuable-as-a-developer-mfi</link>
      <guid>https://dev.to/aftandevelops/ai-can-write-code-so-what-makes-you-valuable-as-a-developer-mfi</guid>
      <description>&lt;p&gt;AI is changing software development faster than most of us expected. Tasks that once required hours of coding can now be completed in minutes with the help of AI tools. Developers can generate entire functions, write tests, debug errors, and even build small applications by describing what they want.&lt;/p&gt;

&lt;p&gt;This raises an important question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If AI can write code, what makes a developer valuable?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The answer isn't to compete with AI at writing code. It's to become the kind of developer who knows what to build, why it matters, how to build it correctly, and how to ensure it works in the real world.&lt;/p&gt;

&lt;p&gt;The future of software development isn't necessarily about writing more code. It's about solving better problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Stop Measuring Your Value by the Code You Write
&lt;/h2&gt;

&lt;p&gt;For years, developers have measured their progress through the technologies they learn, the features they build, and the complexity of the code they can write.&lt;/p&gt;

&lt;p&gt;AI is changing that equation.&lt;/p&gt;

&lt;p&gt;Generating boilerplate, creating CRUD endpoints, writing basic queries, and producing standard components are becoming increasingly accessible. These skills still matter, but they are no longer enough to distinguish an experienced developer from someone who knows how to use an AI coding assistant.&lt;/p&gt;

&lt;p&gt;Your value increasingly comes from the decisions behind the code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can you translate an unclear requirement into a working solution?&lt;/li&gt;
&lt;li&gt;Can you identify the root cause of a production issue?&lt;/li&gt;
&lt;li&gt;Can you recognize when an AI-generated solution is incorrect?&lt;/li&gt;
&lt;li&gt;Can you design a system that remains reliable as it grows?&lt;/li&gt;
&lt;li&gt;Can you understand the business problem you're solving?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI can generate a solution. You need to determine whether it's the right solution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't aim to be the developer who writes the most code. Aim to be the developer who consistently delivers the right outcomes.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Build Strong Fundamentals Instead of Chasing Every New Tool
&lt;/h2&gt;

&lt;p&gt;Every few months, a new AI model, framework, coding assistant, or development workflow appears. It's tempting to believe that staying relevant means constantly learning the latest technology.&lt;/p&gt;

&lt;p&gt;But tools change faster than fundamentals.&lt;/p&gt;

&lt;p&gt;If you're a backend developer, invest in understanding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Databases:&lt;/strong&gt; indexing, query optimization, transactions, locking, and data modeling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System design:&lt;/strong&gt; scalability, caching, queues, service boundaries, and failure handling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Networking:&lt;/strong&gt; HTTP, DNS, TLS, proxies, and how distributed systems communicate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security:&lt;/strong&gt; authentication, authorization, input validation, and common vulnerabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability:&lt;/strong&gt; observability, retries, idempotency, monitoring, and disaster recovery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Programming:&lt;/strong&gt; data structures, algorithms, concurrency, and the behavior of your language and runtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These concepts become even more important when AI generates code quickly.&lt;/p&gt;

&lt;p&gt;An AI assistant might suggest adding a cache to improve performance. An experienced developer asks whether the data can become stale, how invalidation will work, and what happens when the cache goes down.&lt;/p&gt;

&lt;p&gt;The tool provides possibilities. Your fundamentals help you evaluate them.&lt;/p&gt;

&lt;p&gt;You don't need to master everything at once. Choose the fundamentals most relevant to your work and deepen your understanding through practical problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Learn to Use AI Without Becoming Dependent on It
&lt;/h2&gt;

&lt;p&gt;Avoiding AI entirely isn't a sustainable strategy. Neither is blindly accepting everything it produces.&lt;/p&gt;

&lt;p&gt;The goal is to use AI as a force multiplier while retaining your ability to reason independently.&lt;/p&gt;

&lt;p&gt;Use it to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explore unfamiliar codebases.&lt;/li&gt;
&lt;li&gt;Generate repetitive code and initial implementations.&lt;/li&gt;
&lt;li&gt;Understand unfamiliar libraries and APIs.&lt;/li&gt;
&lt;li&gt;Draft unit tests and identify edge cases.&lt;/li&gt;
&lt;li&gt;Review pull requests and investigate potential bugs.&lt;/li&gt;
&lt;li&gt;Compare architectural approaches.&lt;/li&gt;
&lt;li&gt;Automate repetitive development tasks.&lt;/li&gt;
&lt;li&gt;Explain errors and suggest debugging strategies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, don't stop at accepting the output.&lt;/p&gt;

&lt;p&gt;Read the generated code. Verify its assumptions. Run the tests. Inspect the database queries. Consider security implications. Measure performance when it matters.&lt;/p&gt;

&lt;p&gt;One useful practice is to attempt a problem yourself before asking AI for a solution. Even if your first attempt is incomplete, you'll have a better foundation for evaluating its response.&lt;/p&gt;

&lt;p&gt;Another is to ask AI to explain the trade-offs between two approaches instead of simply asking which one to use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The objective is not to become dependent on AI for every answer. It's to become more capable because you know how to use it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Become Better at Debugging and Understanding Complex Systems
&lt;/h2&gt;

&lt;p&gt;Writing a function is one thing. Understanding why a production system fails under unexpected conditions is another.&lt;/p&gt;

&lt;p&gt;Real software systems contain dependencies, historical decisions, imperfect data, resource constraints, race conditions, and failures that rarely appear in a simple example.&lt;/p&gt;

&lt;p&gt;AI can help investigate these problems, but the investigation still requires careful reasoning and evidence.&lt;/p&gt;

&lt;p&gt;For example, imagine an API becomes slow when a report processes millions of database records.&lt;/p&gt;

&lt;p&gt;A superficial solution might be to ask AI to optimize the query.&lt;/p&gt;

&lt;p&gt;A stronger approach is to investigate the entire execution path:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Measure the query's execution time and inspect its execution plan.&lt;/li&gt;
&lt;li&gt;Determine whether indexes are being used effectively.&lt;/li&gt;
&lt;li&gt;Examine memory consumption, connection pools, and concurrent workloads.&lt;/li&gt;
&lt;li&gt;Check whether the application is loading unnecessary records into memory.&lt;/li&gt;
&lt;li&gt;Evaluate pagination, streaming, background processing, or pre-aggregation.&lt;/li&gt;
&lt;li&gt;Test the proposed changes against realistic data volumes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is where experienced developers can create significant value.&lt;/p&gt;

&lt;p&gt;Learn to use logs, metrics, traces, profilers, query plans, and debugging tools. Develop the habit of forming hypotheses and validating them rather than changing code until something appears to work.&lt;/p&gt;

&lt;p&gt;The ability to diagnose unfamiliar problems is a durable skill because the problems themselves keep changing.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Understand System Design and Engineering Trade-Offs
&lt;/h2&gt;

&lt;p&gt;AI can suggest architectures, but good engineering requires decisions based on constraints.&lt;/p&gt;

&lt;p&gt;Should you use a monolith or microservices? Should a task run synchronously or through a queue? Is caching worth the complexity? Does a feature need real-time updates? Should a report use live transactional data or a precomputed summary?&lt;/p&gt;

&lt;p&gt;There isn't always one correct answer.&lt;/p&gt;

&lt;p&gt;The best decision depends on factors such as traffic, data volume, latency requirements, operational complexity, budget, team size, and failure tolerance.&lt;/p&gt;

&lt;p&gt;To improve your system-design skills, practice explaining not just what you would build, but why.&lt;/p&gt;

&lt;p&gt;For every important decision, ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What problem does this solve?&lt;/li&gt;
&lt;li&gt;What alternatives exist?&lt;/li&gt;
&lt;li&gt;What are the trade-offs?&lt;/li&gt;
&lt;li&gt;How will the system behave under failure?&lt;/li&gt;
&lt;li&gt;How will we monitor and maintain it?&lt;/li&gt;
&lt;li&gt;What might need to change as usage grows?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don't need to design systems at the scale of the world's largest technology companies to benefit from system design.&lt;/p&gt;

&lt;p&gt;Even a small SaaS product can teach you about tenant isolation, database design, rate limiting, background jobs, security, deployment, and observability.&lt;/p&gt;

&lt;p&gt;Real constraints make these concepts meaningful.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Build Projects That Demonstrate Engineering Judgment
&lt;/h2&gt;

&lt;p&gt;Tutorial projects can be useful for learning, but completing another basic to-do application rarely demonstrates much beyond familiarity with a framework.&lt;/p&gt;

&lt;p&gt;Build projects that expose you to real engineering challenges.&lt;/p&gt;

&lt;p&gt;Consider a few examples:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A multi-tenant SaaS backend&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Implement tenant isolation, role-based permissions, audit logs, rate limiting, background jobs, and subscription limits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A large-data processing service&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Build a service that processes large CSV files, streams results, handles malformed records, and recovers from interrupted jobs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A reporting system&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create an application that generates reports from substantial datasets, with query optimization, asynchronous processing, caching, and measurable performance targets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A production-ready API&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add authentication, validation, structured logging, integration tests, Docker deployment, monitoring, and documented API contracts.&lt;/p&gt;

&lt;p&gt;The important part isn't the number of features. It's the quality of the engineering decisions you can explain.&lt;/p&gt;

&lt;p&gt;Document the challenges you encountered, the approaches you considered, the benchmarks you measured, and what you would improve next.&lt;/p&gt;

&lt;p&gt;A well-executed project with clear technical reasoning can demonstrate more than several unfinished repositories.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Develop Business Understanding
&lt;/h2&gt;

&lt;p&gt;Developers sometimes focus exclusively on technical implementation and overlook the reason a feature exists.&lt;/p&gt;

&lt;p&gt;But companies don't hire developers merely to produce code. They hire them to help create business value.&lt;/p&gt;

&lt;p&gt;Consider a request to export a large report.&lt;/p&gt;

&lt;p&gt;The immediate task is to generate a downloadable file. The underlying problem might be that customers need timely access to millions of records without slowing down the application.&lt;/p&gt;

&lt;p&gt;Understanding that distinction opens up better solutions: asynchronous exports, progress tracking, streaming, retention policies, or precomputed reports.&lt;/p&gt;

&lt;p&gt;Business understanding helps you identify the actual problem before committing to an implementation.&lt;/p&gt;

&lt;p&gt;Learn to ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who uses this feature?&lt;/li&gt;
&lt;li&gt;What problem are they experiencing?&lt;/li&gt;
&lt;li&gt;How frequently does it occur?&lt;/li&gt;
&lt;li&gt;What does success look like?&lt;/li&gt;
&lt;li&gt;What are the costs of failure?&lt;/li&gt;
&lt;li&gt;Can the problem be solved more simply?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This skill also helps you prioritize your learning. Instead of adopting technologies because they are popular, you can evaluate whether they solve problems worth solving.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Strengthen Communication and Collaboration
&lt;/h2&gt;

&lt;p&gt;Technical ability matters, but communicating technical decisions is also part of engineering.&lt;/p&gt;

&lt;p&gt;Developers need to explain risks, clarify requirements, document decisions, review other people's work, and coordinate changes across teams.&lt;/p&gt;

&lt;p&gt;AI can help draft documentation and summarize technical concepts. However, you still need to understand your audience and communicate the implications clearly.&lt;/p&gt;

&lt;p&gt;Practice explaining complex problems in simple language.&lt;/p&gt;

&lt;p&gt;Instead of saying, "The query is inefficient because the execution plan contains an expensive sequential scan," explain what that means for the user, the system, and the cost of the proposed fix.&lt;/p&gt;

&lt;p&gt;Learn to write useful pull request descriptions, architecture decision records, incident reports, and implementation plans.&lt;/p&gt;

&lt;p&gt;A developer who can identify a problem, explain its impact, propose alternatives, and deliver a solution is valuable beyond their ability to write code.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Learn to Evaluate AI-Generated Code Critically
&lt;/h2&gt;

&lt;p&gt;AI-generated code can look convincing while containing subtle problems.&lt;/p&gt;

&lt;p&gt;It might introduce inefficient queries, insecure authorization checks, incorrect assumptions about library behavior, missing error handling, or tests that fail to cover important cases.&lt;/p&gt;

&lt;p&gt;Make code verification a standard part of your workflow.&lt;/p&gt;

&lt;p&gt;Before accepting an AI-generated implementation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check whether it satisfies the actual requirements.&lt;/li&gt;
&lt;li&gt;Verify that authorization and tenant boundaries are enforced.&lt;/li&gt;
&lt;li&gt;Review database operations and potential performance bottlenecks.&lt;/li&gt;
&lt;li&gt;Test edge cases and failure scenarios.&lt;/li&gt;
&lt;li&gt;Check dependencies and API behavior against reliable documentation.&lt;/li&gt;
&lt;li&gt;Run relevant automated tests, linters, and security checks.&lt;/li&gt;
&lt;li&gt;Review the final diff to identify unintended changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Passing tests is important, but it isn't proof that a system is correct. Tests can be incomplete, and an implementation can satisfy its tests while violating an unstated requirement.&lt;/p&gt;

&lt;p&gt;Treat AI output as a proposal that requires engineering review, not as an authority.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Develop a Specialty While Maintaining Broad Knowledge
&lt;/h2&gt;

&lt;p&gt;Trying to learn every technology is an exhausting strategy.&lt;/p&gt;

&lt;p&gt;A more effective approach is to develop depth in a field while maintaining enough breadth to collaborate across the software development lifecycle.&lt;/p&gt;

&lt;p&gt;Potential areas of specialization include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backend architecture and distributed systems.&lt;/li&gt;
&lt;li&gt;Database performance and data engineering.&lt;/li&gt;
&lt;li&gt;Cloud infrastructure and platform engineering.&lt;/li&gt;
&lt;li&gt;Application security.&lt;/li&gt;
&lt;li&gt;AI integration and AI-powered product development.&lt;/li&gt;
&lt;li&gt;Reliability engineering and production operations.&lt;/li&gt;
&lt;li&gt;Developer tooling and workflow automation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don't have to choose one specialty forever. Your interests and opportunities can evolve.&lt;/p&gt;

&lt;p&gt;For example, a backend developer who understands databases, system design, cloud deployment, and AI-assisted development can take ownership of increasingly complex features.&lt;/p&gt;

&lt;p&gt;The advantage isn't simply knowing more technologies. It's being able to solve a class of problems deeply and reliably.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Build a Habit of Continuous Learning
&lt;/h2&gt;

&lt;p&gt;The pace of change makes continuous learning important, but learning doesn't have to mean spending every evening taking another course.&lt;/p&gt;

&lt;p&gt;A sustainable approach combines reading, building, experimenting, and reflection.&lt;/p&gt;

&lt;p&gt;Try a weekly routine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Learn:&lt;/strong&gt; Study one concept relevant to your current work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apply:&lt;/strong&gt; Use it to solve a real problem or build a small experiment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review:&lt;/strong&gt; Compare your implementation with alternative approaches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document:&lt;/strong&gt; Write down what you learned and what surprised you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share:&lt;/strong&gt; Explain the concept in a short article, technical note, or project write-up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can learn from official documentation, engineering blogs, technical books, open-source repositories, and postmortems from real incidents.&lt;/p&gt;

&lt;p&gt;Prioritize depth over the number of topics covered. Understanding one concept well enough to apply it independently is often more valuable than superficially exploring ten new tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Take Ownership of Outcomes, Not Just Assigned Tasks
&lt;/h2&gt;

&lt;p&gt;Perhaps the most important shift is moving from completing tickets to owning outcomes.&lt;/p&gt;

&lt;p&gt;A task-focused developer might implement an endpoint, open a pull request, and move on.&lt;/p&gt;

&lt;p&gt;An outcome-focused developer also considers whether the endpoint solves the intended problem, whether it is secure, how it performs under load, how it will be monitored, and whether other developers can maintain it.&lt;/p&gt;

&lt;p&gt;Ownership doesn't mean doing everything alone or working unlimited hours. It means understanding your responsibilities, communicating risks, and following through on the quality of the work.&lt;/p&gt;

&lt;p&gt;AI can accelerate implementation, but someone must still make the right decisions, verify the results, and remain accountable for the system.&lt;/p&gt;

&lt;p&gt;That responsibility is a meaningful part of professional software engineering.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Practical 90-Day Plan to Stay Relevant
&lt;/h2&gt;

&lt;p&gt;You don't need to transform your career overnight. Start with a focused plan.&lt;/p&gt;

&lt;h3&gt;
  
  
  Days 1–30: Strengthen your foundations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Identify your three biggest technical weaknesses.&lt;/li&gt;
&lt;li&gt;Choose one relevant area, such as database optimization or system design.&lt;/li&gt;
&lt;li&gt;Use AI to assist with learning, but practice explaining concepts without it.&lt;/li&gt;
&lt;li&gt;Study the architecture of a real application you already understand.&lt;/li&gt;
&lt;li&gt;Improve your debugging and testing habits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Days 31–60: Build something substantial
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Choose a project that solves a real problem.&lt;/li&gt;
&lt;li&gt;Define its requirements and architecture before implementation.&lt;/li&gt;
&lt;li&gt;Use AI to accelerate development while reviewing every important change.&lt;/li&gt;
&lt;li&gt;Add meaningful tests, logging, error handling, and documentation.&lt;/li&gt;
&lt;li&gt;Measure at least one improvement, such as query latency or processing throughput.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Days 61–90: Demonstrate your capabilities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Deploy the project or create a reproducible demonstration.&lt;/li&gt;
&lt;li&gt;Document the architecture and important trade-offs.&lt;/li&gt;
&lt;li&gt;Write a technical article explaining a difficult problem you solved.&lt;/li&gt;
&lt;li&gt;Review your code as if you were reviewing another developer's work.&lt;/li&gt;
&lt;li&gt;Update your resume and portfolio with evidence of impact rather than a long list of technologies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the end of 90 days, you'll have more than a collection of courses. You'll have practical evidence of how you think, build, and solve problems.&lt;/p&gt;

&lt;p&gt;Summarization of Everything we talked about through a visual so you can keep it safe!&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Final Thoughts: The Developer Who Adapts Will Have the Advantage
&lt;/h2&gt;

&lt;p&gt;AI will continue to change how software is built. Some tasks will become faster, certain skills will become less differentiating, and new opportunities will emerge.&lt;/p&gt;

&lt;p&gt;No one can predict exactly how the software engineering job market will evolve. But betting your entire career on the idea that AI will never change development is unwise.&lt;/p&gt;

&lt;p&gt;So is assuming that learning to write prompts is enough to guarantee a successful career.&lt;/p&gt;

&lt;p&gt;The more durable strategy is to combine strong fundamentals, practical engineering experience, critical thinking, business understanding, and effective use of AI.&lt;/p&gt;

&lt;p&gt;Don't abandon coding. Understand it more deeply.&lt;/p&gt;

&lt;p&gt;Don't avoid AI. Learn to work with it intelligently.&lt;/p&gt;

&lt;p&gt;Don't chase every new framework. Learn the concepts that help you evaluate frameworks.&lt;/p&gt;

&lt;p&gt;And don't build your professional identity around tasks that can be automated. Build it around the problems you can solve.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI may change how we write software, but the ability to understand problems, make sound decisions, and deliver reliable solutions will remain central to good engineering.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The goal isn't to prove that you can work without AI.&lt;/p&gt;

&lt;p&gt;It's to become a developer who can accomplish more with AI while still knowing what they're doing—and why it matters.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>development</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>5 JSON Problems Developers Face (And How to Solve Them Without Writing Extra Scripts)</title>
      <dc:creator>Aftan Ahmad</dc:creator>
      <pubDate>Mon, 12 Oct 2026 04:49:07 +0000</pubDate>
      <link>https://dev.to/aftandevelops/5-json-problems-developers-face-and-how-to-solve-them-without-writing-extra-scripts-1mcd</link>
      <guid>https://dev.to/aftandevelops/5-json-problems-developers-face-and-how-to-solve-them-without-writing-extra-scripts-1mcd</guid>
      <description>&lt;p&gt;If you work with APIs, configuration files, or backend services, you've probably spent more time dealing with JSON than you expected.&lt;/p&gt;

&lt;p&gt;Maybe an API response contains hundreds of nested objects. Maybe two API responses look almost identical, but one field has unexpectedly changed. Or perhaps you need to validate a payload against a schema before integrating it into your application.&lt;/p&gt;

&lt;p&gt;These tasks aren't particularly difficult individually, but they can interrupt your workflow.&lt;/p&gt;

&lt;p&gt;Here are five common JSON problems and practical ways to solve them.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Comparing Two JSON Responses
&lt;/h2&gt;

&lt;p&gt;Imagine you're debugging an API regression.&lt;/p&gt;

&lt;p&gt;Yesterday, your endpoint returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Today, it returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jonathan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You could compare the documents manually, use a generic text diff, or write a script.&lt;/p&gt;

&lt;p&gt;However, a text diff may report irrelevant differences caused by formatting or property order.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A structural JSON diff is more useful&lt;/strong&gt; because it focuses on the data itself: added properties, removed properties, and changed values.&lt;/p&gt;

&lt;p&gt;This is particularly helpful when debugging API changes, reviewing configuration updates, or comparing responses between staging and production.&lt;/p&gt;

&lt;p&gt;For quick comparisons, a JSON-specific comparison tool can save you from writing a one-off script.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Extracting Values From Deeply Nested JSON
&lt;/h2&gt;

&lt;p&gt;Consider an API response containing thousands of users, each with profiles, addresses, and account settings.&lt;/p&gt;

&lt;p&gt;You only need the names of users whose age is greater than 18.&lt;/p&gt;

&lt;p&gt;Manually navigating the structure becomes tedious. Writing JavaScript works, but sometimes you just want to inspect the data quickly.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;JSONPath&lt;/strong&gt; comes in.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$.users[*].name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This expression selects the &lt;code&gt;name&lt;/code&gt; property from every item in the &lt;code&gt;users&lt;/code&gt; array.&lt;/p&gt;

&lt;p&gt;A filter expression can narrow the results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$.users[?(@.age &amp;gt; 18)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact supported syntax depends on the JSONPath implementation, but the general idea is simple: query the data instead of manually traversing it.&lt;/p&gt;

&lt;p&gt;JSONPath is especially useful when debugging API responses, inspecting test fixtures, and exploring unfamiliar payloads.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Generating a JSON Schema From Existing Data
&lt;/h2&gt;

&lt;p&gt;Suppose you're integrating with an API and receive this payload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sarah"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"roles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"editor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reviewer"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You want to document the expected structure or validate future responses.&lt;/p&gt;

&lt;p&gt;Writing a JSON Schema manually is straightforward for small objects, but it becomes tedious when the payload contains deeply nested objects and arrays.&lt;/p&gt;

&lt;p&gt;A schema generator can infer a starting point from sample JSON.&lt;/p&gt;

&lt;p&gt;For example, it can identify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt; as an integer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt; as a string&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;active&lt;/code&gt; as a boolean&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;roles&lt;/code&gt; as an array of strings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One important caveat: &lt;strong&gt;a sample doesn't describe every possible valid payload.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;name&lt;/code&gt; can sometimes be &lt;code&gt;null&lt;/code&gt;, or if some fields are optional, you may need to adjust the generated schema. Treat generated schemas as a starting point, not unquestionable truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Validating JSON Against a Schema
&lt;/h2&gt;

&lt;p&gt;Generating a schema solves only half the problem. You may also need to check whether an incoming payload follows it.&lt;/p&gt;

&lt;p&gt;Imagine your application expects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sarah"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the API returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sarah"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"28"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The value looks reasonable, but &lt;code&gt;age&lt;/code&gt; is a string rather than a number.&lt;/p&gt;

&lt;p&gt;This difference can cause unexpected behavior in applications that rely on strict types.&lt;/p&gt;

&lt;p&gt;JSON Schema validation helps identify these mismatches before they become harder-to-debug application errors.&lt;/p&gt;

&lt;p&gt;It's useful for API integration, test data, configuration validation, and checking payloads before processing them.&lt;/p&gt;

&lt;p&gt;For production systems, validation should also happen at the appropriate application boundary—not only in a browser-based utility.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Converting JSON to XML (And Back)
&lt;/h2&gt;

&lt;p&gt;JSON is common in modern APIs, but XML still appears in legacy integrations, enterprise systems, configuration formats, and some external services.&lt;/p&gt;

&lt;p&gt;When two systems expect different formats, you need a conversion step.&lt;/p&gt;

&lt;p&gt;A converter can handle common structures automatically, but JSON and XML don't represent data in exactly the same way.&lt;/p&gt;

&lt;p&gt;For example, XML has attributes, namespaces, and mixed text content. JSON doesn't have direct equivalents for all these concepts.&lt;/p&gt;

&lt;p&gt;Arrays and repeated XML elements can also require explicit conversion rules.&lt;/p&gt;

&lt;p&gt;For that reason, always inspect the output when converting complex documents. A successful conversion doesn't necessarily mean the original structure has been preserved perfectly.&lt;/p&gt;




&lt;h2&gt;
  
  
  One small improvement to your JSON workflow
&lt;/h2&gt;

&lt;p&gt;For occasional tasks, a short script is often enough. For recurring tasks, dedicated tools can save time and reduce repetitive work.&lt;/p&gt;

&lt;p&gt;I've been building a browser-based toolkit called &lt;a href="https://myjsonpal.com" rel="noopener noreferrer"&gt;MyJSONPal&lt;/a&gt; that brings these workflows together.&lt;/p&gt;

&lt;p&gt;It includes JSON formatting and repair, conversion tools, TypeScript and Zod generation, and newer tools for structural comparison, JSONPath queries, schema generation, schema validation, and JSON/XML conversion.&lt;/p&gt;

&lt;p&gt;One design decision I care about is privacy: the tools are designed to process data locally in the browser rather than uploading JSON to a server.&lt;/p&gt;

&lt;p&gt;As always, verify a tool's behavior and privacy claims before pasting production data, API tokens, or other sensitive information into it.&lt;/p&gt;

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

&lt;p&gt;JSON itself is rarely the difficult part of backend development. The friction comes from repeatedly inspecting, comparing, transforming, and validating it.&lt;/p&gt;

&lt;p&gt;A few practical techniques can make these tasks easier:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use structural diffs instead of manually comparing large payloads.&lt;/li&gt;
&lt;li&gt;Use JSONPath to extract values from nested documents.&lt;/li&gt;
&lt;li&gt;Generate schemas to reduce repetitive setup work.&lt;/li&gt;
&lt;li&gt;Validate payloads to catch type and structure mismatches early.&lt;/li&gt;
&lt;li&gt;Check conversion rules when moving between JSON and XML.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These small improvements can save time during debugging and integration work—and let you spend more time building the actual application.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I Built a Tool to Turn Messy Bank Statement PDFs Into Spreadsheets</title>
      <dc:creator>Aftan Ahmad</dc:creator>
      <pubDate>Sat, 03 Oct 2026 14:00:25 +0000</pubDate>
      <link>https://dev.to/aftandevelops/i-built-a-tool-to-turn-messy-bank-statement-pdfs-into-spreadsheets-1hgh</link>
      <guid>https://dev.to/aftandevelops/i-built-a-tool-to-turn-messy-bank-statement-pdfs-into-spreadsheets-1hgh</guid>
      <description>&lt;h2&gt;
  
  
  I Built a Browser-Based PDF Bank Statement Parser
&lt;/h2&gt;

&lt;p&gt;I recently built and launched &lt;strong&gt;SheetParse&lt;/strong&gt;, a browser-based tool that converts bank statement PDFs into spreadsheet-ready data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sheetparse.com" rel="noopener noreferrer"&gt;https://sheetparse.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The idea started with a simple problem: PDF is a great format for reading a bank statement, but it's a pretty terrible format when you actually want to work with the transaction data.&lt;/p&gt;

&lt;p&gt;If you need to analyze, filter, reconcile, or move the transactions into Excel, you quickly end up dealing with manual copy-pasting or unreliable PDF converters.&lt;/p&gt;

&lt;p&gt;So I decided to build my own solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  The interesting part: bank statements aren't standardized
&lt;/h2&gt;

&lt;p&gt;At first, I thought the problem would basically be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PDF → Extract text → Parse transactions → Excel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It turned out to be much messier.&lt;/p&gt;

&lt;p&gt;Different banks use completely different layouts.&lt;/p&gt;

&lt;p&gt;Some have separate debit and credit columns. Others combine them. Transaction descriptions can span multiple lines. Headers and footers can appear between transactions. Some PDFs contain actual text, while others are essentially scanned images.&lt;/p&gt;

&lt;p&gt;So the actual pipeline looks more like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PDF
 ↓
Text extraction / OCR
 ↓
Statement detection
 ↓
Bank-specific parsing
 ↓
Transaction normalization
 ↓
Validation
 ↓
CSV / XLSX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  I decided to process everything locally
&lt;/h2&gt;

&lt;p&gt;One of the main decisions I made was to keep document processing in the browser whenever possible.&lt;/p&gt;

&lt;p&gt;Bank statements contain sensitive financial information, so I didn't particularly like the idea of requiring users to upload their documents to a random server just to convert them.&lt;/p&gt;

&lt;p&gt;With SheetParse, the document can be processed locally in the browser.&lt;/p&gt;

&lt;p&gt;That also means I don't need a large backend infrastructure just to process someone's PDF.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bank-specific parsers
&lt;/h2&gt;

&lt;p&gt;Another thing I learned is that trying to create one universal parser isn't necessarily the best approach.&lt;/p&gt;

&lt;p&gt;Instead, SheetParse has parsers designed around different statement formats, along with a generic parser for unsupported formats.&lt;/p&gt;

&lt;p&gt;The goal is to normalize everything into a consistent structure such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Date
Description
Debit
Credit
Balance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the data is normalized, generating CSV or XLSX becomes much easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  OCR is a different problem
&lt;/h2&gt;

&lt;p&gt;Text-based PDFs and scanned PDFs are very different.&lt;/p&gt;

&lt;p&gt;If a PDF contains actual text, extraction is relatively straightforward.&lt;/p&gt;

&lt;p&gt;But if every page is essentially an image, there isn't any transaction text to extract.&lt;/p&gt;

&lt;p&gt;That's where OCR becomes useful.&lt;/p&gt;

&lt;p&gt;SheetParse uses OCR as a fallback for these types of documents.&lt;/p&gt;

&lt;p&gt;The tradeoff is that OCR is slower and can introduce additional ambiguity, especially with things like numbers, dates and transaction descriptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extraction isn't enough
&lt;/h2&gt;

&lt;p&gt;One of the biggest things I learned while building this is that extracting rows isn't the same as extracting correct data.&lt;/p&gt;

&lt;p&gt;For financial documents, an incorrect transaction can be worse than a missing transaction because it can silently affect someone's calculations.&lt;/p&gt;

&lt;p&gt;So validation becomes important.&lt;/p&gt;

&lt;p&gt;Things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;duplicate transactions&lt;/li&gt;
&lt;li&gt;broken dates&lt;/li&gt;
&lt;li&gt;incorrect debit/credit values&lt;/li&gt;
&lt;li&gt;transactions split across lines&lt;/li&gt;
&lt;li&gt;repeated headers&lt;/li&gt;
&lt;li&gt;page boundaries&lt;/li&gt;
&lt;li&gt;running balances&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;all need to be considered.&lt;/p&gt;

&lt;p&gt;The parser needs to understand the structure of the statement rather than simply grabbing everything that looks like a row.&lt;/p&gt;

&lt;h2&gt;
  
  
  Column Studio
&lt;/h2&gt;

&lt;p&gt;I also wanted SheetParse to do more than simply extract the transactions and immediately export them.&lt;/p&gt;

&lt;p&gt;That's why I built Column Studio in SheetParse.&lt;/p&gt;

&lt;p&gt;After the data has been extracted, Column Studio lets you work with the resulting columns before exporting the final spreadsheet.&lt;/p&gt;

&lt;p&gt;Instead of having to take the raw output into another tool just to make small changes, you can prepare the dataset within SheetParse itself.&lt;/p&gt;

&lt;p&gt;The idea is to make the workflow closer to:&lt;/p&gt;

&lt;p&gt;PDF&lt;br&gt;
 ↓&lt;br&gt;
Extract&lt;br&gt;
 ↓&lt;br&gt;
Clean / organize columns&lt;br&gt;
 ↓&lt;br&gt;
Review&lt;br&gt;
 ↓&lt;br&gt;
Export&lt;/p&gt;

&lt;p&gt;This became particularly useful because different people want different spreadsheet structures.&lt;/p&gt;

&lt;p&gt;Someone might only need:&lt;/p&gt;

&lt;p&gt;Date | Description | Amount&lt;/p&gt;

&lt;p&gt;while another workflow might need:&lt;/p&gt;

&lt;p&gt;Date | Description | Debit | Credit | Balance&lt;/p&gt;

&lt;p&gt;Rather than forcing one output format on everyone, Column Studio gives the user more control over the extracted dataset.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why build it in the browser?
&lt;/h2&gt;

&lt;p&gt;There were a few reasons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privacy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The document doesn't have to be uploaded to a backend just for parsing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Infrastructure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There isn't a document-processing server running for every conversion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simplicity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The application can remain relatively lightweight.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Client-side processing reduces the infrastructure required to operate the service.&lt;/p&gt;

&lt;p&gt;There are obviously tradeoffs too. Large PDFs and OCR can consume significant CPU and memory in the browser, so performance is something I'm continuing to work on.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;The biggest lesson wasn't really about PDF parsing.&lt;/p&gt;

&lt;p&gt;It was that real-world documents are messy.&lt;/p&gt;

&lt;p&gt;A parser can work perfectly against ten sample PDFs and then encounter a completely different layout in the eleventh.&lt;/p&gt;

&lt;p&gt;That's why supporting more banks isn't simply a matter of adding another parser. Each format needs representative documents, edge cases and regression tests.&lt;/p&gt;

&lt;p&gt;I'm now much more interested in the reliability and validation side of document processing than I was when I started the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  SheetParse is live
&lt;/h2&gt;

&lt;p&gt;The first public version is now available:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://sheetparse.com" rel="noopener noreferrer"&gt;https://sheetparse.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It currently supports multiple bank statement formats, a generic parser, and OCR fallback for scanned PDFs.&lt;/p&gt;

&lt;p&gt;It's still an early project, but it's something I've wanted to build for a while, and it's finally out in the wild.&lt;/p&gt;

&lt;p&gt;If you've worked with PDF parsing, OCR, financial data extraction, or document processing, I'd be interested to hear how you've approached similar problems.&lt;/p&gt;

&lt;p&gt;What are some of the weirdest PDF formats you've had to deal with?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>software</category>
    </item>
    <item>
      <title>Why Your JSON Tools Freeze (And How We Fixed It with Web Workers)</title>
      <dc:creator>Aftan Ahmad</dc:creator>
      <pubDate>Fri, 07 Aug 2026 14:01:20 +0000</pubDate>
      <link>https://dev.to/aftandevelops/why-your-json-tools-freeze-and-how-we-fixed-it-with-web-workers-58l1</link>
      <guid>https://dev.to/aftandevelops/why-your-json-tools-freeze-and-how-we-fixed-it-with-web-workers-58l1</guid>
      <description>&lt;p&gt;If you’ve ever pasted a 15MB JSON file into a browser-based formatter, you’ve likely seen it: the screen freezes, typing lags, the browser throws an "Aw, Snap!" error, or the fan spins up like a jet engine.&lt;/p&gt;

&lt;p&gt;The culprit isn't JavaScript being slow—it’s &lt;strong&gt;blocking the UI thread&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When you run &lt;code&gt;JSON.parse()&lt;/code&gt;, complex regex replacements, or type generation on the main thread, you block rendering, user inputs, and animations. &lt;/p&gt;

&lt;p&gt;In this article, we’ll look at how we built &lt;a href="https://myjsonpal.com/" rel="noopener noreferrer"&gt;MyJSONPal&lt;/a&gt;—a client-side JSON and data studio—to process multi-megabyte payloads instantly without freezing the browser using &lt;strong&gt;React 19&lt;/strong&gt;, &lt;strong&gt;CodeMirror 6&lt;/strong&gt;, and &lt;strong&gt;Web Workers&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution: Off-Main-Thread Processing
&lt;/h2&gt;

&lt;p&gt;To keep the editor buttery smooth, we need to offload heavy computation to a background thread using a &lt;strong&gt;Web Worker&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Main Thread ] ----&amp;gt; postMessage(JSON) ----&amp;gt; [ Web Worker ]

CodeMirror / UI                               AST Auto-Fix / Conversions
      │                                                │
      └────────── Receive Output Back ────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By decoupling computation from rendering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The editor remains interactive at &lt;strong&gt;60 FPS&lt;/strong&gt; while background work happens.&lt;/li&gt;
&lt;li&gt;Heavy processing never blocks typing or scrolling.&lt;/li&gt;
&lt;li&gt;Large payloads are processed in parallel with the UI lifecycle.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step-by-Step Architecture
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Define a Unified Processing Contract
&lt;/h3&gt;

&lt;p&gt;To keep workers predictable and type-safe, create a shared contract for all inputs and outputs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// types.ts&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;TargetFormat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;csv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yaml&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;typescript&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sql&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;TaskInput&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;format&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;minify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fix&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;convert&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;targetFormat&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;TargetFormat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;indentation&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;TaskResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;line&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;column&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nl"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;originalBytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;outputBytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;timeMs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;h3&gt;
  
  
  2. Create the Worker Task Processor
&lt;/h3&gt;

&lt;p&gt;Inside &lt;code&gt;worker.ts&lt;/code&gt;, listen for incoming messages, execute pure processing logic, and return the result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// worker.ts&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;processJsonPayload&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="s1"&gt;./jsonProcessor&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TaskInput&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="s1"&gt;./types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MessageEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TaskInput&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;processJsonPayload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;endTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;metrics&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;timeMs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endTime&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;startTime&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="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Processing failed&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. Build a Worker Client with Fallback Support
&lt;/h3&gt;

&lt;p&gt;Not every environment handles Web Workers the same way. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server-side rendering (SSR)&lt;/li&gt;
&lt;li&gt;Embedded webviews&lt;/li&gt;
&lt;li&gt;Restricted browser environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Always provide a fallback path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// workerClient.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TaskInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TaskResult&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="s1"&gt;./types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;workerInstance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Worker&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getWorker&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Worker&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;workerInstance&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;workerInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./worker.ts&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;module&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="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;workerInstance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;executeTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TaskInput&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TaskResult&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getWorker&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Primary path: execute off-main-thread&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;worker&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;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MessageEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TaskResult&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Fallback path: lazy-load on main thread&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;processJsonPayload&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./jsonProcessor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;processJsonPayload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&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;h3&gt;
  
  
  4. Connect It to React &amp;amp; CodeMirror 6
&lt;/h3&gt;

&lt;p&gt;Now wire asynchronous processing into your editor using debouncing to avoid flooding worker threads on every keystroke.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// EditorWorkspace.tsx&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;,&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="s1"&gt;react&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;executeTask&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="s1"&gt;./workerClient&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;const&lt;/span&gt; &lt;span class="nx"&gt;EditorWorkspace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;inputCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setInputCode&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;outputCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setOutputCode&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isProcessing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsProcessing&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleTransform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&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="nf"&gt;setIsProcessing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;executeTask&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;convert&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;targetFormat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;typescript&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setOutputCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;setIsProcessing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&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="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;handleTransform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputCode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;150&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timer&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;inputCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleTransform&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"grid grid-cols-2 gap-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;textarea&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputCode&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setInputCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Paste JSON here..."&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"relative"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isProcessing&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"absolute top-2 right-2 text-xs"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Processing...
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;outputCode&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;h3&gt;
  
  
  Bonus: The "Magic" Auto-Repair Pattern
&lt;/h3&gt;

&lt;p&gt;Moving processing into a worker unlocks CPU budget for automatic JSON repair without affecting UI responsiveness.&lt;/p&gt;

&lt;p&gt;For example, you can handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Trailing commas&lt;/li&gt;
&lt;li&gt;Single quotes&lt;/li&gt;
&lt;li&gt;JavaScript comments&lt;/li&gt;
&lt;li&gt;Python literals (&lt;code&gt;True&lt;/code&gt;, &lt;code&gt;False&lt;/code&gt;, &lt;code&gt;None&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Unquoted object keys
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// jsonFixer.ts&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;repairJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dirtyJson&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dirtyJson&lt;/span&gt;
    &lt;span class="c1"&gt;// Remove UTF-8 BOM&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\u&lt;/span&gt;&lt;span class="sr"&gt;FEFF/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Replace Python/JS literals&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/:&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*True&lt;/span&gt;&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;: true&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/:&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*False&lt;/span&gt;&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;: false&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/:&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*None&lt;/span&gt;&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;: null&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Remove JS comments&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\/\*[\s\S]&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;?\*\/&lt;/span&gt;&lt;span class="sr"&gt;|&lt;/span&gt;&lt;span class="se"&gt;([^\\&lt;/span&gt;&lt;span class="sr"&gt;:&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;|^&lt;/span&gt;&lt;span class="se"&gt;)\/\/&lt;/span&gt;&lt;span class="sr"&gt;.*$/gm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Fix unquoted keys&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;([&lt;/span&gt;&lt;span class="sr"&gt;{,&lt;/span&gt;&lt;span class="se"&gt;]\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)([&lt;/span&gt;&lt;span class="sr"&gt;a-zA-Z0-9_&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;?)\s&lt;/span&gt;&lt;span class="sr"&gt;*:/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$1"$2":&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Convert single quotes&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="sr"&gt;/'&lt;/span&gt;&lt;span class="se"&gt;([^&lt;/span&gt;&lt;span class="sr"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\\]&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;(\\&lt;/span&gt;&lt;span class="sr"&gt;.&lt;/span&gt;&lt;span class="se"&gt;[^&lt;/span&gt;&lt;span class="sr"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\\]&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;'/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;"$1"&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Remove trailing commas&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/,&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;([&lt;/span&gt;&lt;span class="sr"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\]])&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$1&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;p&gt;Because this logic runs inside a worker, even large malformed files can be repaired without causing frame drops or blocking the UI.&lt;/p&gt;




&lt;h2&gt;
  
  
  Results &amp;amp; Takeaways
&lt;/h2&gt;

&lt;p&gt;By moving payload processing, AST repair, and type generation into a Web Worker architecture, we achieved three major improvements:&lt;/p&gt;

&lt;h3&gt;
  
  
  🚀 Zero Thread Blocking
&lt;/h3&gt;

&lt;p&gt;Typing, scrolling, and editor interactions remain smooth at &lt;strong&gt;60 FPS&lt;/strong&gt;, regardless of JSON file size.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔒 True Data Privacy
&lt;/h3&gt;

&lt;p&gt;All processing happens entirely in the browser. No payloads are uploaded, stored, or transmitted to remote servers.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚡ Instant Feedback
&lt;/h3&gt;

&lt;p&gt;Even large datasets can be transformed in under &lt;strong&gt;20ms&lt;/strong&gt; without freezing the browser.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;You can try this exact architecture in production with &lt;strong&gt;&lt;a href="https://myjsonpal.com/" rel="noopener noreferrer"&gt;MyJSONPal&lt;/a&gt;&lt;/strong&gt; — a free, privacy-first JSON studio built with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Astro&lt;/li&gt;
&lt;li&gt;React 19&lt;/li&gt;
&lt;li&gt;CodeMirror 6&lt;/li&gt;
&lt;li&gt;Tailwind CSS v4&lt;/li&gt;
&lt;li&gt;Web Workers&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Web Workers aren't just an optimization anymore—they're a requirement for modern browser-based developer tools handling large datasets.&lt;/p&gt;

&lt;p&gt;If your users are working with multi-megabyte files, schema generation, AST transforms, or code conversion, moving heavy processing off the main thread is one of the highest-impact performance improvements you can make.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How are you handling heavy processing in your client-side applications?&lt;/strong&gt; Let me know in the comments 👇&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>programming</category>
      <category>frontend</category>
    </item>
    <item>
      <title>I got tired of online JSON tools crashing on syntax errors and conversions, so I built a local-first repair engine</title>
      <dc:creator>Aftan Ahmad</dc:creator>
      <pubDate>Sat, 01 Aug 2026 15:52:52 +0000</pubDate>
      <link>https://dev.to/aftandevelops/i-got-tired-of-online-json-tools-crashing-on-syntax-errors-and-conversions-so-i-built-a-jk8</link>
      <guid>https://dev.to/aftandevelops/i-got-tired-of-online-json-tools-crashing-on-syntax-errors-and-conversions-so-i-built-a-jk8</guid>
      <description>&lt;p&gt;Every developer uses online JSON formatters daily to debug API responses, inspect log files, or check database dumps. &lt;/p&gt;

&lt;p&gt;But standard JSON formatters come with two recurring papercuts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Parser Fragility:&lt;/strong&gt; Standard &lt;code&gt;JSON.parse&lt;/code&gt; is unforgiving. A single trailing comma, missing quote, or Python-style &lt;code&gt;True&lt;/code&gt;/&lt;code&gt;False&lt;/code&gt; boolean completely crashes the formatter, forcing you to fix it manually character by character.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Privacy Risks:&lt;/strong&gt; Pasting production payloads, JWTs, or environment variables onto unencrypted, third-party server-side formatters is a security risk waiting to happen.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To solve both issues for my own workflow, I built &lt;strong&gt;&lt;a href="https://myjsonpal.com" rel="noopener noreferrer"&gt;MyJSONPal&lt;/a&gt;&lt;/strong&gt;—a 100% client-side JSON studio designed for speed, privacy, and auto-repair.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ 1. Magic AST Auto-Repair
&lt;/h2&gt;

&lt;p&gt;Instead of failing on malformed JSON, MyJSONPal uses a client-side parsing engine that automatically cleans common syntax issues before formatting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trailing Commas:&lt;/strong&gt; Strips trailing commas from arrays and objects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quote Normalization:&lt;/strong&gt; Converts single-quoted strings and unquoted object keys into valid double-quoted JSON.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language Equivalents:&lt;/strong&gt; Automatically normalizes Python booleans (&lt;code&gt;True&lt;/code&gt;/&lt;code&gt;False&lt;/code&gt;) and &lt;code&gt;None&lt;/code&gt; values into standard JSON syntax (&lt;code&gt;true&lt;/code&gt;/&lt;code&gt;false&lt;/code&gt;/&lt;code&gt;null&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔒 2. 100% In-Browser Privacy
&lt;/h2&gt;

&lt;p&gt;Security shouldn't be an afterthought when inspecting API responses. &lt;/p&gt;

&lt;p&gt;MyJSONPal runs &lt;strong&gt;entirely in your browser&lt;/strong&gt;. There are zero server network calls, zero tracking logs, and zero remote data stores. Your production payloads and tokens never leave your local machine.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛡️ 3. One-Click Type &amp;amp; Schema Generation
&lt;/h2&gt;

&lt;p&gt;When integrating APIs, formatting the JSON is only step one. You usually need type definitions next.&lt;/p&gt;

&lt;p&gt;MyJSONPal instantly infers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zod Schemas:&lt;/strong&gt; Generates ready-to-use &lt;code&gt;z.infer&lt;/code&gt; schemas for immediate runtime validation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript Interfaces:&lt;/strong&gt; Converts raw payloads into clean TS types.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Exports:&lt;/strong&gt; Converts JSON directly to CSV (RFC 4180 compliant) and YAML.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Additional Core Features
&lt;/h2&gt;

&lt;p&gt;Beyond the &lt;strong&gt;AST Auto-Repair&lt;/strong&gt;, &lt;strong&gt;Client-Side Privacy&lt;/strong&gt;, and &lt;strong&gt;Type Generation&lt;/strong&gt; already covered, here are the additional core features built into &lt;strong&gt;MyJSONPal&lt;/strong&gt; that make it a complete JSON workbench.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Advanced Structural Transformations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Recursive Key Sorting&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instantly sorts all keys in nested objects alphabetically (&lt;strong&gt;A–Z&lt;/strong&gt; or &lt;strong&gt;Z–A&lt;/strong&gt;) to standardize payloads before committing or comparing.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Smart Minification &amp;amp; Formatting&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Switch between minifying payloads into a single line for API calls or formatting them with customizable tab or space indentation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Key Extraction &amp;amp; Dot-Notation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flatten complex nested structures and extract all keys along with their precise dot-notation paths (e.g., &lt;code&gt;user.profile.settings.theme&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Deep Data Conversion Pipeline
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Bi-directional Conversions&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Convert JSON seamlessly into &lt;strong&gt;YAML&lt;/strong&gt;, &lt;strong&gt;CSV (RFC 4180)&lt;/strong&gt;, or &lt;strong&gt;XML&lt;/strong&gt;, and vice versa.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Base64 &amp;amp; Stringify Tools&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decode Base64 payloads (such as JWTs) directly into structured JSON, or escape raw JSON into stringified literals ready for use in code variables.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Visual Exploration &amp;amp; Search
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Interactive Collapsible Tree View&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate massive multi-megabyte payloads with expandable and collapsible nodes, making it easy to inspect deeply nested responses.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Live Search &amp;amp; Path Finder&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search for specific keys, values, or array indices across large datasets without slowing down the editor.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Performance &amp;amp; UX Foundations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Web Worker Architecture&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Heavy processing runs inside isolated background threads, keeping the UI responsive even when working with large database exports.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Shared Workspace State&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Paste your JSON once and switch between validators, converters, and generators without losing your input or re-uploading files.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;VsCode Styled Editor&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enjoy syntax highlighting, error-line navigation, dark/light theme support, and offline-first functionality.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🚀 Try It Out
&lt;/h2&gt;

&lt;p&gt;It's completely free to use with no account required:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://myjsonpal.com" rel="noopener noreferrer"&gt;myjsonpal.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’d love to hear your feedback! What JSON edge cases or converter options would make your daily debugging workflow easier? Let me know in the comments below!&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>software</category>
      <category>tools</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
