<?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: Cruz_Smith</title>
    <description>The latest articles on DEV Community by Cruz_Smith (@cruz_smith).</description>
    <link>https://dev.to/cruz_smith</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%2F4076608%2F0e402d55-4093-446d-ba2d-f283e9287cfc.jpg</url>
      <title>DEV Community: Cruz_Smith</title>
      <link>https://dev.to/cruz_smith</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cruz_smith"/>
    <language>en</language>
    <item>
      <title>From Design Canvas to React: Build a Shader Hero with InspoAI Shades</title>
      <dc:creator>Cruz_Smith</dc:creator>
      <pubDate>Mon, 12 Oct 2026 12:09:10 +0000</pubDate>
      <link>https://dev.to/cruz_smith/from-design-canvas-to-react-build-a-shader-hero-with-inspoai-shades-2oh3</link>
      <guid>https://dev.to/cruz_smith/from-design-canvas-to-react-build-a-shader-hero-with-inspoai-shades-2oh3</guid>
      <description>&lt;p&gt;The designer wants a background that moves. The developer wants something that won’t eat the page’s performance budget. Both want the headline to stay readable.&lt;/p&gt;

&lt;p&gt;That’s the real challenge with animated hero sections. Getting pixels to move is only the beginning; making them belong on the page takes a little more care.&lt;/p&gt;

&lt;p&gt;This walkthrough uses &lt;a href="https://app.inspoai.io/shades" rel="noopener noreferrer"&gt;InspoAI Shades&lt;/a&gt; to explore a visual design, export a React component, and keep the surrounding UI accessible. Shades is part of &lt;a href="https://www.inspoai.io/" rel="noopener noreferrer"&gt;InspoAI&lt;/a&gt;. The workflow below is about the handoff from design to frontend code, rather than building a shader engine from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, decide what the background is doing
&lt;/h2&gt;

&lt;p&gt;Imagine a product page with one headline and one call to action. A slow gradient might give it atmosphere. A cursor ripple could make it feel responsive. Grain or dithering could give a clean composition a more editorial character.&lt;/p&gt;

&lt;p&gt;Pick one direction. If every layer is trying to be the interesting part, the headline usually loses.&lt;/p&gt;

&lt;p&gt;Shades lets you work with visual effects as layers. The editor screenshot below shows the effects library, a Mesh hero composition, and controls for the selected text layer.&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%2Fuwa2rdd7plxgzmyz5ffh.jpeg" 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%2Fuwa2rdd7plxgzmyz5ffh.jpeg" alt="InspoAI Shades editor showing a purple and blue Mesh hero shader background, the effects library on the left, and text and layer controls on the right." width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The live Shades editor, with effects on the left and layer controls on the right.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Remix a starter before building from zero
&lt;/h2&gt;

&lt;p&gt;For a first experiment, choose a starter, set the frame size, and change the colors before adding more effects. It is much easier to judge a design when you change one thing at a time.&lt;/p&gt;

&lt;p&gt;Here’s the God rays starter on the canvas. Notice that the device controls are part of the same workflow: the composition needs room for both the effect and the content.&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%2Fasznal2ye2xey1hyyqw3.jpeg" 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%2Fasznal2ye2xey1hyyqw3.jpeg" alt="God rays starter in InspoAI Shades alongside the starter library and device presets" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Start with a composition, then adjust it for the actual place it will appear.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A useful design pass looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choose the mood and frame size.&lt;/li&gt;
&lt;li&gt;Adjust the background colors and movement.&lt;/li&gt;
&lt;li&gt;Check where the brightest and busiest areas appear.&lt;/li&gt;
&lt;li&gt;Leave a quiet area behind the headline and button.&lt;/li&gt;
&lt;li&gt;Review a narrow mobile composition separately.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The text in the editor can help you compose the visual. For the website itself, keep the real headline and links in HTML. That gives you normal wrapping, selection, keyboard access, and text that remains available outside the canvas.&lt;/p&gt;
&lt;h2&gt;
  
  
  Export the background, then give it a home
&lt;/h2&gt;

&lt;p&gt;Use the React code export when the result needs to render live on a website. Shades also provides image and video exports, but a rendered video won’t preserve cursor interaction.&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%2Fypf3u9cv11o2e5uwh7db.jpeg" 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%2Fypf3u9cv11o2e5uwh7db.jpeg" alt="React code export for a God rays shader background in Shades" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The export panel includes the generated component and framework choices.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Save your exported component in a local file such as &lt;strong&gt;ShadesBackground.jsx&lt;/strong&gt;. Follow the dependency instructions in the export panel; the screenshot shows the &lt;strong&gt;shaders&lt;/strong&gt; package. Its &lt;a href="https://github.com/shader-effects-inc/shaders" rel="noopener noreferrer"&gt;official repository&lt;/a&gt; documents the supported framework integrations.&lt;/p&gt;

