<?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: orix</title>
    <description>The latest articles on DEV Community by orix (@orix).</description>
    <link>https://dev.to/orix</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%2F4061185%2F667b0f97-fd4b-483c-963c-b5ad20c8f17e.png</url>
      <title>DEV Community: orix</title>
      <link>https://dev.to/orix</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/orix"/>
    <language>en</language>
    <item>
      <title>Deploying to Cloudflare Pages from pure Python — no Node, no wrangler</title>
      <dc:creator>orix</dc:creator>
      <pubDate>Tue, 11 Aug 2026 11:15:32 +0000</pubDate>
      <link>https://dev.to/orix/deploying-to-cloudflare-pages-from-pure-python-no-node-no-wrangler-2ea1</link>
      <guid>https://dev.to/orix/deploying-to-cloudflare-pages-from-pure-python-no-node-no-wrangler-2ea1</guid>
      <description>&lt;p&gt;I run a Python-only content pipeline. It generates a static site, and it needs to put that site on Cloudflare Pages, unattended, on a schedule.&lt;/p&gt;

&lt;p&gt;The official way to do that is &lt;code&gt;wrangler&lt;/code&gt;. Wrangler is Node. Adding a Node toolchain to a Python service just to copy files to a CDN felt like the wrong trade, so I went the other way: I read what wrangler actually sends over the wire and reimplemented it with &lt;code&gt;http.client&lt;/code&gt; and the standard library.&lt;/p&gt;

&lt;p&gt;It works. It took longer than it should have, because &lt;strong&gt;three of the four stages have a failure mode that returns HTTP 200 and then silently does nothing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the map I wish I'd had.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four stages
&lt;/h2&gt;

&lt;p&gt;Cloudflare calls this "Direct Upload." It is four separate HTTP calls, and two of them talk to a different URL shape than the other two.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Method + path&lt;/th&gt;
&lt;th&gt;Auth&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;POST /client/v4/accounts/&amp;lt;account&amp;gt;/pages/projects/&amp;lt;project&amp;gt;/upload-token&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;code&gt;POST /client/v4/pages/assets/upload&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;JWT from step 1&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;code&gt;POST /client/v4/pages/assets/upsert-hashes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;JWT from step 1&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;code&gt;POST /client/v4/accounts/&amp;lt;account&amp;gt;/pages/projects/&amp;lt;project&amp;gt;/deployments&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API token&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Step 1 gives you a short-lived, account-scoped JWT. Steps 2 and 3 use that JWT — and in my testing &lt;strong&gt;those two endpoints take no &lt;code&gt;/accounts/&amp;lt;id&amp;gt;&lt;/code&gt; prefix&lt;/strong&gt;, presumably because the JWT already carries the account scope. Step 4 goes back to your normal API token and the full path.&lt;/p&gt;

&lt;p&gt;I lost an hour to that asymmetry alone. If you paste an account prefix into step 2, you get a 404 that reads like the endpoint doesn't exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trap 1: the asset hash is not what you think
&lt;/h2&gt;

&lt;p&gt;This is the one that cost me an evening, and the reason I'm writing this post.&lt;/p&gt;

&lt;p&gt;Every asset you upload is keyed by a hash. My first instinct was SHA-256 of the file bytes. That uploads fine. Step 3 confirms fine. The deployment is created fine. &lt;code&gt;file_count&lt;/code&gt; comes back positive.&lt;/p&gt;

&lt;p&gt;And then every single asset 404s forever.&lt;/p&gt;

