<?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: Richard Ali</title>
    <description>The latest articles on DEV Community by Richard Ali (@raliworks).</description>
    <link>https://dev.to/raliworks</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%2F4157844%2F8083f1a0-32f0-47ca-8a15-092089e6a783.JPG</url>
      <title>DEV Community: Richard Ali</title>
      <link>https://dev.to/raliworks</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/raliworks"/>
    <language>en</language>
    <item>
      <title>I let Muse ship an app on SnoozeStack. Here's the whole thing.</title>
      <dc:creator>Richard Ali</dc:creator>
      <pubDate>Fri, 02 Oct 2026 17:48:36 +0000</pubDate>
      <link>https://dev.to/raliworks/i-let-muse-ship-an-app-on-snoozestack-heres-the-whole-thing-4pn4</link>
      <guid>https://dev.to/raliworks/i-let-muse-ship-an-app-on-snoozestack-heres-the-whole-thing-4pn4</guid>
      <description>&lt;h2&gt;
  
  
  Why I did this
&lt;/h2&gt;

&lt;p&gt;I created SnoozeStack — a backend platform with a specific bet: most developers don't have one app with a million users, they have ten apps with a hundred users each, and the infrastructure tax per project is what kills the other nine.&lt;/p&gt;

&lt;p&gt;I wanted to test out Meta's new Muse AI Assistant and thought having it start from zero and setup a working public site on SnoozeStack would be a great test. If the platform is actually agent-friendly, an agent should be able to drive it end to end.&lt;/p&gt;

&lt;h2&gt;
  
  
  What got built
&lt;/h2&gt;

&lt;p&gt;A guestbook app to test every layer that matters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Database:&lt;/strong&gt; a &lt;code&gt;signatures&lt;/code&gt; table (id, name, message, created_at), declared in a committed &lt;code&gt;schema.mjs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API:&lt;/strong&gt; a &lt;code&gt;guestbook&lt;/code&gt; function — &lt;code&gt;POST&lt;/code&gt; writes a row, &lt;code&gt;GET&lt;/code&gt; reads them back, newest first&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; a static site with a form that talks to the API on the same origin&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hosting:&lt;/strong&gt; all of it published as one immutable release to &lt;code&gt;muse-demo.snzzz.com&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/8GWr254_oco" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Sign up and log in
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ snoozestack user login
Logged in as richard+muse@raliworks.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI uses a browser device-code flow — it prints a code that you approve it in the browser. Muse drove the whole thing except it couldn't click the email confirmation link during signup only because I didn't grant it access to my email.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/1FnSrdQi8jQ" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: The project is a folder
&lt;/h2&gt;

&lt;p&gt;This is the part I care about most. The entire application — functions, schema, sites, capabilities — is one &lt;code&gt;project.toml&lt;/code&gt; that Muse can configure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[project]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"muse-demo"&lt;/span&gt;

&lt;span class="nn"&gt;[[functions]]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hello"&lt;/span&gt;
&lt;span class="py"&gt;entry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hello/index.ts"&lt;/span&gt;
&lt;span class="py"&gt;auth&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"optional"&lt;/span&gt;

&lt;span class="nn"&gt;[[functions]]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"guestbook"&lt;/span&gt;
&lt;span class="py"&gt;entry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"guestbook/index.ts"&lt;/span&gt;
&lt;span class="py"&gt;auth&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"optional"&lt;/span&gt;
&lt;span class="py"&gt;capabilities&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"db"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nn"&gt;[[sites]]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"www"&lt;/span&gt;
&lt;span class="py"&gt;dir&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"www"&lt;/span&gt;
&lt;span class="py"&gt;primary&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note &lt;code&gt;capabilities = ["db"]&lt;/code&gt;. Functions declare what they may reach, and undeclared capabilities simply don't exist inside the handler. The agent wrote this correctly on its first try.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: The schema is code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineTable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;snoozestack-js&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;signatures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defineTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;signatures&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;notNull&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;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;notNull&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;&lt;code&gt;schema build&lt;/code&gt; compiles it to a &lt;code&gt;schema.json&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: The function is the only thing that touches the database
&lt;/h2&gt;