&lt;p&gt;Next comes the part that is easy to miss: the exported visual needs a container with a real size. Treat it as a decorative layer behind the hero copy.&lt;/p&gt;

&lt;p&gt;Here is an illustrative React wrapper. &lt;strong&gt;ShadesBackground&lt;/strong&gt; is your exported file, not a built-in React component. This example assumes a React app with a browser client; adapt the client boundary and imports for your framework.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;useEffect&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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="nx"&gt;ShadesBackground&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;./ShadesBackground&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./hero.css&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="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Hero&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;motionAllowed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setMotionAllowed&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="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;preference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;(prefers-reduced-motion: reduce)&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;update&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="nf"&gt;setMotionAllowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;preference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;preference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;update&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="nx"&gt;preference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;update&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&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;"hero"&lt;/span&gt; &lt;span class="na"&gt;aria-labelledby&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hero-title"&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;"hero__visual"&lt;/span&gt; &lt;span class="na"&gt;aria-hidden&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"true"&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;motionAllowed&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ShadesBackground&lt;/span&gt; &lt;span class="p"&gt;/&amp;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;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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hero__copy"&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;h1&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hero-title"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Make room for a better idea.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;A clear message, with a little atmosphere behind it.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&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;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/get-started"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Get started&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&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;section&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;
&lt;span class="nc"&gt;.hero&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;isolation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;32rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#141322&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.hero__visual&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;inset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;pointer-events&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.hero__visual&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.hero__copy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;42rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1.5rem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5vw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4rem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt; &lt;span class="m"&gt;19&lt;/span&gt; &lt;span class="m"&gt;34&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;75%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.hero__copy&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.75rem&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#141322&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.hero__copy&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:focus-visible&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;outline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#ffd166&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;outline-offset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&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;There are a few deliberate choices here.&lt;/p&gt;

&lt;p&gt;The solid background remains when motion is disabled or the visual is unavailable. The copy has its own backing so it doesn’t depend entirely on whatever color the shader happens to show. The effect is decorative, while the heading and link keep their normal HTML semantics.&lt;/p&gt;

&lt;p&gt;The motion preference starts disabled, then updates on the client. When reduced motion is requested, the exported component is not mounted. This goes further than hiding a running canvas with CSS. See &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion" rel="noopener noreferrer"&gt;MDN’s reduced-motion reference&lt;/a&gt; and &lt;a href="https://react.dev/reference/react/useEffect" rel="noopener noreferrer"&gt;React’s effect documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This wrapper intentionally uses &lt;strong&gt;pointer-events: none&lt;/strong&gt; so the visual won’t intercept clicks. For a cursor-reactive effect, check how the exported component receives pointer input and adapt the layering accordingly. Don’t remove that rule blindly and accidentally make the call to action unclickable.&lt;/p&gt;

&lt;h2&gt;
  
  
  A screenshot can’t tell you whether it’s ready to ship
&lt;/h2&gt;

&lt;p&gt;Before using the design in production, check it in the actual page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Readability:&lt;/strong&gt; does the headline stay clear across the whole animation?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Touch:&lt;/strong&gt; does the page still make sense without hover or a mouse?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keyboard:&lt;/strong&gt; can someone focus and activate the link normally?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced motion:&lt;/strong&gt; does changing the system preference leave a usable static hero?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Browser support:&lt;/strong&gt; does your fallback work when the graphics runtime is unavailable?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; what happens on a modest phone, not just your development laptop?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A browser API being present does not guarantee that a graphics adapter or device will initialize successfully. Inspect the exported runtime’s behavior and test failures rather than assuming support from one feature check.&lt;/p&gt;

&lt;p&gt;Also consider loading the effect only when needed and stopping offscreen animation where your runtime supports it. Those choices depend on your app and the exported component; they aren’t handled by the small wrapper above.&lt;/p&gt;

&lt;h2&gt;
  
  
  When code is more than you need
&lt;/h2&gt;

&lt;p&gt;For a social clip or launch announcement, a video export may be the better handoff. You avoid introducing a graphics runtime into a page that doesn’t need live interaction.&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%2Fo9z8jfgixwqjkasbzppn.jpeg" 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%2Fo9z8jfgixwqjkasbzppn.jpeg" alt="Shades video export showing duration, frame rate, and MP4 or WebM options" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Use video for a rendered animation; use code when you need a live effect.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For a blog cover, presentation, or static fallback, export a PNG or JPG instead. Choosing a still is often a design decision, not a compromise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Do I need to write GLSL?
&lt;/h3&gt;

&lt;p&gt;No. Shades lets you compose the visual with layers and controls. Integrating the code export still involves frontend work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use the same effect in Vue or Svelte?
&lt;/h3&gt;