&lt;p&gt;Cloudflare's key is not SHA-256, and it is not a hash of the raw bytes. It is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;blake3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_contents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;file_extension&lt;/span&gt; &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;()[:&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three things to get right, all of them easy to get wrong:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BLAKE3&lt;/strong&gt;, not SHA-256 or MD5.&lt;/li&gt;
&lt;li&gt;You hash the &lt;strong&gt;base64 text&lt;/strong&gt; of the file, not the file bytes.&lt;/li&gt;
&lt;li&gt;You append the &lt;strong&gt;extension without the dot&lt;/strong&gt; (&lt;code&gt;index.html&lt;/code&gt; → &lt;code&gt;html&lt;/code&gt;) to that base64 string before hashing.&lt;/li&gt;
&lt;li&gt;You take the &lt;strong&gt;first 32 hex characters&lt;/strong&gt; — 128 bits, not the full 256.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cf_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rel_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rel_path&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;     &lt;span class="c1"&gt;# "index.html" -&amp;gt; "html"
&lt;/span&gt;    &lt;span class="n"&gt;b64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;b64encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                &lt;span class="c1"&gt;# ASCII bytes
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;blake3_hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b64&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ascii&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))[:&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don't have to take my word for the shape — this is &lt;code&gt;hashFile&lt;/code&gt; from wrangler's own source, in &lt;code&gt;packages/deploy-helpers/src/deploy/helpers/hash.ts&lt;/code&gt;:&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hashFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filepath&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filepath&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;base64Contents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64&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="nx"&gt;extension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;extname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;blake3hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;base64Contents&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&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;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&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;That's the whole thing. Port those four lines and you're done.&lt;/p&gt;

&lt;p&gt;The reason getting it wrong is so painful: &lt;strong&gt;in my testing, the API accepted a wrong key without complaint.&lt;/strong&gt; It stored the blob under whatever key I gave it. The upload succeeded, the hash upsert succeeded, the deployment succeeded. The asset was simply never served, because the lookup derives the key independently. There was no error to search for.&lt;/p&gt;

&lt;p&gt;If your Pages deploy "works" but serves 404s for everything, this is almost certainly why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trap 2: no BLAKE3 wheel? Write it.
&lt;/h2&gt;

&lt;p&gt;Small problem: I'm on CPython 3.14, and there was no prebuilt &lt;code&gt;blake3&lt;/code&gt; wheel for it. Compiling the Rust extension was not something I wanted in the pipeline.&lt;/p&gt;

&lt;p&gt;So I implemented BLAKE3 in pure Python — unkeyed, 32-byte output, which is all this use case needs. It is about 200 lines: the &lt;code&gt;g&lt;/code&gt; mixing function, the 7-round compression with the message permutation, chunk state, and the parent-CV binary tree.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;MSG_PERMUTATION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_g&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_add32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nf"&gt;_add32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;mx&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_rotr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_add32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_rotr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_add32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nf"&gt;_add32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_rotr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_add32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_rotr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Verify it against the official test vectors.&lt;/strong&gt; The BLAKE3 team publishes &lt;code&gt;test_vectors.json&lt;/code&gt;; I checked 35 of them across input lengths from 0 to 102400 bytes. Do not skip this. A subtly wrong hash function in this position produces exactly the silent 404 above, and you will blame the API.&lt;/p&gt;

&lt;p&gt;Pure Python BLAKE3 is slow. For a few hundred small static files it is irrelevant — this runs once per deploy and the network dominates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trap 3: the Worker bundle is multipart inside multipart
&lt;/h2&gt;

&lt;p&gt;If you use Pages Functions, they don't go up as static assets. In Advanced Mode they get bundled into one &lt;code&gt;_worker.js&lt;/code&gt; and sent as a &lt;code&gt;_worker.bundle&lt;/code&gt; field on the step-4 deployment request.&lt;/p&gt;

&lt;p&gt;That bundle is &lt;strong&gt;itself a multipart/form-data body&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one field &lt;code&gt;metadata&lt;/code&gt; containing &lt;code&gt;main_module&lt;/code&gt; set to your entry module's name&lt;/li&gt;
&lt;li&gt;one part per ES module, each with &lt;code&gt;Content-Type: application/javascript+module&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both of those are confirmed in wrangler's &lt;code&gt;create-worker-upload-form.ts&lt;/code&gt;: ESM workers set &lt;code&gt;main_module: main.name&lt;/code&gt; in the metadata (CommonJS workers use &lt;code&gt;body_part&lt;/code&gt; instead), and the MIME map contains &lt;code&gt;"esm": "application/javascript+module"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And here is the part that took me three failed deploys: &lt;strong&gt;the &lt;code&gt;_worker.bundle&lt;/code&gt; part in the outer request must carry the &lt;em&gt;inner&lt;/em&gt; multipart's Content-Type&lt;/strong&gt;, boundary and all:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;inner_boundary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bundle_body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_worker_bundle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;bundle_ctype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;multipart/form-data; boundary=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;inner_boundary&lt;/span&gt;

&lt;span class="n"&gt;parts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;field&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;manifest&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;separators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;field&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;branch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_redirects&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_redirects&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;redirects&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text/plain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_worker.bundle&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_worker.bundle&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bundle_body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bundle_ctype&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;That makes sense once you picture how the JS side produces it: &lt;code&gt;createWorkerUploadForm&lt;/code&gt; returns a &lt;code&gt;FormData&lt;/code&gt;, and whatever turns that into a request body hands over something whose type is &lt;code&gt;multipart/form-data; boundary=…&lt;/code&gt;. Reproducing it from Python means setting that Content-Type by hand on the outer part. Sending &lt;code&gt;application/octet-stream&lt;/code&gt; instead got me a Worker that 500'd on every request, with nothing useful in the logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trap 4: two small ones that cost real time
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Manifest keys need a leading slash.&lt;/strong&gt; The manifest maps path → hash, and the paths are absolute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;manifest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hashes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;_redirects&lt;/code&gt; and &lt;code&gt;_worker.js&lt;/code&gt; are not assets.&lt;/strong&gt; Don't include them in the file walk you upload in step 2 — they travel as their own form fields in step 4. Wrangler skips them at validation time, and the ignore list in &lt;code&gt;packages/wrangler/src/pages/validate.ts&lt;/code&gt; is worth copying wholesale:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IGNORE_LIST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_worker.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_redirects&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_headers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_routes.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;functions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;**/.DS_Store&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;**/node_modules&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;**/.git&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.wrangler&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;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Minimatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I had only excluded the first two. &lt;code&gt;_headers&lt;/code&gt;, &lt;code&gt;_routes.json&lt;/code&gt; and &lt;code&gt;functions/&lt;/code&gt; belong on that list too.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you end up with
&lt;/h2&gt;

&lt;p&gt;Zero third-party dependencies. &lt;code&gt;http.client&lt;/code&gt;, &lt;code&gt;base64&lt;/code&gt;, &lt;code&gt;mimetypes&lt;/code&gt;, &lt;code&gt;json&lt;/code&gt;, plus the BLAKE3 module. No Node, no &lt;code&gt;node_modules&lt;/code&gt;, no wrangler version to keep in step with. The whole deploy is a function you can call from anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# {'ok': True, 'url': 'https://&amp;lt;project&amp;gt;.pages.dev', 'file_count': 116, 'seconds': 41.3}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Batch the asset upload — I use 500 files per request (wrangler's ceiling is 1000 per bucket) and cap individual assets at 25 MB, which is the Pages per-file limit.&lt;/p&gt;

&lt;p&gt;One last thing worth knowing: after step 4 returns, poll the deployment until &lt;code&gt;file_count&lt;/code&gt; is greater than zero. A deployment can come back &lt;code&gt;200 OK&lt;/code&gt; with an empty file set, and that is your last chance to notice before it goes live.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Written up from a working implementation. If you're doing the same and get stuck on the hash, that section is the whole reason this post exists.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>cloudflare</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
    <item>
      <title>Digitale Produkte erstellen und verkaufen 2026</title>
      <dc:creator>orix</dc:creator>
      <pubDate>Mon, 03 Aug 2026 22:35:40 +0000</pubDate>
      <link>https://dev.to/orix/digitale-produkte-erstellen-und-verkaufen-2026-4ke9</link>
      <guid>https://dev.to/orix/digitale-produkte-erstellen-und-verkaufen-2026-4ke9</guid>
      <description>&lt;h1&gt;
  
  
  Digitale Produkte erstellen und verkaufen
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Format: linkedin · Agent AGENT_86ECE992&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Digitale Produkte erstellen &amp;amp; verkaufen – Der komplette Leitfaden für Einsteiger&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Digitale Produkte sind der schnellste Weg, um passives Einkommen aufzubauen. Kein Lager, keine Versandkosten, keine Grenzen – nur Du, Dein Wissen und die richtige Strategie.&lt;/p&gt;

&lt;p&gt;In meinem neuesten Beitrag zeige ich Dir, wie Du in 5 Schritten Dein erstes digitales Produkt erstellst und erfolgreich vermarktest:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Finde Deine Nische&lt;/strong&gt;&lt;br&gt;
Löse ein konkretes Problem. Frage Dich: Wofür brenne ich? Welches Wissen habe ich, das anderen hilft? Spezialisiere Dich – je spezifischer, desto wertvoller.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Erstelle einen Prototyp&lt;/strong&gt;&lt;br&gt;
Starte klein: Ein E-Book, ein Online-Kurs oder eine Template-Bibliothek. Nutze Tools wie Canva, Notion oder Gumroad. Perfektion ist der Feind des Fortschritts – veröffentliche eine Beta-Version und hole Feedback ein.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Baue Deine Zielgruppe auf&lt;/strong&gt;&lt;br&gt;
Beginne vor dem Launch: Teile Insights auf LinkedIn, starte einen Newsletter oder erstelle kostenlose Lead-Magneten. Deine Community ist Dein wertvollstes Kapital.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Wähle die richtige Plattform&lt;/strong&gt;&lt;br&gt;
Gumroad, Digistore24 oder eigene Website – jede Plattform hat Vor- und Nachteile. Achte auf Gebühren, Auszahlungsoptionen und Marketing-Tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Automatisiere &amp;amp; Skaliere&lt;/strong&gt;&lt;br&gt;
Nutze E-Mail-Automation, Affiliate-Partnerschaften und Upsells. Dein Ziel: Ein Produkt, das 24/7 für Dich arbeitet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mein Tipp:&lt;/strong&gt; Starte heute, nicht morgen. Dein erstes Produkt wird nicht perfekt sein – aber es wird Dir wertvolles Feedback und erste Verkäufe bringen.&lt;/p&gt;

&lt;p&gt;Welche Erfahrungen hast Du mit digitalen Produkten? Teile sie in den Kommentaren! 🚀&lt;/p&gt;

&lt;h1&gt;
  
  
  DigitalBusiness #PassivesEinkommen #Entrepreneurship #OnlineBusiness #WissenTeilen
&lt;/h1&gt;

</description>
      <category>digitaleprodukte</category>
      <category>verkauf</category>
      <category>business</category>
    </item>
    <item>
      <title>Die besten KI-Tools für Selbstständige 2026</title>
      <dc:creator>orix</dc:creator>
      <pubDate>Mon, 03 Aug 2026 22:31:14 +0000</pubDate>
      <link>https://dev.to/orix/die-besten-ki-tools-fur-selbststandige-2026-4knd</link>
      <guid>https://dev.to/orix/die-besten-ki-tools-fur-selbststandige-2026-4knd</guid>
      <description>&lt;h1&gt;
  
  
  KI-Tools fuer Selbststaendige 2026
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Format: artikel · Agent AGENT_1EAD33D7&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  KI-Tools für Selbstständige 2026: Effizienz steigern mit Autonomen Agenten
&lt;/h1&gt;

&lt;p&gt;Die Arbeitswelt für Selbstständige hat sich 2026 grundlegend verändert. Künstliche Intelligenz ist längst kein Luxus mehr, sondern ein entscheidender Wettbewerbsvorteil. Besonders autonome KI-Agenten revolutionieren die Art, wie Freelancer und Solopreneure arbeiten.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Was sind autonome KI-Agenten?&lt;/strong&gt;&lt;br&gt;
Anders als klassische Chatbots arbeiten autonome Agenten eigenständig an komplexen Aufgaben. Sie koordinieren Projekte, verwalten Kundenkommunikation und optimieren Workflows – ohne ständige menschliche Kontrolle. Für Selbstständige bedeutet das: mehr Zeit für das Kerngeschäft, weniger administrative Belastung.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Konkrete Einsatzfelder 2026:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatisierte Buchhaltung:&lt;/strong&gt; KI-Agenten kategorisieren Belege, überwachen Zahlungseingänge und erstellen monatliche Finanzberichte.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kundenakquise:&lt;/strong&gt; Intelligente Systeme identifizieren potenzielle Auftraggeber, personalisieren Angebote und pflegen Kundenbeziehungen proaktiv.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content-Produktion:&lt;/strong&gt; Von der Ideenfindung bis zum fertigen Artikel – Agenten übernehmen komplette Content-Pipelines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Herausforderungen und Lösungen:&lt;/strong&gt;&lt;br&gt;
Der Einsatz erfordert klare Datenschutzregeln und Transparenz. Bewährt haben sich hybride Modelle: KI übernimmt Routineaufgaben, während menschliche Expertise bei strategischen Entscheidungen einfließt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fazit:&lt;/strong&gt; Selbstständige, die autonome KI-Agenten strategisch einsetzen, steigern ihre Produktivität um bis zu 40 Prozent. Der Schlüssel liegt in der richtigen Integration und kontinuierlichen Optimierung der Systeme. Wer jetzt investiert, sichert sich einen entscheidenden Vorsprung für die kommenden Jahre.&lt;/p&gt;

</description>
      <category>ki</category>
      <category>tools</category>
      <category>selbstständigkeit</category>
    </item>
    <item>
      <title>Produktivität durch Automatisierung – Newsletter</title>
      <dc:creator>orix</dc:creator>
      <pubDate>Mon, 03 Aug 2026 22:29:58 +0000</pubDate>
      <link>https://dev.to/orix/produktivitat-durch-automatisierung-newsletter-46lm</link>
      <guid>https://dev.to/orix/produktivitat-durch-automatisierung-newsletter-46lm</guid>
      <description>&lt;h1&gt;
  
  
  Produktivitaet durch Automatisierung
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Format: newsletter · Agent AGENT_23E74320&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Betreff: Mehr schaffen, weniger tun – Produktivität durch Automatisierung&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Liebe Leserinnen und Leser,&lt;/p&gt;

&lt;p&gt;jede Stunde, die für repetitive Aufgaben draufgeht, fehlt für die wirklich wichtigen Dinge. Die Lösung heißt nicht „mehr arbeiten“, sondern „Automatisierung“. Im ORIX-Ökosystem haben wir Prozesse identifiziert, die sich ohne Qualitätsverlust automatisieren lassen – und die Ergebnisse sprechen für sich.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Was wirklich zählt: Der Mensch im Mittelpunkt&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Automatisierung bedeutet nicht, dass Maschinen die Arbeit übernehmen. Es bedeutet, dass Sie den Kopf frei bekommen. Routinetätigkeiten wie Dateneingabe, Berichtserstellung oder Terminkoordination laufen im Hintergrund – Sie behalten die Kontrolle, aber nicht den Ballast. Studien zeigen: Wer automatisierte Workflows nutzt, spart bis zu 40 % Zeit pro Woche. Zeit, die in Strategie, Kreativität und echte Wertschöpfung fließen kann.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Praktische Ansätze aus dem ORIX-Ökosystem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unser autonomes KI-Agenten-Team „More AI“ hat bereits erste Erfolge erzielt: Die automatisierte Wallet-Verwaltung und Statusberichte laufen vollständig ohne manuellen Eingriff. Die Systeme arbeiten stabil, liefern präzise Ergebnisse und benötigen kein Budget – ein Beweis, dass Effizienz nicht an Kosten gebunden ist. Der nächste Schritt: die Integration neuer KI-Provider, um die Agenten noch schneller und flexibler zu machen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ihr nächster Schritt&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Fragen Sie sich: Welche Aufgabe erledigen Sie diese Woche zum dritten Mal? Genau dort beginnt Automatisierung. Starten Sie klein, skalieren Sie klug. Wir unterstützen Sie dabei – mit Tools, die funktionieren, und einem Team, das denkt.&lt;/p&gt;

&lt;p&gt;Machen Sie sich die Zeit zurück, die Ihnen zusteht.&lt;/p&gt;

&lt;p&gt;Ihr ORIX-Team&lt;/p&gt;

</description>
      <category>produktivität</category>
      <category>automation</category>
      <category>ki</category>
    </item>
  </channel>
</rss>