&lt;p&gt;There is no client-facing table API, by design. The frontend can't query the database; it calls the function, and the function decides:&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="k"&gt;default&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;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;capabilities&lt;/span&gt;&lt;span class="p"&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;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&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;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;insert into signatures (id, name, message, created_at) values (?, ?, ?, ?)&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="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&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;60&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="nf"&gt;trim&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;280&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;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&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;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ok&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="nx"&gt;id&lt;/span&gt; &lt;span class="p"&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;rows&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;select id, name, message, created_at from signatures order by created_at desc limit 50&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;signatures&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rows&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;r&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;r&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;r&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="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;r&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="na"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;r&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="p"&gt;})),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plain SQL, parameterized, one statement per call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Run it all locally
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ snoozestack dev
muse-demo is running
  app   http://localhost:8788/          site "www", primary
  api   http://localhost:8787/guestbook   the new function
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One process: the site, the functions, and the database. The agent tested the round-trip before publishing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST localhost:8787/guestbook &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name":"Local Tester","message":"hello from dev"}'&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;:true,&lt;span class="s2"&gt;"id"&lt;/span&gt;:&lt;span class="s2"&gt;"c2d2429d-81a4-454c-b1db-05ca520e5b82"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; localhost:8787/guestbook
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"signatures"&lt;/span&gt;:[&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;:&lt;span class="s2"&gt;"c2d2429d…"&lt;/span&gt;,&lt;span class="s2"&gt;"name"&lt;/span&gt;:&lt;span class="s2"&gt;"Local Tester"&lt;/span&gt;,&lt;span class="s2"&gt;"message"&lt;/span&gt;:&lt;span class="s2"&gt;"hello from dev"&lt;/span&gt;,
&lt;span class="s2"&gt;"created_at"&lt;/span&gt;:&lt;span class="s2"&gt;"2026-10-02T05:48:52Z"&lt;/span&gt;&lt;span class="o"&gt;}]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Write, then read, against the local database. Only then did it publish.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Publish
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ snoozestack publish
Publishing "muse-demo" to production
  ok    Checking project        2 functions, 1 site
  ok    Planning schema         1 change against production
  ok    Uploading sites         "www": 1 uploaded
  ok    Building functions      2 functions bundled
  ok    Deploying release       release r3 is production — runtime healthy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One command. The schema migrated against the production database, the site uploaded, the functions bundled — all recorded as immutable release.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Verify it live
&lt;/h2&gt;

&lt;p&gt;The agent didn't trust the deploy output — it wrote rows to the production database and read them back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://muse-demo.snzzz.com/api/functions/v1/guestbook &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name":"Muse","message":"First signature, written by the AI that built this."}'&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;:true,&lt;span class="s2"&gt;"id"&lt;/span&gt;:&lt;span class="s2"&gt;"efba91fd-4baa-4956-b854-8989f46abde0"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://muse-demo.snzzz.com/api/functions/v1/guestbook
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"signatures"&lt;/span&gt;:[&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;:&lt;span class="s2"&gt;"efba91fd…"&lt;/span&gt;,&lt;span class="s2"&gt;"name"&lt;/span&gt;:&lt;span class="s2"&gt;"Muse"&lt;/span&gt;,
&lt;span class="s2"&gt;"message"&lt;/span&gt;:&lt;span class="s2"&gt;"First signature, written by the AI that built this."&lt;/span&gt;,
&lt;span class="s2"&gt;"created_at"&lt;/span&gt;:&lt;span class="s2"&gt;"2026-10-02T05:49:30Z"&lt;/span&gt;&lt;span class="o"&gt;}]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the site: &lt;code&gt;200&lt;/code&gt;. Go sign it yourself — &lt;a href="https://muse-demo.snzzz.com" rel="noopener noreferrer"&gt;https://muse-demo.snzzz.com&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some notes for improvements I can make to the platform.
&lt;/h2&gt;

&lt;p&gt;Here's what actually happened:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The email confirmation.&lt;/strong&gt; Signup needed a human to click a link. Agents can't have inboxes (yet) and for people skeptical of handing over their email account to AI Agents I need some other route of verification.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The schema needed a table.&lt;/strong&gt; The scaffold's &lt;code&gt;schema.mjs&lt;/code&gt; initializes with everything commented out, and publish refuses a schema with zero tables. Reasonable guardrail, slightly confusing error that could be improved.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The SDK isn't on npm.&lt;/strong&gt; &lt;code&gt;snoozestack-js&lt;/code&gt; installs from a version-pinned tarball on snoozestack.com. The agent found it in the docs in about a minute. I'll explore publishing to npm.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Function URLs differ locally vs. hosted.&lt;/strong&gt; Locally it's &lt;code&gt;localhost:8787/guestbook&lt;/code&gt;; in production it's &lt;code&gt;/api/functions/v1/guestbook&lt;/code&gt;. The docs explain why, and the agent adapted — but it's the kind of thing that should probably just work the same.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The site swallows function routes.&lt;/strong&gt; A primary site at &lt;code&gt;/&lt;/code&gt; intercepts paths before functions see them. Worth adding validation to prevent naming a function the same as a page.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of these stopped the agent. But most of the time was spent on the agent reading docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;I'll work on a more complex demo using the other features of SnoozeStack including user auth and custom domains.&lt;/p&gt;

&lt;h2&gt;
  
  
  What was Interesting
&lt;/h2&gt;

&lt;p&gt;The interesting thing isn't that Muse wrote a guestbook. It's the shape of the work: the agent operated entirely through four surfaces — committed files, the CLI, the docs, and curl.&lt;/p&gt;

&lt;p&gt;Muse was a great substitute to having a friend try out the platform. It's always difficult convincing people to test out your apps and Muse served as a great stand in for a potential customer.&lt;/p&gt;

&lt;p&gt;And if you're a developer with tons of small apps you've built for yourself and friends, give SnoozeStack a try for simple affordable project hosting.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with &lt;a href="https://snoozestack.com" rel="noopener noreferrer"&gt;SnoozeStack&lt;/a&gt; — run the backend locally, publish with one command. The demo app lives at &lt;a href="https://muse-demo.snzzz.com" rel="noopener noreferrer"&gt;muse-demo.snzzz.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>showdev</category>
      <category>backend</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