&lt;p&gt;Shades provides Vue, Svelte, Solid, and JavaScript exports alongside React. Use the appropriate export rather than translating a React component by hand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does the exported background make the page accessible automatically?
&lt;/h3&gt;

&lt;p&gt;No. You still own text contrast, semantic content, keyboard access, reduced-motion behavior, and testing. The background is one layer of the page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is this wrapper a complete production integration?
&lt;/h3&gt;

&lt;p&gt;No. It illustrates layout and motion-preference handling around your exported component. You still need to verify the runtime, browser support, loading strategy, and performance in your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  The handoff should include more than a component
&lt;/h2&gt;

&lt;p&gt;The most useful thing a designer can pass to a developer is the intended behavior: where the copy sits, how much movement feels right, what the mobile version should look like, and what happens when animation is unavailable.&lt;/p&gt;

&lt;p&gt;Start with &lt;a href="https://app.inspoai.io/shades" rel="noopener noreferrer"&gt;Shades&lt;/a&gt;, or follow the &lt;a href="https://www.inspoai.io/blogs/how-to-use-shades-animated-background" rel="noopener noreferrer"&gt;Shades walkthrough&lt;/a&gt; for the editor steps. You can explore the rest of the workspace on the &lt;a href="https://www.inspoai.io/" rel="noopener noreferrer"&gt;InspoAI homepage&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What usually causes more work in your projects: getting the visual right, or getting it to behave inside the real page?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>design</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How we stopped our AI UI generator from producing the same screen every time</title>
      <dc:creator>Cruz_Smith</dc:creator>
      <pubDate>Mon, 14 Sep 2026 14:03:08 +0000</pubDate>
      <link>https://dev.to/cruz_smith/how-we-stopped-our-ai-ui-generator-from-producing-the-same-screen-every-time-3a97</link>
      <guid>https://dev.to/cruz_smith/how-we-stopped-our-ai-ui-generator-from-producing-the-same-screen-every-time-3a97</guid>
      <description>&lt;p&gt;Every prompt-to-UI tool generates the same purple gradient. Here is the retrieval architecture we built to fix it, and the two ugly repair layers nobody writes about.&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%2Fyl8mufime30vylmhdvhg.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%2Fyl8mufime30vylmhdvhg.png" alt=" " width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ask any AI tool to generate a dashboard and you get the same thing. Purple gradient header. Centered card. Three feature columns with rounded icons.&lt;/p&gt;

&lt;p&gt;Lovable does it. v0 does it. Bolt does it. Ours did it too, which is where this post starts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this happens&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A language model generating UI has no reference for what good product design looks like. It has seen billions of tokens of HTML and CSS and it returns the statistical center of that distribution. Average is not a bug in the output. Average is the output.&lt;/p&gt;

&lt;p&gt;You cannot prompt your way out of this. We tried. Longer system prompts, few-shot examples, explicit anti-patterns in the instructions. Every approach produced a marginally different flavour of the same screen, because we were still asking the model to invent a design from nothing.&lt;/p&gt;

&lt;p&gt;Fine-tuning was the obvious next move and we ruled it out for three reasons. Design trends move faster than a fine-tune cycle. The labelled dataset you would need does not exist. And the moment your training set ages, the model produces 2023 interfaces with total confidence. Retrieval updates the second you add a screenshot to the index. A fine-tune does not.&lt;/p&gt;

&lt;p&gt;So we changed the input instead of the model.&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%2Fzvu7ji7mhw9qz4r96tj7.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%2Fzvu7ji7mhw9qz4r96tj7.png" alt=" " width="800" height="841"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Intent understanding&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The raw prompt makes a bad retrieval query. "A plant identification app" and "onboarding screen for a plant app, camera-first, friendly" need different references. This stage expands the prompt into a structured brief: surface type, density, tone, likely components. It also decides what to skip — if design choices are already explicit, several downstream stages are unnecessary, which is the difference between a four-second response and a twelve-second one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Retrieval&lt;/strong&gt;&lt;br&gt;
Supabase with pgvector, queried by cosine distance:&lt;br&gt;
&lt;code&gt;create or replace function match_design_assets (&lt;br&gt;
  query_embedding vector(1536),&lt;br&gt;
  match_threshold float,&lt;br&gt;
  match_count int&lt;br&gt;
)&lt;br&gt;
returns table (id uuid, url text, metadata jsonb, similarity float)&lt;br&gt;
language sql stable&lt;br&gt;
as $$&lt;br&gt;
  select da.id, da.url, da.metadata,&lt;br&gt;
         1 - (da.embedding &amp;lt;=&amp;gt; query_embedding) as similarity&lt;br&gt;
  from design_assets da&lt;br&gt;
  where 1 - (da.embedding &amp;lt;=&amp;gt; query_embedding) &amp;gt; match_threshold&lt;br&gt;
  order by da.embedding &amp;lt;=&amp;gt; query_embedding&lt;br&gt;
  limit match_count;&lt;br&gt;
$$;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Screenshot retrieval and brand lookup are independent, so they run concurrently. Biggest latency win in the system:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const [references, brand] = await Promise.all([&lt;br&gt;
  matchDesignAssets(embedding, { threshold: 0.78, count: 8 }),&lt;br&gt;
  fetchBrandContext(intent.domain)&lt;br&gt;
]);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Vision pass&lt;/strong&gt;&lt;br&gt;
Retrieved screenshots go through a multimodal model that extracts what makes them work — spacing rhythm, type scale, where weight sits. Retrieval gives you relevant images; this turns them into constraints a text model can follow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The design contract&lt;/strong&gt;&lt;br&gt;
The stage most implementations skip, and the one that matters most. Before any JSX exists, we lock palette, spacing, type ramp and radius, and hand it to the generator as a hard constraint:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const contract = {&lt;br&gt;
  palette: { bg: '#FAF9F6', fg: '#1A1A1A', accent: '#E8623D' },&lt;br&gt;
  spacing: [4, 8, 12, 16, 24, 32, 48, 64],&lt;br&gt;
  radius: 'rounded-xl',&lt;br&gt;
  typeScale: { display: 'text-4xl', body: 'text-base' }&lt;br&gt;
};&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Without it the model drifts. It starts on your palette and three components later has invented a blue nobody asked for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Generation&lt;/strong&gt;&lt;br&gt;
React and Tailwind against the contract, then two repair layers.&lt;/p&gt;

&lt;p&gt;The two ugly parts&lt;/p&gt;

&lt;p&gt;Icon healing. The model hallucinated Lucide names constantly — , , . Each one is a build-breaking import, which in a live sandbox means a blank screen. So we mapped every real Lucide export and fuzzy-match every generated import:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const healIcon = (name) =&amp;gt; {&lt;br&gt;
  if (LUCIDE_EXPORTS.has(name)) return name;&lt;br&gt;
  return closestMatch(name, LUCIDE_EXPORTS) ?? 'Circle';&lt;br&gt;
};&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Not elegant. Killed an entire class of failure.&lt;/p&gt;

&lt;p&gt;Babel sanitization. Generated JSX fails to parse more than you'd expect: unclosed fragments, stray TS annotations in .jsx, surviving markdown fences. Every generation compiles in-process before reaching the preview. Parse failure triggers repair, repair failure triggers regeneration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What still doesn't work&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Multi-page drift. The first three screens hold the contract. By the fifth the spacing scale has quietly relaxed. Probably needs per-screen contract injection, not per-session.&lt;br&gt;
Novel surfaces. No analogue in 200k screens means weak matches, and output regresses to the mean this post opened by complaining about.&lt;br&gt;
Ranking. Pure cosine similarity. A screenshot can be semantically close and stylistically wrong, and I haven't found a better approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The source is public&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;github.com/inspoai-studio/inspoai-studio — PolyForm Noncommercial 1.0.0, which is source-available, not OSI open source. Fork it, modify it, use it for personal, academic or nonprofit work. Commercial use needs a separate licence.&lt;/p&gt;

&lt;p&gt;React 18 + Vite, Node/Express, Supabase with pgvector. One SQL file sets up schema, vector search and RLS. MCP server at /api/mcp/sse for Cursor and Claude Desktop.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git clone https://github.com/inspoai-studio/inspoai-studio.git&lt;br&gt;
cd inspoai-studio &amp;amp;&amp;amp; npm install&lt;br&gt;
cp frontend/.env.example frontend/.env&lt;br&gt;
cp backend/.env.example backend/.env&lt;br&gt;
npm run dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you fork it, tell me what you changed — especially if you have a better answer than cosine similarity for ranking.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>saas</category>
      <category>promptengineering</category>
      <category>ui</category>
    </item>
    <item>
      <title>DocSend vs Papermark vs SendNow: What’s the Best DocSend Alternative in 2026?</title>
      <dc:creator>Cruz_Smith</dc:creator>
      <pubDate>Fri, 04 Sep 2026 17:05:08 +0000</pubDate>
      <link>https://dev.to/cruz_smith/docsend-vs-papermark-vs-sendnow-whats-the-best-docsend-alternative-in-2026-4k15</link>
      <guid>https://dev.to/cruz_smith/docsend-vs-papermark-vs-sendnow-whats-the-best-docsend-alternative-in-2026-4k15</guid>
      <description>&lt;p&gt;If you want secure document sharing, viewer analytics, and a lightweight data room without enterprise complexity, SendNow is the strongest DocSend alternative for startups and deal-driven teams in 2026.&lt;/p&gt;

&lt;p&gt;DocSend is established.&lt;/p&gt;

&lt;p&gt;Papermark is developer-friendly and open source.&lt;/p&gt;

&lt;p&gt;But &lt;strong&gt;&lt;a href="https://sendnow.live/" rel="noopener noreferrer"&gt;SendNow&lt;/a&gt;&lt;/strong&gt; connects the entire workflow:&lt;/p&gt;

&lt;p&gt;Share → Track → Understand → Close.&lt;/p&gt;

&lt;p&gt;That is the important difference&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why are teams looking for DocSend alternatives?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sending a document is no longer the hard part.&lt;/p&gt;

&lt;p&gt;Google Drive can already do that.&lt;br&gt;
The real questions are:&lt;/p&gt;

&lt;p&gt;Who opened it?&lt;br&gt;
How long did they read?&lt;br&gt;
Which pages mattered?&lt;br&gt;
Did they return?&lt;br&gt;
Can I block downloads?&lt;br&gt;
Can I require an NDA?&lt;br&gt;
Can I turn several files into one secure deal room?&lt;/p&gt;

&lt;p&gt;This is where modern document-sharing tools become useful.&lt;/p&gt;

&lt;p&gt;And it is also where SendNow starts to separate itself from basic document tracking.&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%2Fell3elfi1wssfvd15njv.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%2Fell3elfi1wssfvd15njv.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DocSend: proven, but built around the traditional workflow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;DocSend helped popularize tracked document links.&lt;br&gt;
The workflow is simple:&lt;/p&gt;

&lt;p&gt;Share a document&lt;br&gt;
     ↓&lt;br&gt;
Recipient opens it&lt;br&gt;
     ↓&lt;br&gt;
Track engagement&lt;/p&gt;

&lt;p&gt;It remains a good choice if your team already uses DocSend and doesn't have a strong reason to switch.&lt;/p&gt;

&lt;p&gt;But that is also its biggest advantage:familiarity.&lt;/p&gt;

&lt;p&gt;For a modern startup starting from scratch, familiarity alone may not be enough.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Papermark’s “open-source advantage” is overrated&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Papermark loves to sell open source as the big differentiator.&lt;/p&gt;

&lt;p&gt;But here’s the problem: the basic product idea — upload, secure link, permissions, analytics — is no longer technically impressive. A startup can prototype that kind of workflow with Lovable or modern vibe-coding tools surprisingly fast.&lt;/p&gt;

&lt;p&gt;And once you want serious customization, you inherit the ugly part:&lt;/p&gt;

&lt;p&gt;security responsibility&lt;br&gt;
auth and permissions&lt;br&gt;
analytics reliability&lt;br&gt;
audit logs&lt;br&gt;
infrastructure&lt;br&gt;
compliance&lt;br&gt;
ongoing maintenance&lt;/p&gt;

&lt;p&gt;At that point, “open source” stops feeling like freedom and starts feeling like more software you now have to babysit.&lt;/p&gt;

&lt;p&gt;If you really want a deeply custom workflow, building your own focused version from scratch may make more sense than heavily modifying someone else’s codebase.&lt;/p&gt;

&lt;p&gt;Papermark gives you code.&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%2F3muul5k827ek0x7lcts2.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%2F3muul5k827ek0x7lcts2.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SendNow gives you the outcome: Share → Track → Understand → Close.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://sendnow.live" rel="noopener noreferrer"&gt;SendNow&lt;/a&gt;: built around what happens after you share&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sendnow.live/" rel="noopener noreferrer"&gt;SendNow&lt;/a&gt; doesn't stop at:&lt;/p&gt;

&lt;p&gt;Did they open my document?&lt;/p&gt;

&lt;p&gt;The workflow is:&lt;/p&gt;

&lt;p&gt;Share&lt;br&gt;
  ↓&lt;br&gt;
Track engagement&lt;br&gt;
  ↓&lt;br&gt;
Understand interest&lt;br&gt;
  ↓&lt;br&gt;
Move the deal forward&lt;/p&gt;

&lt;p&gt;A founder might start by sharing one pitch deck.&lt;br&gt;
Then the investor becomes interested.&lt;/p&gt;

&lt;p&gt;Suddenly they need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pitch Deck&lt;/li&gt;
&lt;li&gt;Financial Model&lt;/li&gt;
&lt;li&gt;Cap Table&lt;/li&gt;
&lt;li&gt;Legal Documents&lt;/li&gt;
&lt;li&gt;Market Research&lt;/li&gt;
&lt;li&gt;Product Documents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At that point, you're no longer sharing a PDF.&lt;/p&gt;

&lt;p&gt;You're running a deal process.&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%2Fn55k5l5e7t3t6qkh30yl.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%2Fn55k5l5e7t3t6qkh30yl.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SendNow lets that workflow expand into a Microsite-style lightweight data room instead of forcing the team to jump immediately into a complicated enterprise VDR&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%2Fxem3da17i8v3j0y6s15e.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%2Fxem3da17i8v3j0y6s15e.png" alt=" " width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The feature lists may look similar.&lt;/p&gt;

&lt;p&gt;The philosophy isn't.&lt;/p&gt;

&lt;p&gt;DocSend asks:&lt;br&gt;
Did they view it?&lt;/p&gt;

&lt;p&gt;Papermark asks:&lt;br&gt;
How much control do you want?(with high pricing)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sendnow.live/" rel="noopener noreferrer"&gt;SendNow&lt;/a&gt; asks:&lt;br&gt;
What should you do next?&lt;br&gt;
That is a much more useful question for founders and revenue teams.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The real advantage: intent&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine two investors.&lt;br&gt;
Investor A&lt;br&gt;
Opened once&lt;br&gt;
38 seconds&lt;br&gt;
Never returned&lt;br&gt;
Investor B&lt;br&gt;
Opened four times&lt;br&gt;
11 minutes&lt;br&gt;
Returned next day&lt;br&gt;
Spent most time on financials&lt;/p&gt;

&lt;p&gt;Both opened your pitch deck.&lt;br&gt;
But only one is showing serious intent.&lt;/p&gt;

&lt;p&gt;That's why the future of document sharing isn't just analytics.&lt;br&gt;
It's document intelligence.&lt;br&gt;
The value is understanding what viewer behavior actually means.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why SendNow makes sense for startups&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Startups often fall into an awkward middle ground.&lt;br&gt;
Google Drive is too basic.&lt;/p&gt;

&lt;p&gt;Traditional enterprise VDRs can be too complicated.&lt;/p&gt;

&lt;p&gt;They need something between:&lt;/p&gt;

&lt;p&gt;Google Drive&lt;br&gt;
   ↓&lt;br&gt;
   ?&lt;br&gt;
   ↓&lt;br&gt;
Enterprise VDR&lt;/p&gt;

&lt;p&gt;That middle layer is where SendNow's secure document sharing + analytics + Microsites make the most sense.&lt;/p&gt;

&lt;p&gt;You can start with one document.&lt;/p&gt;

&lt;p&gt;And when the deal becomes serious, expand into a structured room.&lt;/p&gt;

&lt;p&gt;No unnecessary complexity.&lt;/p&gt;

&lt;p&gt;So which one should you choose?&lt;br&gt;
Choose DocSend if&lt;/p&gt;

&lt;p&gt;Your company already uses it and changing workflows isn't worth the migration.&lt;/p&gt;

&lt;p&gt;Choose Papermark if&lt;br&gt;
Open source, self-hosting and developer control are major requirements(limited only that you can easly vibe coded).&lt;/p&gt;

&lt;p&gt;Choose SendNow if&lt;br&gt;
You're a startup, founder, adviser, sales team or deal team that wants:&lt;br&gt;
secure sharing + engagement analytics + lightweight data rooms in one workflow.&lt;/p&gt;

&lt;p&gt;For that use case, SendNow is the strongest option of the three.&lt;/p&gt;

&lt;p&gt;The bigger shift&lt;br&gt;
Document sharing has gone through three generations.&lt;/p&gt;

&lt;p&gt;Generation 1&lt;br&gt;
File storage&lt;br&gt;
"Where is my file?"&lt;br&gt;
     ↓&lt;br&gt;
Generation 2&lt;br&gt;
Document tracking&lt;br&gt;
"Did they read it?"&lt;br&gt;
     ↓&lt;br&gt;
Generation 3&lt;br&gt;
Document intelligence&lt;br&gt;
"What does their behavior mean?"&lt;/p&gt;

&lt;p&gt;Google Drive solved storage.&lt;br&gt;
DocSend helped popularize tracking.&lt;br&gt;
The next generation is about understanding intent and acting on it.&lt;br&gt;
That's exactly where SendNow is positioning itself.&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%2F0ehttq85u32v2gcbyi5v.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%2F0ehttq85u32v2gcbyi5v.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FAQ&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;What is the best DocSend alternative in 2026?&lt;/strong&gt;&lt;br&gt;
For startups and deal-driven teams, SendNow is one of the strongest DocSend alternatives because it combines secure document sharing, viewer analytics and lightweight Microsite/data-room workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is SendNow better than DocSend?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It depends on the workflow. DocSend is strong for established teams already using its ecosystem. SendNow can be a better fit for startups that want a simpler path from sharing one document to managing a complete fundraising, sales or due-diligence workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is SendNow better than Papermark?&lt;/strong&gt;&lt;br&gt;
Papermark is particularly strong for teams prioritizing open source and developer control. SendNow is better suited to teams prioritizing a SaaS-first document-sharing and deal workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the best DocSend alternative for startups?&lt;/strong&gt;&lt;br&gt;
SendNow is particularly well suited to startups because it combines document tracking, security and Microsite-style multi-document sharing without requiring a traditional enterprise VDR.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can SendNow be used as a virtual data room?&lt;/strong&gt;&lt;br&gt;
Yes. SendNow's Microsite workflow can be used to organize and securely share multiple documents for fundraising, sales and other deal-related workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can SendNow track investor engagement?&lt;/strong&gt;&lt;br&gt;
SendNow is designed around viewer engagement analytics, helping teams understand how recipients interact with shared documents and identify stronger engagement signals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the difference between DocSend and SendNow?&lt;/strong&gt;&lt;br&gt;
DocSend is primarily associated with established document tracking workflows. SendNow combines tracked sharing with a broader progression from document → engagement → Microsite → deal workflow.&lt;/p&gt;

</description>
      <category>documentation</category>
      <category>sideprojects</category>
      <category>programming</category>
      <category>saas</category>
    </item>
    <item>
      <title>What Actually Happens When You Share a Sensitive Document With a Public Link?</title>
      <dc:creator>Cruz_Smith</dc:creator>
      <pubDate>Thu, 13 Aug 2026 17:04:48 +0000</pubDate>
      <link>https://dev.to/cruz_smith/what-actually-happens-when-you-share-a-sensitive-document-with-a-public-link-5f48</link>
      <guid>https://dev.to/cruz_smith/what-actually-happens-when-you-share-a-sensitive-document-with-a-public-link-5f48</guid>
      <description>&lt;p&gt;You upload a PDF.&lt;/p&gt;

&lt;p&gt;You click Share.&lt;/p&gt;

&lt;p&gt;You copy a URL.&lt;/p&gt;

&lt;p&gt;You send it to someone.&lt;/p&gt;

&lt;p&gt;From your perspective, the job is done.&lt;br&gt;
From a security perspective, you've just created a new problem:&lt;br&gt;
What happens after the link leaves your hands?&lt;/p&gt;

&lt;p&gt;A normal file-sharing link often answers only one question:&lt;br&gt;
Can someone open this file?&lt;br&gt;
For sensitive documents, that's nowhere near enough.&lt;/p&gt;

&lt;p&gt;You also need to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who opened it?&lt;/li&gt;
&lt;li&gt;When did they open it?&lt;/li&gt;
&lt;li&gt;Which pages did they read?&lt;/li&gt;
&lt;li&gt;Can they download it?&lt;/li&gt;
&lt;li&gt;Can they forward the link?&lt;/li&gt;
&lt;li&gt;Can you revoke access?&lt;/li&gt;
&lt;li&gt;Can the link expire?&lt;/li&gt;
&lt;li&gt;Can you prove who accessed it later?&lt;/li&gt;
&lt;li&gt;What happens if the recipient screenshots it?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the difference between file sharing and secure document sharing.&lt;/p&gt;

&lt;p&gt;The problem with a normal document link&lt;br&gt;
Consider this workflow:&lt;br&gt;
                     You&lt;br&gt;
                      │&lt;br&gt;
                      ↓&lt;br&gt;
                 Upload PDF&lt;br&gt;
                      │&lt;br&gt;
                      ↓&lt;br&gt;
                  Share URL&lt;br&gt;
                      │&lt;br&gt;
                      ↓&lt;br&gt;
               Recipient opens&lt;br&gt;
                      │&lt;br&gt;
                      ↓&lt;br&gt;
                   ...?&lt;/p&gt;

&lt;p&gt;The last part is where most basic sharing tools become a black box.&lt;br&gt;
You don't necessarily know what happened after the click.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Maybe they opened the document.&lt;/li&gt;
&lt;li&gt;Maybe they downloaded it.&lt;/li&gt;
&lt;li&gt;Maybe they forwarded it.&lt;/li&gt;
&lt;li&gt;Maybe an automated security scanner opened the link.&lt;/li&gt;
&lt;li&gt;Maybe they opened page 1 and immediately left.&lt;/li&gt;
&lt;li&gt;Maybe they spent 15 minutes reading the financial model.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From a business perspective, these are completely different events.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A secure document-sharing system has layers&lt;/strong&gt;&lt;br&gt;
A useful way to think about secure document sharing is as a stack.&lt;/p&gt;

&lt;p&gt;┌──────────────────────────────┐&lt;br&gt;
│        Analytics             │&lt;br&gt;
│ Who / when / what / where    │&lt;br&gt;
├──────────────────────────────┤&lt;br&gt;
│        Audit trail           │&lt;br&gt;
│ Every access event recorded  │&lt;br&gt;
├──────────────────────────────┤&lt;br&gt;
│        Access control        │&lt;br&gt;
│ Email / password / NDA       │&lt;br&gt;
├──────────────────────────────┤&lt;br&gt;
│        Link controls         │&lt;br&gt;
│ Expiry / revoke / view limit │&lt;br&gt;
├──────────────────────────────┤&lt;br&gt;
│        Content controls      │&lt;br&gt;
│ Download / screenshot / WM   │&lt;br&gt;
├──────────────────────────────┤&lt;br&gt;
│        Encryption            │&lt;br&gt;
│ TLS + AES-256                │&lt;br&gt;
└──────────────────────────────┘&lt;/p&gt;

&lt;p&gt;New DEV content formula&lt;/p&gt;

&lt;p&gt;400–800 words max for most posts.&lt;/p&gt;

&lt;p&gt;Structure:&lt;/p&gt;

&lt;p&gt;Strong technical hook&lt;br&gt;
        ↓&lt;br&gt;
Interesting problem&lt;br&gt;
        ↓&lt;br&gt;
2–4 technical facts&lt;br&gt;
        ↓&lt;br&gt;
Small example / diagram&lt;br&gt;
        ↓&lt;br&gt;
SendNow connection&lt;br&gt;
        ↓&lt;br&gt;
One takeaway&lt;/p&gt;

&lt;p&gt;Not 10 sections and 20 bullet points.&lt;br&gt;
Example: much better version&lt;br&gt;
Your PDF Link Is More Powerful Than You Think&lt;/p&gt;

&lt;p&gt;You send someone a PDF link.&lt;/p&gt;

&lt;p&gt;They open it.&lt;/p&gt;

&lt;p&gt;You see:&lt;/p&gt;

&lt;p&gt;1 view&lt;/p&gt;

&lt;p&gt;But what actually happened?&lt;/p&gt;

&lt;p&gt;Did they:&lt;/p&gt;

&lt;p&gt;open page 1 and leave?&lt;br&gt;
read the entire document?&lt;br&gt;
download it?&lt;br&gt;
forward the link?&lt;br&gt;
come back three times?&lt;br&gt;
get blocked by an email security scanner?&lt;/p&gt;

&lt;p&gt;A simple URL doesn't tell you much.&lt;/p&gt;

&lt;p&gt;The interesting part&lt;/p&gt;

&lt;p&gt;A modern document-sharing system can turn:&lt;/p&gt;

&lt;p&gt;PDF → URL&lt;/p&gt;

&lt;p&gt;into:&lt;/p&gt;

&lt;p&gt;PDF → identity → access → events → analytics&lt;/p&gt;

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

&lt;p&gt;Share&lt;br&gt;
  ↓&lt;br&gt;
Verify viewer&lt;br&gt;
  ↓&lt;br&gt;
Open document&lt;br&gt;
  ↓&lt;br&gt;
Track pages&lt;br&gt;
  ↓&lt;br&gt;
Detect engagement&lt;br&gt;
  ↓&lt;br&gt;
Control access&lt;/p&gt;

&lt;p&gt;That's where document sharing starts looking less like file storage and more like an event-driven application.&lt;/p&gt;

&lt;p&gt;One technical detail people often miss&lt;/p&gt;

&lt;p&gt;Not every "document view" is a human.&lt;/p&gt;

&lt;p&gt;Corporate email security tools can automatically open links to check them.&lt;/p&gt;

&lt;p&gt;So this:&lt;br&gt;
Link opened = 1&lt;br&gt;
doesn't necessarily mean:&lt;br&gt;
Human read document = 1&lt;/p&gt;

&lt;p&gt;That's why serious document analytics need to distinguish automated scans from real engagement.&lt;/p&gt;

&lt;p&gt;And access doesn't have to be permanent&lt;/p&gt;

&lt;p&gt;A secure document link can have rules like:&lt;/p&gt;

&lt;p&gt;Expires → 24 hours&lt;br&gt;
Download → Disabled&lt;br&gt;
Viewer → Verified email&lt;br&gt;
NDA → Required&lt;br&gt;
Access → Revocable&lt;/p&gt;

&lt;p&gt;Now the URL isn't just a location.&lt;/p&gt;

&lt;p&gt;It's a controlled access point.&lt;br&gt;
That's the interesting shift happening in modern document sharing.&lt;/p&gt;

&lt;p&gt;Tools like SendNow are building around this idea: share the document, but keep visibility and control after the link is sent.&lt;/p&gt;

&lt;p&gt;The takeaway:&lt;br&gt;
A file tells you what was shared.&lt;br&gt;
A controlled document link tells you what happened next.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sendnow.live" rel="noopener noreferrer"&gt;Explore SendNow&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>saas</category>
      <category>opensource</category>
      <category>docsend</category>
    </item>
  </channel>
</rss>
